julien-c HF staff commited on
Commit
1bdef4c
1 Parent(s): 2f61c11

one final try

Browse files
.gitattributes CHANGED
@@ -38,7 +38,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
38
  *.pdfp filter=lfs diff=lfs merge=lfs -text
39
  *.jpeg filter=lfs diff=lfs merge=lfs -text
40
  *.gif filter=lfs diff=lfs merge=lfs -text
41
- *.js filter=lfs diff=lfs merge=lfs -text
42
  *.png filter=lfs diff=lfs merge=lfs -text
43
  *.bcmap filter=lfs diff=lfs merge=lfs -text
44
  /assets/player/pdfjs/web/cmaps/LICENSE filter=lfs diff=lfs merge=lfs -text
 
38
  *.pdfp filter=lfs diff=lfs merge=lfs -text
39
  *.jpeg filter=lfs diff=lfs merge=lfs -text
40
  *.gif filter=lfs diff=lfs merge=lfs -text
 
41
  *.png filter=lfs diff=lfs merge=lfs -text
42
  *.bcmap filter=lfs diff=lfs merge=lfs -text
43
  /assets/player/pdfjs/web/cmaps/LICENSE filter=lfs diff=lfs merge=lfs -text
assets/player/AnimationManager.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:caa5f82edd64ad130e8bd367c53083d36866b2db3edf177b7d28e071b93b4367
3
- size 746
 
1
+ var kKeyframeRule=window.CSSRule.WEBKIT_KEYFRAMES_RULE;var AnimationManager=Class.create({initialize:function(){var a=document.createElement("style");a.type="text/css";a.media="screen";document.getElementsByTagName("head")[0].appendChild(a);this.styleSheet=document.styleSheets[document.styleSheets.length-1];this.createdAnimations=new Object()},createAnimation:function(a){this.styleSheet.insertRule(kKeyframesPropertyName+" "+a+" {}",0);return this.styleSheet.cssRules[0]},deleteAllAnimations:function(){while(this.styleSheet.cssRules.length>0){this.styleSheet.deleteRule(0)}this.createdAnimations=new Object()},markAnimationsCreated:function(a){this.createdAnimations[a]=true},animationsCreated:function(a){return this.createdAnimations[a]}});
 
 
assets/player/DebuggingSupport.js CHANGED
@@ -1,3 +1,276 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:d73e75a5f730735a02a52b4eff417056a0b5da3abe6fefc335fd653cff5022b7
3
- size 9466
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * DebuggingSupport.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Responsibility: Tungwei Cheng
6
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ // Set this to "false" to disable ALL debugging logic
10
+ var gDebug = false;
11
+
12
+ // Set this to "false" to disable debug messages when running on the iPhone or iPad
13
+ var gDebugOnMobile = false;
14
+
15
+ // Globals:
16
+ // ===============================================================
17
+
18
+ var gNumDebugMessagesSent = 0;
19
+ var gNumDebugMessagesQueued = 0;
20
+ var gDebugMessageQueue = new Array();
21
+ var gDebugMessageRequest = null;
22
+ var gDebugLastClassName = "";
23
+ var gDebugLastMethodName = "";
24
+
25
+ // Enable these constants to simulate various conditions/errors:
26
+
27
+ var gDebugSimulateSlowTextureDownload = false;
28
+ var gDebugSimulateTextureLoadFailure = false;
29
+ var gDebugSimulateScriptDownloadFailure = false;
30
+
31
+ // Constants:
32
+ // ===============================================================
33
+
34
+ var kDebugFunction = "function";
35
+ var kDebugSurpressMessage = "!NoOp_!NoOp";
36
+
37
+ //----------------------------------------------------------------------
38
+
39
+ var kDebugSetupShowController = kDebugFunction + "_" + "setupShowController";
40
+
41
+ //----------------------------------------------------------------------
42
+
43
+ var kDebugShowController = "!ShowController";
44
+
45
+ var kDebugShowController_AdvanceToNextBuild = kDebugShowController + "_" + "!advanceToNextBuild";
46
+ var kDebugShowController_AdvanceToNextSlide = kDebugShowController + "_" + "!advanceToNextSlide";
47
+ var kDebugShowController_DoIdleProcessing = kDebugShowController + "_" + "!doIdleProcessing";
48
+ var kDebugShowController_GoBackToPreviousBuild = kDebugShowController + "_" + "!goBackToPreviousBuild";
49
+ var kDebugShowController_GoBackToPreviousSlide = kDebugShowController + "_" + "!goBackToPreviousSlide";
50
+ var kDebugShowController_HandleScriptDidDownloadEvent = kDebugShowController + "_" + "!handleScriptDidDownloadEvent";
51
+ var kDebugShowController_HandleScriptDidNotDownloadEvent = kDebugShowController + "_" + "!handleScriptDidNotDownloadEvent";
52
+ var kDebugShowController_JumpToScene = kDebugShowController + "_" + "!jumpToScene";
53
+ var kDebugShowController_OnKeyPress = kDebugShowController + "_" + "!onKeyPress";
54
+
55
+ //----------------------------------------------------------------------
56
+
57
+ var kDebugTouchController = "!TouchController";
58
+
59
+ var kDebugTouchController_HandleGestureEndEvent = kDebugTouchController + "_" + "!handleGestureEndEvent";
60
+ var kDebugTouchController_HandleGestureStartEvent = kDebugTouchController + "_" + "!handleGestureStartEvent";
61
+ var kDebugTouchController_HandleTouchCancelEvent = kDebugTouchController + "_" + "!handleTouchCancelEvent";
62
+ var kDebugTouchController_HandleTouchCancelEvent = kDebugTouchController + "_" + "!handleTouchMoveEvent";
63
+ var kDebugTouchController_HandleTouchEndEvent = kDebugTouchController + "_" + "!handleTouchEndEvent";
64
+ var kDebugTouchController_HandleTouchStartEvent = kDebugTouchController + "_" + "!handleTouchStartEvent";
65
+ var kDebugTouchController_Initialize = kDebugTouchController + "_" + "!initialize";
66
+ var kDebugTouchController_IsTouchWithinTrackArea = kDebugTouchController + "_" + "!isTouchWithinTrackArea";
67
+ var kDebugTouchController_SetTrackArea = kDebugTouchController + "_" + "!setTrackArea";
68
+
69
+ //----------------------------------------------------------------------
70
+
71
+ var kDebugScriptMangaer = "!ScriptManager";
72
+
73
+ var kDebugScriptMangaer_DownloadScript = kDebugScriptMangaer + "_" + "!downloadScript";
74
+
75
+ //----------------------------------------------------------------------
76
+
77
+ var kDebugTimer = "DebugTimer";
78
+
79
+ var kDebugTimer_AdvanceToNextBuild = kDebugTimer + "_" + "!advanceToNextBuild";
80
+ var kDebugTimer_CreateAnimationsForScene = kDebugTimer + "_" + "!createAnimationsForScene";
81
+ var kDebugTimer_ApplyAnimationsForScene = kDebugTimer + "_" + "!applyAnimationsForScene";
82
+ var kDebugTimer_PreProcessSceneAnimations = kDebugTimer + "_" + "!preProcessSceneAnimations";
83
+ var kDebugTimer_AdvanceToNextBuild_to_ApplyAnimations = kDebugTimer + "_" + "!preProcessSceneAnimations_to_ApplyAnimations";
84
+ var kDebugTimer_JumpToScene = kDebugTimer + "_" + "!jumpToScene";
85
+ var kDebugTimer_DisplayScene = kDebugTimer + "_" + "!displayScene";
86
+
87
+ // Functions:
88
+ // ===============================================================
89
+
90
+ function debugWarning(sender, messageText) {
91
+ if (gDebug === false) {
92
+ return;
93
+ }
94
+ debugSendMessage(sender, "WARNING: " + messageText, true);
95
+ }
96
+
97
+ function debugMessageAlways(sender, messageText) {
98
+ debugSendMessage(sender, messageText, true);
99
+ }
100
+
101
+ function debugMessage(sender, messageText) {
102
+ if (gDebug == false) {
103
+ return;
104
+ }
105
+
106
+ if ((gDevice == kDeviceMobile) && (gDebugOnMobile == false)) {
107
+ return;
108
+ }
109
+
110
+ debugSendMessage(sender, messageText, false);
111
+ }
112
+
113
+ function debugSendMessage(sender, messageText, always) {
114
+ var indexOfUnderscore = sender.indexOf("_");
115
+ var className = sender.substring(0, indexOfUnderscore);
116
+ var methodName = sender.substring(indexOfUnderscore + 1);
117
+ var suppress = false;
118
+
119
+ if (className[0] == "!") {
120
+ className = className.substring(1);
121
+ suppress = true;
122
+ }
123
+
124
+ if (methodName[0] == "!") {
125
+ methodName = methodName.substring(1);
126
+ suppress = true;
127
+ }
128
+
129
+ if (methodName[0] == "+") {
130
+ methodName = methodName.substring(1);
131
+ always = true;
132
+ }
133
+
134
+ if ((suppress == true) && (always == false)) {
135
+ return;
136
+ }
137
+
138
+ var prefix = "";
139
+
140
+ if (messageText == null) {
141
+ messageText = "";
142
+ }
143
+
144
+ if (messageText[0] != "-" || className != gDebugLastClassName || methodName != gDebugLastMethodName) {
145
+ if (className == kDebugTimer) {
146
+ prefix = sender + ": ";
147
+ }
148
+ else if (className == kDebugFunction) {
149
+ prefix = methodName + "() ";
150
+ }
151
+ else {
152
+ prefix = className + "." + methodName + "() ";
153
+ }
154
+ } else {
155
+ prefix = "";
156
+ }
157
+
158
+ gDebugLastClassName = className;
159
+ gDebugLastMethodName = methodName;
160
+
161
+ if (gDevice == kDeviceMobile) {
162
+ gNumDebugMessagesSent++;
163
+
164
+ var formattedMessageText = escape(gNumDebugMessagesSent + ": " + prefix + messageText);
165
+
166
+ gDebugMessageQueue[gNumDebugMessagesQueued] = formattedMessageText;
167
+ gNumDebugMessagesQueued++;
168
+
169
+ if (gNumDebugMessagesQueued == 1) {
170
+ debugCheckMessageQueue();
171
+ }
172
+ } else {
173
+ if (window.console) {
174
+ window.console.log( prefix + messageText );
175
+ }
176
+ }
177
+ }
178
+
179
+ function debugSendNextMessageInQueue() {
180
+ var formattedMessageText = gDebugMessageQueue[0];
181
+
182
+ gNumDebugMessagesQueued--;
183
+ gDebugMessageQueue.splice(0,1);
184
+
185
+ var messageUrl = '/debugMessage.rhtml?message="' + formattedMessageText + '"';
186
+
187
+ new Ajax.Request( messageUrl, {
188
+ method: "get",
189
+ onSuccess: function(transport) {debugMessageWasSent(transport);},
190
+ onFailure: function(transport) {debugMessageWasNotSent(transport);}
191
+ });
192
+ }
193
+
194
+ function debugMessageWasSent(transport) {
195
+ debugCheckMessageQueue();
196
+ }
197
+
198
+ function debugMessageWasNotSent(transport) {
199
+ debugCheckMessageQueue();
200
+ }
201
+
202
+ function debugCheckMessageQueue() {
203
+ if (gNumDebugMessagesQueued > 0) {
204
+ setTimeout(debugSendNextMessageInQueue, 10);
205
+ }
206
+ }
207
+
208
+ var DebugTimer = Class.create({
209
+ initialize: function(timerId) {
210
+ var indexOfUnderscore = timerId.indexOf("_");
211
+ var timerName = timerId.substring( indexOfUnderscore + 1 );
212
+
213
+ if (timerName[0] != "!") {
214
+ this.id = timerId;
215
+ this.startTime = new Date();
216
+
217
+ debugMessageAlways(timerId, "Start");
218
+ } else {
219
+ this.startTime = null;
220
+ }
221
+ },
222
+
223
+ stop: function() {
224
+ if (this.startTime != null) {
225
+ var endTime = new Date();
226
+ var elapsedTime = endTime - this.startTime;
227
+
228
+ debugMessageAlways(this.id , "Stop - Elapsed Time: " + elapsedTime);
229
+ }
230
+ }
231
+ });
232
+
233
+ function debugStopTimer(timer) {
234
+ if (timer) {
235
+ timer.stop();
236
+ }
237
+ }
238
+
239
+ var debugDomDumpLineNumber = 0;
240
+
241
+ function debugDumpDomFrom(rootObject, context) {
242
+ var kDebugDumpDomFrom = kDebugFunction + "_" + "debugDumpDomFrom";
243
+
244
+ debugDomDumpLineNumber = 0;
245
+ debugMessageAlways(kDebugDumpDomFrom, "------------------ S T A R T O F D O M D U M P --- Context: " + context);
246
+ debugRecursivelyDumpDomFrom(rootObject, "");
247
+ debugMessageAlways(kDebugDumpDomFrom, "------------------ E N D O F D O M D U M P");
248
+ }
249
+
250
+ function debugRecursivelyDumpDomFrom(object, indentPadding) {
251
+ var kDebugRecursivelyDumpDomFrom = kDebugFunction + "_" + "recursivelyDumpDomFrom";
252
+ var objectId = object.id;
253
+ var objectTag = object.nodeName.toLowerCase();
254
+
255
+ if (objectTag == "#text") {
256
+ return;
257
+ }
258
+
259
+ debugMessageAlways( kDebugRecursivelyDumpDomFrom, "-" + (debugDomDumpLineNumber++) + indentPadding + "<" + objectTag + " id='" + objectId + "'>");
260
+
261
+ var iChild;
262
+
263
+ for (iChild = 0; iChild < object.childNodes.length; iChild++) {
264
+ var child = object.childNodes[iChild];
265
+ recursivelyDumpDomFrom(child, indentPadding + " ");
266
+ }
267
+
268
+ if (objectTag == "img") {
269
+ return;
270
+ }
271
+
272
+ debugMessageAlways(kDebugRecursivelyDumpDomFrom, "-" + (debugDomDumpLineNumber++) + indentPadding + "</" + objectTag + ">");
273
+ }
274
+
275
+
276
+
assets/player/DisplayManager.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:fc42593d07bb05c4a045fc584bba10ded7b3092debfd256ecf1780f8929bd6fb
3
- size 14869
 
1
+ var kStageSizeDidChangeEvent="DisplayManager:StageSizeDidChangeEvent";var kTimeoutValueForCursor=1000;var kMobilePortraitModeHorizontalMargin=8;var kMobilePortraitModeTopMargin=47;var kMobilePortraitModeVerticalCenterLine=161;var kMobilePortraitModeMaxStageHeight=228;var kMobilePortraitMaxStageHeight=0;var kMobilePortraitMaxStageWidth=0;var kMobileLandscapeModeVerticalMargin=7;var kMobileLandscapeModeHorizontallMargin=15;var kBottomButtonHeight=50;var kNavigationArrowSize=27;var kNavigationAreaHeight=kNavigationArrowSize;var kHelpAreaHeight=16;var kMobilePortraitModeVerticalCenterLineToNavigationAreaGap=148;var kStageToNavigationAreaGap=31;var kNavigationAreaToHelpAreaGap=52;var kHelpAreaToBottomGap=12;var kMobilePortraitModeNavigationAreaSideMargin=32;var kMobilePortraitModeHelpAreaSideMargin=16;var kMobileLandscapeModeMinSideSpacerWidth=kNavigationArrowSize+10;var kPadPortraitModeHorizontalMargin=8;var kPadPortraitModeMaxStageHeight=540;var kPadPortraitModeVerticalCenterLine=400;var kPadLandscapeModeHorizontallMargin=15;var kPadLandscapeModeVerticalMargin=7;var DisplayManager=Class.create({initialize:function(){document.observe(kShowSizeDidChangeEvent,this.handleShowSizeDidChangeEvent.bind(this));document.observe(kOrientationChangedEvent,this.handleOrientationDidChangeEvent.bind(this));this.body=document.getElementById("body");this.stageArea=document.getElementById("stageArea");this.stage=document.getElementById("stage");this.hyperlinkPlane=document.getElementById("hyperlinkPlane");this.waitingIndicator=document.getElementById("waitingIndicator");this.helpText=document.getElementById("helpText");this.previousButton=document.getElementById("previousButton");this.nextButton=document.getElementById("nextButton");this.slideCounter=document.getElementById("slideCounter");this.waitingIndicatorTimeout=null;this.orientation=kOrientationUnknown;this.showWidth=0;this.showHeight=0;this.stageAreaWidth=0;this.stageAreaHeight=0;this.stageAreaTop=0;this.stageAreaLeft=0;this.usableDisplayWidth=0;this.usableDisplayHeight=0;this.inLaunchMode=true;this.initialAddressBarScrollPerformed=false;this.updateUsableDisplayArea();this.positionWaitingIndicator();this.showWaitingIndicator();this.hyperlinksOnly=false;this.showStatisticsDisplay=gIpad&&getUrlParameter("statistics")==="1";this.hasCacheEverGoneOverPixelLimit=false;this.hhasStageEverGoneOverPixelLimit=false;this.cacheHighWaterMark=0;this.stageHighWaterMark=0;if(gMode===kModeMobile){this.stageArea.style.backgroundColor="black";this.helpText.innerHTML=kTapOrSwipeToAdvance}else{Event.observe(this.body,"mousemove",this.handleMouseMove.bind(this));this.lastMouseX=-1;this.lastMouseY=-1;this.cursorTimeout=null;this.setTimeoutForCursor()}},setHyperlinksOnlyMode:function(){this.hyperlinksOnly=true;this.setPreviousButtonEnabled(false);this.setNextButtonEnabled(false);this.helpText.style.display="none"},handleMouseMove:function(a){a=a||window.event;var b=Math.abs(this.lastMouseX-a.clientX)+Math.abs(this.lastMouseY-a.clientY);if(b>10){if(this.cursorIsShowing===false){this.showCursor()}else{if(!this.navigatorIsShowing){this.setTimeoutForCursor()}}}else{if(!this.navigatorIsShowing){this.setTimeoutForCursor()}}this.lastMouseX=a.clientX;this.lastMouseY=a.clientY},updateSlideNumber:function(b,a){var d="";var c=null;if(gMode!=kModeDesktop){d=kSlideLabel+" "+b+"/"+a;c=this.slideCounter}if(c!=null){c.innerHTML=d}},handleShowSizeDidChangeEvent:function(a){this.showWidth=a.memo.width;this.showHeight=a.memo.height;this.layoutDisplay()},handleOrientationDidChangeEvent:function(a){this.orientation=a.memo.orientation;clearTimeout(this.resizeTimer);this.resizeTimer=setTimeout(this.handleOrientationDidChangeEvent_partTwo.bind(this),300)},handleOrientationDidChangeEvent_partTwo:function(){this.layoutDisplay();if(this.inLaunchMode===false){this.showApplicableControls()}},showCursor:function(){if(this.inLaunchMode){return}this.body.style.cursor="default";this.cursorIsShowing=true;this.setTimeoutForCursor()},hideCursor:function(){this.body.style.cursor="none";this.cursorIsShowing=false},setTimeoutForCursor:function(){if(this.cursorTimeout){clearTimeout(this.cursorTimeout)}this.cursorTimeout=setTimeout(this.handleTimeoutForCursor.bind(this),kTimeoutValueForCursor)},clearTimeoutForCursor:function(){if(this.cursorTimeout){clearTimeout(this.cursorTimeout)}},handleTimeoutForCursor:function(){this.hideCursor()},updateUsableDisplayArea:function(){if(gMode===kModeMobile){var a=gIpad;if(this.orientation===kOrientationLandscape){this.usableDisplayWidth=(a?kiPadDeviceHeight:kiPhoneDeviceHeight);this.usableDisplayHeight=(a?kiPadDeviceWidth:kiPhoneDeviceWidth)-kiPhoneStatusBarHeight-kiPhoneLandscapeButtonBarHeight-(a?(kiPadAddressBarHeight+kiPadBookmarksBarHeight):0)}else{this.usableDisplayWidth=(a?kiPadDeviceWidth:kiPhoneDeviceWidth);this.usableDisplayHeight=(a?kiPadDeviceHeight:kiPhoneDeviceHeight)-kiPhoneStatusBarHeight-kiPhonePortraitButtonBarHeight-(a?kiPadBookmarksBarHeight+10:0)}}else{this.usableDisplayWidth=window.innerWidth;this.usableDisplayHeight=window.innerHeight}},clearLaunchMode:function(){this.inLaunchMode=false;var a=this;runInNextEventLoop(this.showAll.bind(this))},positionWaitingIndicator:function(){var c=110;var b=32;var a;var d;if(gMode===kModeMobile&&this.orientation===kOrientationUnknown){a=1000;d=1000}else{if(gMode===kModeMobile&&this.orientation===kOrientationPortrait){a=(this.usableDisplayWidth-c)/2;if(gIpad===false){d=kMobilePortraitModeVerticalCenterLine-(c/2)}else{d=kPadPortraitModeVerticalCenterLine-(c/2)}}else{a=(this.usableDisplayWidth-c)/2;d=(this.usableDisplayHeight-c)/2}}setElementPosition(this.waitingIndicator,d,a,c,c)},hideWaitingIndicator:function(){this.waitingIndicator.style.display="none"},showWaitingIndicator:function(){this.waitingIndicator.style.display="block"},convertDisplayCoOrdsToShowCoOrds:function(d){var b={};var c=this.stageAreaLeft+this.stageAreaWidth;var a=this.stageAreaTop+this.stageAreaHeight;if((d.pointX<this.stageAreaLeft)||(d.pointX>c)||(d.pointY<this.stageAreaTop)||(d.pointY>a)){b.pointX=-1;b.pointY=-1}else{b.pointX=((d.pointX-this.stageAreaLeft)/this.stageAreaWidth)*this.showWidth;b.pointY=((d.pointY-this.stageAreaTop)/this.stageAreaHeight)*this.showHeight}return b},layoutDisplay:function(){this.updateUsableDisplayArea();var q;var k;if(gMode===kModeDesktop){q=this.usableDisplayWidth;k=this.usableDisplayHeight;if(!gShowController.isFullscreen){if(q>this.showWidth||k>k){q=this.showWidth;k=k}}}else{if(gIpad===false){if(this.orientation===kOrientationPortrait){q=this.usableDisplayWidth-2*kMobilePortraitModeHorizontalMargin;k=kMobilePortraitModeMaxStageHeight}else{q=this.usableDisplayWidth-2*kMobileLandscapeModeHorizontallMargin;k=this.usableDisplayHeight-2*kMobileLandscapeModeVerticalMargin}}else{if(this.orientation===kOrientationPortrait){q=this.usableDisplayWidth-2*kPadPortraitModeHorizontalMargin;k=kPadPortraitModeMaxStageHeight}else{q=this.usableDisplayWidth-2*kPadLandscapeModeHorizontallMargin;k=this.usableDisplayHeight-2*kPadLandscapeModeVerticalMargin}}}var o=scaleSizeWithinSize(this.showWidth,this.showHeight,q,k);this.stageAreaWidth=o.width;this.stageAreaHeight=o.height;this.stageAreaLeft=(this.usableDisplayWidth-this.stageAreaWidth)/2;if(gMode===kModeDesktop){this.stageAreaTop=(k-this.stageAreaHeight)/2}else{if(this.orientation===kOrientationPortrait){if(gIpad===false){this.stageAreaTop=Math.max(10,kMobilePortraitModeVerticalCenterLine-(this.stageAreaHeight/2))}else{this.stageAreaTop=Math.max(10,kPadPortraitModeVerticalCenterLine-(this.stageAreaHeight/2))}}else{this.stageAreaTop=(this.usableDisplayHeight-this.stageAreaHeight)/2}}setElementPosition(this.stageArea,this.stageAreaTop,this.stageAreaLeft,this.stageAreaWidth,this.stageAreaHeight);var e=-1;var b=-1;var p=-1;var h=-1;var a=null;if(gMode===kModeDesktop){a=false;e=-1;b=-1;p=-1;h=-1}else{a=true;p=0;h=0;if(gIpad){b=kiPadDeviceHeight}else{b=kiPhoneDeviceHeight}e=b}if(p!=-1&&h!=-1&&e!=-1&&b!=-1){var s=document.getElementById("background");s.style.top=p;s.style.left=h;s.style.width=e;s.style.height=b;if(a===true){s.style.visibility="visible"}}var g={x:0,y:0,width:this.usableDisplayWidth,height:this.stageAreaTop};var d={x:0,y:this.stageAreaTop+this.stageAreaHeight,width:this.usableDisplayWidth,height:this.usableDisplayHeight-this.stageAreaTop-this.stageAreaHeight};var n={x:0,y:this.stageAreaTop,width:this.stageAreaLeft,height:this.stageAreaHeight};var i={x:this.stageAreaLeft+this.stageAreaWidth,y:this.stageAreaTop,width:this.usableDisplayWidth-this.stageAreaWidth-n.width,height:this.stageAreaHeight};var l=document.getElementById("statisticsDisplay");if(this.showStatisticsDisplay&&gIpad&&this.orientation===kOrientationPortrait){setElementPosition(l,d.y+70,0,this.usableDisplayWidth,d.height-105);l.style.visibility="visible"}if(gMode!=kModeDesktop){if(this.orientation===kOrientationPortrait){var m=kNavigationArrowSize+2*kMobilePortraitModeNavigationAreaSideMargin;var f=kNavigationArrowSize+2*kStageToNavigationAreaGap;var r=this.usableDisplayWidth-2*m;var c=d.y+7;setElementPosition(this.previousButton,c,0,m,f);setElementPosition(this.slideCounter,c+kStageToNavigationAreaGap,m,r,f);setElementPosition(this.nextButton,c,m+r-5,m,f);setElementPosition(this.helpText,d.y+d.height-kHelpAreaToBottomGap-kHelpAreaHeight,0,this.usableDisplayWidth,kHelpAreaHeight);setElementPosition(this.infoPanelIcon,this.usableDisplayHeight-kInfoPanelButtonHeight,this.usableDisplayWidth-kInfoPanelButtonWidth-5,kInfoPanelButtonWidth,kInfoPanelButtonHeight)}else{var j={x:0,y:0,width:0,height:0};if(n.width>kMobileLandscapeModeMinSideSpacerWidth){setElementRect(this.previousButton,n);setElementRect(this.nextButton,i)}else{setElementRect(this.previousButton,j);setElementRect(this.nextButton,j)}setElementRect(this.slideCounter,j);setElementRect(this.helpText,j);setElementRect(this.infoPanelIcon,j)}}this.positionWaitingIndicator();this.hideAddressBar();document.fire(kStageSizeDidChangeEvent,{left:this.stageAreaLeft,top:this.stageAreaTop,width:this.stageAreaWidth,height:this.stageAreaHeight})},showApplicableControls:function(){if(this.inLaunchMode===true){hideElement(this.previousButton);hideElement(this.nextButton);hideElement(this.slideCounter);hideElement(this.helpText);hideElement(this.infoPanelIcon)}else{if(gMode===kModeDesktop){hideElement(this.previousButton);hideElement(this.nextButton);hideElement(this.slideCounter);hideElement(this.helpText);hideElement(this.infoPanelIcon)}else{if(this.orientation===kOrientationPortrait){showElement(this.previousButton);showElement(this.nextButton);showElement(this.slideCounter);showElement(this.helpText);showElement(this.infoPanelIcon)}else{hideElement(this.slideCounter);hideElement(this.helpText);hideElement(this.infoPanelIcon);if(this.stageAreaLeft>kMobileLandscapeModeMinSideSpacerWidth){showElement(this.previousButton);showElement(this.nextButton)}else{hideElement(this.previousButton);hideElement(this.nextButton)}}}}this.hideAddressBar()},showAll:function(){this.hideWaitingIndicator();setTimeout(this.showAll_partTwo.bind(this))},showAll_partTwo:function(){if(gDevice===kDeviceMobile){window.scrollTo(0,1);setTimeout(this.showAll_partThree.bind(this))}else{this.showAll_partThree()}},showAll_partThree:function(){if(this.inLaunchMode===false){this.showApplicableControls()}showElement(this.stageArea);var a=navigator.userAgent.match(/Windows/);if(a){if(gShowController.delegate.triggerReflow){gShowController.delegate.triggerReflow()}}showElement(this.hyperlinkPlane);if(gMode===kModeMobile){showElement(this.infoPanelIcon)}},setPreviousButtonEnabled:function(a){if(this.hyperlinksOnly){return}if(gMode!=kModeDesktop){if(a){this.previousButton.setAttribute("class","previousButtonEnabled")}else{this.previousButton.setAttribute("class","previousButtonDisabled")}}},setNextButtonEnabled:function(a){if(this.hyperlinksOnly){return}if(gMode!=kModeDesktop){if(a){this.nextButton.setAttribute("class","nextButtonEnabled")}else{this.nextButton.setAttribute("class","nextButtonDisabled")}}},hideAddressBar:function(){if(this.inLaunchMode){return}if(gDevice===kDeviceMobile){var a=this.initialAddressBarScrollPerformed?0:kHideAddressBarDelay;setTimeout("window.scrollTo(0, 1);",a);this.initialAddressBarScrollPerformed=true}},updateStatisticsDisplay:function(){if(this.showStatisticsDisplay===false){return}var k=document.getElementById("statisticsDisplay");var j=gShowController.textureManager.getCacheStatistics();var a=gShowController.scriptManager.degradeStatistics;var h=gShowController.stageManager.debugGetStageStatistics();var d=gShowController.textureManager.numLoadFailures;var c=gShowController.textureManager.numOutstandingLoadRequests;var i=1024*1024;var b=gSafeMaxPixelCount/i;b=Math.floor(b*100)/100;j.numPixels/=i;h.numPixels/=i;j.numPixels=Math.floor(j.numPixels*100)/100;h.numPixels=Math.floor(h.numPixels*100)/100;var e=false;var g=false;if(j.numPixels>b){e=true;this.hasCacheEverGoneOverPixelLimit=true}if(h.numPixels>b){g=true;this.hasStageEverGoneOverPixelLimit=true}if(j.numPixels>this.cacheHighWaterMark){this.cacheHighWaterMark=j.numPixels}if(h.numPixels>this.stageHighWaterMark){this.stageHighWaterMark=h.numPixels}var f="<div style='position: absolute; left: 0px;'><b>Cache Statistics:</b><br>- Scenes: <b>"+j.numScenes+"</b><br>- Textures: <b>"+j.numTextures+"</b><br>- Pixels: <b>"+j.numPixels+" MP</b><br>- Peak Pixels: <b>"+this.cacheHighWaterMark+" MP</b><br>%nbsp<br><b>Limits:</b><br>- Max Pixels: <b>"+b+" MP</b><br></div><div style='position: absolute; left: 175px;'><b>Scene Statistics:</b><br>- Scene Index: <b>"+gShowController.currentSceneIndex+"</b><br>- Textures: <b>"+h.numTextures+"</b><br>- Total Pixels: <b>"+h.numPixels+" MP</b><br>- Peak Pixels: <b>"+this.stageHighWaterMark+" MP</b><br><b>Texture Loader:</b><br>- Num Load Requests: <b>"+(c>0?("<span style='color:yellow;'>"+c+"</span>"):"0")+"</b><br>- Num Load Failures: <b>"+(d>0?("<span style='color:red;'>"+d+"</span>"):"0")+"</b><br></div><div style='position: absolute; left: 350px;'><b>Degrade Statistics:</b><br>- Scenes w/Degrades: <b>"+a.numDegradedSlides+"</b><br>- Total Textures Degraded: <b>"+a.numDegradedTextures+"</b><br>- Max Textures/Scene: <b>"+a.maxNumDegradedTexturesPerSlide+"</b><br>- Textures in Current: <b>"+(h.numDegraded>0?("<span style='color:yellow;'>"+h.numDegraded+"</span>"):"0")+"</b><br></div><div style='position: absolute; left: 550px;'><b>Summary:</b><br>- Cache: <br>- Over Pixel Limit Now: <b>"+(e?"<span style='color:red;'>YES</span>":"NO")+"</b><br>- Ever Over Pixel Limit: <b>"+(this.hasCacheEverGoneOverPixelLimit?"<span style='color:red;'>YES</span>":"NO")+"</b><br>- Stage: <br>- Over Pixel Limit Now: <b>"+(g?"<span style='color:red;'>YES</span>":"NO")+"</b><br>- Ever Over Pixel Limit: <b>"+(this.hasStageEverGoneOverPixelLimit?"<span style='color:red;'>YES</span>":"NO")+"</b><br></div>";k.innerHTML=f}});
 
 
assets/player/HelpPlacardController.js CHANGED
@@ -1,3 +1,194 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:8be916926e9e8058e4f2b4059a85b4dbaf40b94b2948951b9b820b53aec9c790
3
- size 6730
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * HelpPlacardController.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var HelpPlacardController = Class.create({
10
+ initialize: function(domNode) {
11
+ //root node for the slide number control
12
+ this.domNode = domNode;
13
+ this.width = 822;
14
+ this.height = 603;
15
+
16
+ var itemList = [
17
+ {key: "&nbsp;", text: kHelpPlacardNavigationTitle, header:true},
18
+ {key: "return/enter &nbsp; space &nbsp; &#8594 &nbsp; &#8595 &nbsp; page down", text: kHelpPlacardAdvanceToNextBuild},
19
+ {key: "[ &nbsp; shift - page up &nbsp; shift - &#8592", text: kHelpPlacardGoBackToPreviousBuild},
20
+ {key: "] &nbsp; shift - &#8594", text: kHelpPlacardAdvanceAndSkipBuild},
21
+ {key: "shift - page down &nbsp; shift - &#8595 &nbsp; + &nbsp; =", text: kHelpPlacardAdvanceToNextSlide},
22
+ {key: "&#8592 &nbsp; &#8593 &nbsp; - &nbsp; shift - &#8593", text: kHelpPlacardGoBackToPreviousSlide},
23
+ {key: "home", text: kHelpPlacardGoToFirstSlide},
24
+ {key: "end", text: kHelpPlacardGoToLastSlide},
25
+ {key: "slide number + return/enter", text: kHelpPlacardGoToSpecificSlide},
26
+ {key: "&nbsp;", text: kHelpPlacardOtherTitle, header: true},
27
+ {key: "? &nbsp; /", text: kHelpPlacardShowOrHideKeyboardShortcuts},
28
+ {key: "s", text: kHelpPlacardShowOrHideTheCurrentSlideNumber},
29
+ {key: "esc &nbsp; q", text: kHelpPlacardQuitPresentationMode}
30
+ ];
31
+
32
+ this.helpPlacardTitleBar = new HelpPlacardTitleBar();
33
+ this.helpPlacardContentPanel = new HelpPlacardContentPanel(itemList);
34
+ this.helpPlacardFooter = new HelpPlacardFooter();
35
+
36
+ this.domNode.appendChild(this.helpPlacardTitleBar.domNode);
37
+ this.domNode.appendChild(this.helpPlacardContentPanel.domNode);
38
+ this.domNode.appendChild(this.helpPlacardFooter.domNode);
39
+
40
+ this.isShowing = false;
41
+ },
42
+
43
+ handleClickEvent: function(event) {
44
+ event = event || window.event;
45
+ var target = event.target || event.srcElement;
46
+
47
+ // stop event from propagating up
48
+ if (this.isShowing) {
49
+ if (browserPrefix === "ms") {
50
+ event.cancelBubble = true;
51
+ } else {
52
+ event.stopPropagation();
53
+ }
54
+ }
55
+
56
+ this.hide();
57
+ },
58
+
59
+ setPosition: function(left, top) {
60
+ this.domNode.style.left = left + "px";
61
+ this.domNode.style.top = top + "px"
62
+ },
63
+
64
+ show: function() {
65
+ this.isShowing = true;
66
+ this.domNode.style.display = "block";
67
+ this.domNode.style.opacity = 1;
68
+ },
69
+
70
+ hide: function() {
71
+ this.isShowing = false;
72
+ this.domNode.style.display = "none";
73
+ this.domNode.style.opacity = 0;
74
+ },
75
+
76
+ registerDragEvents: function() {
77
+ this.drag = this.dragging.bindAsEventListener(this);
78
+ this.dragStop = this.stopDragging.bindAsEventListener(this);
79
+
80
+ Event.observe(this.domNode, "mousedown", this.startDragging.bindAsEventListener(this));
81
+ },
82
+
83
+ startDragging: function(event) {
84
+ this.startX = Event.pointerX(event);
85
+ this.startY = Event.pointerY(event);
86
+
87
+ this.left = parseInt(this.domNode.style.left);
88
+ this.top = parseInt(this.domNode.style.top);
89
+
90
+ Event.observe(document, "mousemove", this.drag);
91
+ Event.observe(this.domNode, "mouseup", this.dragStop);
92
+ },
93
+
94
+ dragging: function(event) {
95
+ var x = Event.pointerX(event);
96
+ var y = Event.pointerY(event);
97
+
98
+ this.domNode.style.left = (x - this.startX + this.left) + "px";
99
+ this.domNode.style.top = (y - this.startY + this.top) + "px";
100
+
101
+ Event.stop(event);
102
+ },
103
+
104
+ stopDragging: function(event) {
105
+ Event.stopObserving(document, "mousemove", this.drag);
106
+ Event.stopObserving(this.domNode, "mouseup", this.dragStop);
107
+
108
+ Event.stop(event);
109
+ }
110
+ });
111
+
112
+ var HelpPlacardTitleBar = Class.create({
113
+ initialize: function() {
114
+ this.domNode = document.createElement("div");
115
+ this.domNode.setAttribute("class", "helpPlacardTitleBar");
116
+
117
+ this.closeButton = document.createElement("div");
118
+ this.closeButton.setAttribute("class", "helpPlacardCloseButton");
119
+
120
+ this.title = document.createElement("div");
121
+ this.title.setAttribute("class", "helpPlacardTitle");
122
+ this.title.innerHTML = kHelpPlacardMainTitle;
123
+
124
+ this.domNode.appendChild(this.closeButton);
125
+ this.domNode.appendChild(this.title);
126
+ }
127
+ });
128
+
129
+ var HelpPlacardContentPanel = Class.create({
130
+ initialize: function(itemList) {
131
+ this.domNode = document.createElement("div");
132
+ this.domNode.setAttribute("class", "helpPlacardContentPanel");
133
+
134
+ for (var i = 0, length = itemList.length; i < length; i++) {
135
+ var item = itemList[i];
136
+ var div = document.createElement("div");
137
+ var leftDiv, rightDiv;
138
+
139
+ if (item.header) {
140
+ div.setAttribute("class", "helpPlacardHeader");
141
+
142
+ leftDiv = document.createElement("div");
143
+ leftDiv.setAttribute("class", "helpPlacardLeftHeaderItem");
144
+ leftDiv.innerHTML = item.text;
145
+
146
+ div.appendChild(leftDiv);
147
+ }
148
+ else {
149
+ div.setAttribute("class", "helpPlacardItem");
150
+
151
+ leftDiv = document.createElement("div");
152
+ leftDiv.setAttribute("class", "helpPlacardRightItem");
153
+ leftDiv.innerHTML = item.key;
154
+
155
+ rightDiv = document.createElement("div");
156
+ rightDiv.setAttribute("class", "helpPlacardLeftItem");
157
+ rightDiv.innerHTML = item.text;
158
+
159
+ div.appendChild(leftDiv);
160
+ div.appendChild(rightDiv);
161
+ }
162
+
163
+ this.domNode.appendChild(div);
164
+ }
165
+ }
166
+ });
167
+
168
+ var HelpPlacardFooter = Class.create({
169
+ initialize: function() {
170
+ this.domNode = document.createElement("div");
171
+ this.domNode.setAttribute("class", "helpPlacardFooter");
172
+
173
+ var div = document.createElement("div");
174
+ div.innerHTML = "Acknowledgements";
175
+ div.setAttribute("class", "helpPlacardAcknowledgementsButton");
176
+
177
+ Event.observe(div, "click", this.handleClickEvent.bind(this));
178
+
179
+ this.domNode.appendChild(div);
180
+ },
181
+
182
+ handleClickEvent: function(event) {
183
+ event = event || window.event;
184
+
185
+ // stop event from propagating up
186
+ if (browserPrefix === "ms") {
187
+ event.cancelBubble = true;
188
+ } else {
189
+ event.stopPropagation();
190
+ }
191
+
192
+ window.open("Acknowledgements.pdf", "_Acknowledgements");
193
+ }
194
+ });
assets/player/KPFObjects.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:6c33531bbaa192876ad04fc2c35cbccd9bdff583af65debf7d4c39af79dba2ff
3
- size 58322
 
1
+ var kpfLayerCounter=0;var eventOverallDuration=0;var KPFPlaybackController=Class.create({initialize:function(b,a){this.domNode=a;this.kpfEvent=null},destroy:function(){this.removeEvent();this.domNode=null},removeEvent:function(){if(this.kpfEvent){this.kpfEvent.destroy();delete this.kpfEvent;this.kpfEvent=null;while(this.domNode.childNodes.length>0){this.domNode.removeChild(this.domNode.childNodes[0])}}},renderEvent:function(a){this.removeEvent();this.kpfEvent=a;this.kpfEvent.renderEvent(this.domNode)},renderEffects:function(){var a=this.kpfEvent.renderEffects(this.kpfEvent.event.effects);return a},animateEffects:function(a){this.kpfEvent.animateEffects(a)},eventOverallEndTime:function(){return this.kpfEvent.eventOverallEndTime}});var KPFEvent=Class.create({initialize:function(a){this.slideId=a.slideId;this.slideIndex=a.slideIndex;this.sceneIndex=a.sceneIndex;this.animationSupported=a.animationSupported;this.event=a.event;this.baseLayer={};this.effects=[];this.cssRenderer={};this.glRenderer={};this.canvasIdFromObjectIdLookup={};this.eventOverallEndTime=0;this.overallEndTimeInternal()},destroy:function(){this.baseLayer.destroy();this.cssRenderer.destroy();for(var a=0,b=this.effects.length;a<b;a++){this.effects[a].destroy()}delete this.baseLayer;delete this.cssRenderer;delete this.effects;delete this.event;this.slideId=null;this.slideIndex=null;this.sceneIndex=null;this.animationSupported=null;this.eventOverallEndTime=null},addAnimationsToIdenticalLayer:function(c,f){if(c.animations&&c.animations.length>0){for(var b=0,e=c.animations.length;b<e;b++){f.animations.push(c.animations[b])}}if(c.layers&&c.layers.length>0){for(var a=0,d=c.layers.length;a<d;a++){this.addAnimationsToIdenticalLayer(c.layers[a],f.layers[a])}}},processEffects:function(a){var d=[];for(var h=0;h<a.length;h++){var m=a[h];if(m.type==="actionBuild"){var f=false;var l;for(var g=0,b=d.length;g<b;g++){if(d[g].type==="actionBuild"&&d[g].objectID===m.objectID){l=g;f=true;break}}if(f){this.addAnimationsToIdenticalLayer(m.baseLayer,d[l].baseLayer);if(m.beginTime<d[l].beginTime){d[l].beginTime=m.beginTime}if(m.beginTime+m.duration>d[l].beginTime+d[l].duration){d[l].duration=m.beginTime+m.duration}for(var e=0,c=m.effects.length;e<c;e++){d[l].effects.push(m.effects[e])}if(d[l].names==null){d[l].names=[]}d[l].names.push(m.name)}else{d.push(m)}}else{d.push(m)}}for(var h=0,b=d.length;h<b;h++){d[h].effects=this.processEffects(d[h].effects)}return d},renderEffects:function(c){var o=[];for(var h=0,f=c.length;h<f;h++){var m=new KPFEffect(c[h],this.animationSupported);var k=false;var b=m.objectID;this.cssRenderer.initRendererFlags(m);if(m.baseLayer==null){this.renderAudioOnlyEffect(m)}else{if(m.name==="renderMovie"){this.renderMovie(this.baseLayer,m)}else{if(m.type==="actionBuild"&&!m.isEmphasisBuild){for(var g=0,q=this.effects.length;g<q;g++){if(this.effects[g].objectID===b){if(this.effects[g].type==="actionBuild"||this.effects[g].name==="renderMovie"){k=true}else{k=false}}}}if(this.baseLayer.objectID===b){var l=new KPFLayer(m.baseLayer,{animationSupported:this.animationSupported,name:m.name,type:m.type,objectID:b});var n="layer"+this.baseLayer.layerId;var p=document.getElementById(n);var a=p.parentNode;var r=document.createElement("div");r.setAttribute("id","layer"+l.layerId);this.baseLayer=l;m.kpfLayer=l;if(useWebGL&&kSupportedWebGLEffects.indexOf(m.name)!==-1){var e=this.canvasId;var d;if(e){d=document.getElementById(e)}else{e=this.canvasId=b+"-canvas";d=this.createCanvasElement(e);a.appendChild(d)}m.nodeToSwapId=n;m.canvasId=e}else{this.cssRenderer.layer=l;this.cssRenderer.domNode=r;this.cssRenderer.draw(a);a.removeChild(p)}}else{this.renderEffect(this.baseLayer,m,k)}}}this.effects.push(m);o.push(m)}return o},renderMovie:function(c,m){var h;for(var j=0,f=c.layers.length;j<f;j++){var d=m.objectID;var b=m.name;var p=m.type;var g=m.movie;if(c.layers[j].objectID===d){var l=new KPFLayer(m.baseLayer,{animationSupported:this.animationSupported,name:b,type:p,objectID:d,movie:g},c.bounds.offset);var o="layer"+c.layers[j].layerId;var n="layer"+c.layers[j].layerId;var q=document.getElementById(n);if(!q){continue}var a=q.parentNode;m.kpfLayer=l;var e=this.canvasIdFromObjectIdLookup[d];if(e){var k=this.glRenderer[e];if(k){k.removeProgram(d)}}c.layers[j]=l;var r=this.cssRenderer.createNodes(a,c,l);a.replaceChild(r,q);h=true}else{h=this.renderMovie(c.layers[j],m)}if(h){break}}return h},renderEffect:function(E,C,k){var D;for(var z=0,j=E.layers.length;z<j;z++){var x=C.objectID;var G=C.name;var h=C.type;var v=C.movie;if(E.layers[z].objectID===x){var F=new KPFLayer(C.baseLayer,{animationSupported:this.animationSupported,name:G,type:h,objectID:x,movie:v},E.bounds.offset);var u="layer"+E.layers[z].layerId;var a="layer"+E.layers[z].layerId;var l=document.getElementById(a);if(!l){continue}var q=l.parentNode;C.kpfLayer=F;if(useWebGL&&kSupportedWebGLEffects.indexOf(G)!==-1){var B=this.canvasId;var f;if(B){f=document.getElementById(B);f.style.opacity=1}else{B=this.canvasId=x+"-canvas";f=this.createCanvasElement(B);q.appendChild(f)}this.canvasIdFromObjectIdLookup[x]=B;C.nodeToSwapId=a;C.canvasId=B}else{var B=this.canvasIdFromObjectIdLookup[x];if(B){var y=this.glRenderer[B];if(y){y.removeProgram(x)}}if(!k){E.layers[z]=F;var b=this.cssRenderer.createNodes(q,E,F);q.replaceChild(b,l)}else{var c=C.objectID+"-video";var A=gShowController.movieCache&&gShowController.movieCache[c];if(C.name==="apple:action-scale"&&!A){var g=document.getElementById(l.childNodes[0].id+"-contents");var w=this.cssRenderer.createNodes(q,E,F);var p=w.childNodes[0].id;var o=document.getElementById(p+"-contents-from");var t=document.getElementById(p+"-contents-to");if(o&&t){var r=E.bounds;var e=r.width;var m=r.height;var s=l.childNodes[0].id;var d=document.createElement("div");d.id=s+"-contents-to";this.setStyle(d,"0px","0px",e+"px",m+"px",kPositionAbsolutePropertyValue,null,null);d.appendChild(t.childNodes[0]);g.appendChild(d);setElementProperty(d,"opacity",0);var n=document.createElement("div");n.id=s+"-contents-from";this.setStyle(n,"0px","0px",e+"px",m+"px",kPositionAbsolutePropertyValue,null,null);n.appendChild(o.childNodes[0]);g.appendChild(n)}else{w.parentNode.removeChild(w)}}C.currentKPFLayer=E.layers[z]}}D=true}else{D=this.renderEffect(E.layers[z],C,k)}if(D){break}}return D},renderEvent:function(a){var b={animationSupported:this.animationSupported};if(this.event.effects&&this.event.effects.length===1){b.name=this.event.effects[0].name;b.type=this.event.effects[0].type;b.objectID=this.event.effects[0].objectID}this.baseLayer=new KPFLayer(this.event.baseLayer,b);this.cssRenderer=new KPFCssRenderer(this.baseLayer,this.sceneIndex,this.animationSupported,this.effects);this.cssRenderer.draw(a)},renderAudioOnlyEffect:function(e){if(e.name!="renderMovie"){return}var b=e.movie;if(!b.isAudioOnly){return}if(gShowController.audioCache==null){gShowController.audioCache={}}var a=b.asset+"-audio";var d=gShowController.audioCache[a];if(d==null){var c=gShowController.textureManager.urlForAsset(b.asset,this.slideId);d=new Audio(c);if(b){if(b.loopMode&&b.loopMode==="looping"){d.loop=true}if(b.volume){d.volume=b.volume}}gShowController.audioCache[a]=d}d.play()},animateEffects:function(e){for(var b=0,c=e.length;b<c;b++){var a=e[b];this.animateEffect(a)}for(var f in this.glRenderer){var d=this.glRenderer[f];d.animate();d.animationStarted=true}},animateEffect:function(c){var f=c.canvasId;var g=c.nodeToSwapId;if(f){var b=document.getElementById(f);var e={canvasId:f,canvas:b,nodeToSwapId:g,textureAssets:gShowController.textureManager.slideCache[this.slideIndex].textureAssets,effect:c,overallEndTime:this.eventOverallEndTime};var d=this.glRenderer[f];if(!d){d=new KNWebGLRenderer(e);this.glRenderer[f]=d}var a=c.beginTime*1000;if(c.type==="transition"){a=0}setTimeout(this.animateEffectWillBegin.bind(this,e),a)}else{this.cssRenderer.animate(c)}if(c.effects.length>0){setTimeout(this.handleEffectDidComplete.bind(this,c),(c.beginTime+c.duration)*1000)}},animateEffectWillBegin:function(e){var d=e.canvasId;var b=e.effect;var c=this.glRenderer[d];c.draw(b);if(!c.animationStarted){c.animate();c.animationStarted=true}var a=document.getElementById(e.nodeToSwapId);if(!a){return}if(b.type==="transition"){a.parentNode.removeChild(a)}else{a.style.opacity=0}},handleEffectDidComplete:function(c){var e=this.renderEffects(c.effects);for(var b=0,d=e.length;b<d;b++){var a=e[b];this.animateEffect(a)}},overallEndTime:function(){return this.eventOverallEndTime},overallEndTimeInternal:function(){for(var a=0,d=this.event.effects.length;a<d;a++){var c=0;var b=this.event.effects[a];this.calculateOverallEndTime(c,b)}},calculateOverallEndTime:function(e,c){var b=e+c.beginTime+c.duration;if(b>this.eventOverallEndTime){this.eventOverallEndTime=b}for(var a=0,d=c.effects.length;a<d;a++){this.calculateOverallEndTime(b,c.effects[a])}},createCanvasElement:function(b){var a=document.createElement("canvas");a.width=gShowController.script.slideWidth;a.height=gShowController.script.slideHeight;a.setAttribute("id",b);return a},setStyle:function(f,h,g,e,b,a,d,c){f.style.top=h;f.style.left=g;f.style.width=e;f.style.height=b;f.style.position=a;if(d!=null&&d!=undefined){f.style.opacity=d}if(c!=null&&c!=undefined){f.style.visibility=c}}});var KPFEffect=Class.create({initialize:function(b,a){this.attributes=b.attributes;this.type=b.type;this.name=b.name;this.beginTime=b.beginTime;this.duration=b.duration;this.objectID=b.objectID;this.baseLayer=b.baseLayer;if(kEmphasisEffects.indexOf(this.name)>-1){this.isEmphasisBuild=true}if(b.movie){this.movie=b.movie}this.effects=[];this.addSubEffect(b.effects,a)},destroy:function(){for(var a=0,b=this.effects.length;a<b;a++){this.destroyEffect(this.effects[a])}this.type=null;this.name=null;this.beginTime=null;this.duration=null;this.objectID=null;delete this.kpfLayer;delete this.effects;delete this.baseLayer;if(this.movie){delete this.movie}if(this.currentKPFLayer){delete this.currentKPFLayer}},destroyEffect:function(b){for(var a=0,c=b.effects.length;a<c;a++){this.destroyEffect(b.effects[a])}b.type=null;b.name=null;b.beginTime=null;b.duration=null;b.objectID=null;delete b.kpfLayer;delete b.effects;delete b.baseLayer;if(b.movie){delete b.movie}if(b.currentKPFLayer){delete b.currentKPFLayer}},addSubEffect:function(c,a){for(var b=0,e=c.length;b<e;b++){var d=new KPFEffect(c[b],a);this.effects.push(d)}}});var KPFMovie=Class.create({initialize:function(b){this.objectID=b.objectID;this.movieId=b.movieId;this.width=b.width;this.height=b.height;this.sceneIndex=b.sceneIndex;this.textureId=b.textureId;this.src=b.src;this.showControls=b.showControls;this.movieDiv=b.movieDiv;this.parentLayer=b.parentLayer;var a=this.videoElement=document.createElement("video");this.setDefaultStyle();this.setInsertBeforeOrAfterTextureId();setElementProperty(a,"pointer-events","all");a.setAttribute("id",this.movieId);a.setAttribute("src",this.src);if(this.showControls){Event.observe(a,"mouseover",this.handleMouseOver.bind());Event.observe(a,"mouseleave",this.handleMouseLeave.bind())}this.isFirstRendered=true;this.isEnded=false;this.isPlaying=false},destroy:function(){var a=this.videoElement;if(a){a.pause();a.src=""}},handleMouseOver:function(){this.setAttribute("controls","controls")},handleMouseLeave:function(){this.removeAttribute("controls")},setDefaultStyle:function(){var a=this.videoElement.style;a.top="0px";a.left="0px";a.width=this.width+"px";a.height=this.height+"px";a.position=kPositionAbsolutePropertyValue;a.visibility="hidden"},setInsertBeforeOrAfterTextureId:function(){var d=this.parentLayer.layers;for(var b=0,c=d.length;b<c;b++){var a=d[b];if(a.isVideoLayer){if(b+1<c){this.insertBeforeTextureId=d[b+1].textureId}if(b-1>=0){this.insertAfterTextureId=d[b-1].textureId}}}},observeEvents:function(a){var b=this.videoElement;Event.stopObserving(b,"canplay");Event.stopObserving(b,"ended");Event.observe(b,"canplay",this.handleMovieDidStart.bind(this,a));Event.observe(b,"ended",this.handleMovieDidEnd.bind(this,a))},setLoop:function(a){this.videoElement.loop=a},setVolume:function(a){this.videoElement.volume=a},removeControls:function(){if(this.videoElement.hasAttribute("controls")){this.videoElement.removeAttribute("controls")}},handleMovieDidStart:function(a){this.videoElement.style.visibility="visible";if(a){setTimeout(this.hideMoviePoster.bind(this,a),120)}},handleMovieDidEnd:function(a){if(!this.videoElement.loop){this.isEnded=true}},startMovie:function(){if(this.videoElement){this.videoElement.play();this.isPlaying=true}},stopMovie:function(){if(this.videoElement){this.videoElement.pause()}},hideMoviePoster:function(a){var b=a.style;b.visibility="hidden";b.display="none";if(a.parentNode){a.parentNode.removeChild(a)}}});var KPFCssRenderer=Class.create({initialize:function(b,d,a,c){this.textureId=b.textureId;this.nativeWidth=b.bounds.width;this.nativeHeight=b.bounds.height;this.opacity=b.opacity;this.visibility=b.hidden===true?"hidden":"visible";this.textureTransform=b.textureTransform;this.affineTransform=b.affineTransform;this.anchorPoint=b.anchorPoint;this.contentsRect=b.contentsRect;this.layer=b;this.sceneIndex=d;this.animationSupported=a;this.enableCompositingUsingBackface=false;this.enablePreserve3DFromParent=false;if(c.length>0){this.initRendererFlags(c[0])}this.glContentsRenderer={};this.domNode=document.createElement("div");this.domNode.setAttribute("id","layer"+b.layerId)},initRendererFlags:function(a){if(a.type==="transition"&&a.name!="apple:ca-swing"&&a.name!="com.apple.iWork.Keynote.BLTSwoosh"){this.enableCompositingUsingBackface=true;this.enablePreserve3DFromParent=true;if(isChrome&&(a.name==="apple:ca-push"||a.name==="com.apple.iWork.Keynote.BLTFadeThruColor")){this.enableCompositingUsingBackface=false;this.enablePreserve3DFromParent=false}}else{this.enableCompositingUsingBackface=false;this.enablePreserve3DFromParent=false}if(a.name==="apple:apple-grid"){this.isGridTransition=true}else{if(a.name==="com.apple.iWork.Keynote.BLTMosaicFlip"){this.isMosaicTransition=true}else{if(a.name==="com.apple.iWork.Keynote.BLTSwoosh"&&a.type==="transition"){this.isSwooshTransition=true}}}},destroy:function(){this.textureId=null;this.nativeWidth=null;this.nativeHeight=null;this.opacity=null;this.visibility=null;this.textureTransform=null;this.affineTransform=null;this.anchorPoint=null;this.textureAnimation=null;this.contentsRect=null;this.requiresPerspectiveTransform=null;this.sceneIndex=null;var d=this.domNode.getElementsByTagName("canvas");for(var c=d.length;c--;){var a=d[c];if(a){var b=a.getContext("2d");if(b){b.clearRect(0,0,a.width,a.height);d[c].remove()}}}if(this.domNode.hasChildNodes()){while(this.domNode.childNodes.length>0){this.domNode.removeChild(this.domNode.firstChild)}}this.domNode=null},addAnimationNode:function(e,d,a,c){if(d==null){return e}var f=d.shift();if(f==null){return e}var h=document.createElement("div");var g=a+"-"+escapeTextureId(f);h.setAttribute("id",g);if(c.initialState.masksToBounds){setElementProperty(h,"overflow","hidden")}if(this.enableCompositingUsingBackface){setElementProperty(h,kBackfaceVisibilityPropertyName,"hidden")}else{if(this.isSwooshTransition){setElementProperty(h,kTransformPropertyName,"translateZ(0px)")}}this.setStyle(h,"0px","0px",e.style.width,e.style.height,kPositionAbsolutePropertyValue,null,null);setElementProperty(h,kTransformStylePropertyName,kTransformStylePreserve3DPropertyValue);if(c.anchorPoint.pointX!=0.5||c.anchorPoint.pointY!=0.5){setElementProperty(h,kTransformOriginPropertyName,(c.anchorPoint.pointX*100)+"% "+(c.anchorPoint.pointY*100)+"%")}var b=["opacity","doubleSided","anchorPointZ"];if(c.transformOriginValue&&c.transformOriginZValue){if(c.animationInfo.name==="apple:ca-revolve"){b.push("anchorPoint","position","zPosition")}else{if(c.animationInfo.name==="apple:3D-cube"){b.push("anchorPoint","position","zPosition","transform.rotation.x","transform.rotation.y")}}}if(c.transformOriginZValue&&b.indexOf(f)===-1){if(Prototype.Browser.Gecko){setElementProperty(h,kTransformOriginPropertyName,(c.anchorPoint.pointX*100)+"% "+(c.anchorPoint.pointY*100)+"% "+c.transformOriginZValue+"px")}else{setElementProperty(h,kTransformOriginZPropertyName,c.transformOriginZValue+"px");if(navigator.userAgent.lastIndexOf("Chrome/")<=0){setElementProperty(h,kTransformPropertyName,"translateZ("+c.transformOriginZValue+"px)")}}}e.appendChild(h);return this.addAnimationNode(h,d,a,c)},createNodes:function(a,d,c){var b=gShowController.movieCache;if(b&&c.animationInfo.name!=="renderMovie"){this.setVideoLayer(c,b)}var e=this.addNode(a,d,c);return e},setVideoLayer:function(l,p){var a=l.objectID;var o=a+"-video";kpfMovie=p[o];if(!kpfMovie){for(var h=0,b=l.layers.length;h<b;h++){this.setVideoLayer(l.layers[h],p)}}else{if(l.layers.length===1){if(l.layers[0].textureId){l.layers[0].isVideoLayer=true;l.layers[0].movieObjectID=a}else{if(l.layers[0].layers[0].textureId){l.layers[0].layers[0].isVideoLayer=true;l.layers[0].layers[0].movieObjectID=a}}}else{var m=false;var d;for(var h=0,b=l.layers.length;h<b;h++){var k;if(l.layers[h].textureId){k=l.layers[h]}else{k=l.layers[h].layers[0]}var g=k.textureId;if(g===kpfMovie.insertAfterTextureId){d=k}var n=false;for(var f=0,c=kpfMovie.parentLayer.layers.length;f<c;f++){var e=kpfMovie.parentLayer.layers[f].textureId;if(e===g){n=true;break}}if(!n){m=true;k.isVideoLayer=true;k.movieObjectID=a}}if(!m&&d){d.isVideoLayer=true;d.movieObjectID=a}}}},addNode:function(r,E,f){if(f.canvasId){return}var G="layer"+f.layerId;var ae=document.createElement("div");ae.setAttribute("id",G);setElementProperty(ae,"pointer-events","none");var Q=f.contentsRect.x;var O=f.contentsRect.y;var R=f.contentsRect.width;var ad=f.contentsRect.height;var ao=f.affineTransform[0];var am=f.affineTransform[1];var al=f.affineTransform[2];var ak=f.affineTransform[3];var ai=f.affineTransform[4];var af=f.affineTransform[5];var v=f.animationInfo;var S=false;if(ao===-1&&v.name==="com.apple.iWork.Keynote.KLNComet"){ao=1;S=true}var C="matrix("+ao+","+am+","+al+","+ak+","+(ai+f.bounds.offset.pointX)+","+(af+f.bounds.offset.pointY)+")";var o=f.bounds;var s=o.width;var U=o.height;this.setStyle(ae,"0px","0px",s+"px",U+"px",kPositionAbsolutePropertyValue,f.opacity,f.visibility);setElementProperty(ae,kTransformPropertyName,C);if(f.anchorPoint.pointX!=0.5||f.anchorPoint.pointY!=0.5){setElementProperty(ae,kTransformOriginPropertyName,(f.anchorPoint.pointX*100)+"% "+(f.anchorPoint.pointY*100)+"%")}if(f.initialState.masksToBounds){setElementProperty(ae,"overflow","hidden")}r.appendChild(ae);var H;if(this.animationSupported){H=this.addAnimationNode(ae,f.divNames,G,f)}else{H=ae}if(f.isTransition&&this.enablePreserve3DFromParent){if(E.sublayerTransform[11]!=0){setElementProperty(ae,kTransformStylePropertyName,kTransformStylePreserve3DPropertyValue)}if(f.sublayerTransform[11]!=0){setElementProperty(ae,kPerspectivePropertyName,gShowController.stageManager.perspective+"px");setElementProperty(ae,kTransformStylePropertyName,kTransformStylePreserve3DPropertyValue)}}else{if(E.sublayerTransform[11]!=0){setElementProperty(r,kPerspectivePropertyName,gShowController.stageManager.perspective+"px");setElementProperty(ae,kTransformStylePropertyName,kTransformStylePreserve3DPropertyValue)}else{setElementProperty(ae,kTransformStylePropertyName,kTransformStyleFlatPropertyValue)}}if(isChrome){if(this.enableCompositingUsingBackface){setElementProperty(ae,kBackfaceVisibilityPropertyName,"hidden")}else{if(this.isSwooshTransition){setElementProperty(ae,kTransformPropertyName,"translateZ(0px)")}}}var M=f.textureId;if(M){var z=gShowController.textureManager;var F=z.getTextureObject(this.sceneIndex,M);if(!F){return ae}var p=document.createElement("canvas");var ap=p.getContext("2d");var a=F.width;var d=F.height;if(Q===0&&O===0&&R===1&&ad===1){p.width=a;p.height=d;if(a>0&&d>0){ap.drawImage(F,0,0)}this.setStyle(p,"0px","0px",s+"px",U+"px",kPositionAbsolutePropertyValue,null,null)}else{var n=O*d;var X=(Q+R)*a;var c=(O+ad)*d;var k=Q*a;var u=p.width=X-k;var j=p.height=c-n;ap.drawImage(F,k*pdfScaleFactor,n*pdfScaleFactor,u*pdfScaleFactor,j*pdfScaleFactor,0,0,u,j);this.setStyle(p,"0px","0px",u+"px",j+"px",kPositionAbsolutePropertyValue,null,null)}var L=p;L.setAttribute("id",M);if(browserPrefix==="webkit"&&f.isTransition==null){if(S){setElementProperty(L,kTransformPropertyName,"rotateY(180deg) translateZ(0px)")}else{setElementProperty(L,kTransformPropertyName,"translateZ(0px)")}}if(f.isTransition){if(isChrome){if(this.enableCompositingUsingBackface){if(!this.isGridTransition&&!this.isMosaicTransition){setElementProperty(L,kBackfaceVisibilityPropertyName,"hidden")}}else{if(this.isSwooshTransition){setElementProperty(L,kTransformPropertyName,"translateZ(0px)")}}}else{if(this.enableCompositingUsingBackface){setElementProperty(L,kBackfaceVisibilityPropertyName,"hidden")}else{setElementProperty(L,kTransformPropertyName,"translateZ(0px)")}}}var K=v.objectID;var g=v&&v.type==="buildOut";var W;var t;if(f.isVideoLayer){if(v.name==="renderMovie"){var Y=z.getMovieUrl(this.sceneIndex,v.movie.asset);var P=/(?:\.([^.]+))?$/;var ah=P.exec(Y)[1];if(ah==="gif"){t=new Image();this.setStyle(t,"0px","0px",s+"px",U+"px",kPositionAbsolutePropertyValue,null,null);Event.observe(t,"load",this.hideElement.bind(this,L));t.src=Y}else{if(gShowController.movieCache==null){gShowController.movieCache={}}var V=K+"-video";f.hasMovie=true;f.movieId=V;W=gShowController.movieCache[V];if(W==null){var ag={objectID:K,movieId:V,width:s,height:U,sceneIndex:this.sceneIndex,textureId:M,src:Y,showControls:gShowController.isRecording===false?true:false,movieDiv:ae,parentLayer:E};W=new KPFMovie(ag);gShowController.movieCache[V]=W;W.observeEvents(L)}}}else{var Z=gShowController.movieCache;if(Z){var V=f.movieObjectID+"-video";W=Z[V]}}}if(f.hasContentsAnimation){var an=f.cssAnimation.animations;var T;var e;for(var m=0,ab=an.length;m<ab;m++){if(an[m].property==="contents"){T=an[m].to.texture;e=an[m].from.texture;break}}var b=z.getTextureObject(this.sceneIndex,T);var N=document.createElement("canvas");var aq=N.getContext("2d");var a=N.width=b.width;var d=N.height=b.height;var J=a/s;var I=d/U;aq.drawImage(b,0,0);N.setAttribute("id",T);if(J>1&&I>1&&J!==0&&I!==0){this.setStyle(N,"0px","0px",a+"px",d+"px",kPositionAbsolutePropertyValue,null,null);setElementProperty(N,kTransformOriginPropertyName,"0% 0%");setElementProperty(N,kTransformPropertyName,"scale("+1/J+","+1/I+")")}else{this.setStyle(N,"0px","0px",s+"px",U+"px",kPositionAbsolutePropertyValue,null,null)}var B=document.createElement("div");B.id=G+"-contents-to";this.setStyle(B,"0px","0px",s+"px",U+"px",kPositionAbsolutePropertyValue,null,null);B.appendChild(N);H.appendChild(B);setElementProperty(B,"opacity",0);var D=z.getTextureObject(this.sceneIndex,e);var q=document.createElement("canvas");var aj=q.getContext("2d");q.width=D.width;q.height=D.height;aj.drawImage(D,0,0);q.setAttribute("id",e);this.setStyle(q,"0px","0px",s+"px",U+"px",kPositionAbsolutePropertyValue,null,null);var l=document.createElement("div");l.id=G+"-contents-from";this.setStyle(l,"0px","0px",s+"px",U+"px",kPositionAbsolutePropertyValue,null,null);l.appendChild(q);H.appendChild(l)}else{H.appendChild(L);if(t){H.appendChild(t)}}if(W){if(W.isFirstRendered){H.insertBefore(W.videoElement,L);W.isFirstRendered=false}else{if(f.animationInfo&&f.animationInfo.name!=="renderMovie"){if(W.objectID===K&&g){W.stopMovie();W.removeControls();W.isBuiltOut=true}else{if(!W.isBuiltOut){H.parentNode.appendChild(W.movieDiv)}}}}}}else{if(f.initialState.backgroundColor){var aa=f.initialState.backgroundColor;setElementProperty(H,"background-color","rgba("+parseInt(aa[0]*255)+","+parseInt(aa[1]*255)+","+parseInt(aa[2]*255)+","+aa[3]+")")}}for(var ac=0,A=f.layers.length;ac<A;ac++){this.addNode(H,f,f.layers[ac])}return ae},hideElement:function(a){a.style.visibility="hidden"},serializeSvg:function(e){var f=e.getElementsByTagName("image");for(var d=0,b=f.length;d<b;d++){var a=f[d];var g=document.createElement("a");g.href=a.getAttributeNS("http://www.w3.org/1999/xlink","href");var j=window.location.protocol+"//"+g.host+g.pathname;a.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",j)}var h=new XMLSerializer;var c=h.serializeToString(e);return c},draw:function(a){this.setStyle(this.domNode,"0px","0px",this.nativeWidth+"px",this.nativeHeight+"px",kPositionAbsolutePropertyValue,this.opacity,this.visibility);if(browserPrefix==="webkit"){if(this.enableCompositingUsingBackface&&isChrome){setElementProperty(this.domNode,kBackfaceVisibilityPropertyName,"hidden")}else{setElementProperty(this.domNode,kTransformPropertyName,"translateZ(0px)")}}if(this.layer.sublayerTransform[11]!=0){setElementProperty(this.domNode,kPerspectivePropertyName,gShowController.stageManager.perspective+"px");setElementProperty(this.domNode,kTransformStylePropertyName,kTransformStylePreserve3DPropertyValue)}else{setElementProperty(this.domNode,kTransformStylePropertyName,kTransformStyleFlatPropertyValue)}for(var b=0,c=this.layer.layers.length;b<c;b++){this.createNodes(this.domNode,this.layer,this.layer.layers[b])}a.appendChild(this.domNode)},setStyle:function(f,h,g,e,b,a,d,c){f.style.top=h;f.style.left=g;f.style.width=e;f.style.height=b;f.style.position=a;if(d!=null&&d!=undefined){f.style.opacity=d}if(c!=null&&c!=undefined){f.style.visibility=c}},overallEndTime:function(a){var b={};b.duration=0;this.overallEndTimeForLayer(this.layer,b);return b.duration},overallEndTimeForLayer:function(b,c){if(b.cssAnimation){if(b.cssAnimation.overallEndTime>c.duration){c.duration=b.cssAnimation.overallEndTime}}for(var a=0,d=b.layers.length;a<d;a++){this.overallEndTimeForLayer(b.layers[a],c)}},animate:function(a){if(this.animationSupported){if(a.kpfLayer){if(a.movie){this.animateEffect(a,a.kpfLayer,a.currentKPFLayer?a.currentKPFLayer:null,a.movie)}else{this.animateEffect(a,a.kpfLayer,a.currentKPFLayer?a.currentKPFLayer:null)}}}},animateEffect:function(q,b,k,e){var m=q.objectID+"-video";if(b.cssAnimationRules.length>0){var g=k?"layer"+k.layerId:"layer"+b.layerId;var d=document.getElementById(g);if(d){this.applyCssAnimation(d,b,k,q)}else{if(q.currentKPFLayer){g="layer"+q.currentKPFLayer.layerId;if(q.currentKPFLayer.layers[0]){g="layer"+q.currentKPFLayer.layers[0].layerId}d=document.getElementById(g);if(d){this.applyCssAnimation(d,b,q.currentKPFLayer,q)}}}}else{if(b.isRenderMovie&&b.animationInfo.name==="renderMovie"){var j=gShowController.movieCache;if(j){var p=j[m];if(p){if(e.loopMode&&e.loopMode==="looping"){p.setLoop(true)}if(e.volume){p.setVolume(e.volume)}p.startMovie()}}}if(k){var a=document.getElementById("layer"+k.layerId);var l=window.getComputedStyle(a,null);var n=l.getPropertyValue(kTransformPropertyName);var f=parseTransformMatrix(n);var o="matrix("+f[0]+","+f[1]+","+f[2]+","+f[3]+","+b.bounds.offset.pointX+","+b.bounds.offset.pointY+")";if(q.name==="apple:action-motion-path"){setElementProperty(a,kTransformPropertyName,o)}}}for(var h=0,c=b.layers.length;h<c;h++){if(gShowController.movieCache&&gShowController.movieCache[m]){this.animateEffect(q,b.layers[h],k,e)}else{this.animateEffect(q,b.layers[h],k?k.layers[h]:null,e)}}},applyCssAnimation:function(y,h,K,Z){var U=h.cssAnimation;var B=h.cssAnimationRules;var T=h.cssAnimation.overallEndTime;if(h.hasMovie){if(h.animationInfo.type==="buildOut"){this.stopMovie(document.getElementById(h.movieId))}}if(isChrome&&h.animationInfo.name==="apple:doorway"){if(h.layers.length===0&&h.contentsRect.x===0&&h.contentsRect.y===0&&h.contentsRect.width===1&&h.contentsRect.height===1){y.style.visibility="hidden"}}var g=U.keyAnimations.bounds;if(g){var z=document.styleSheets[1].cssRules;var ag=z.length;var D=y.id+"-bounds";if(K){D="layer"+h.layerId+"-bounds"}for(var ac=0;ac<ag;ac++){var v=z[ac];if(v.name===D){while(v.cssRules.length>0){if(isIE){for(var ab=0,E=v.cssRules.length;ab<E;ab++){v.deleteRule(ab)}}else{v.deleteRule(v.cssRules[0].keyText)}}for(var ab=0,A=g.keyframes.length;ab<A;ab++){var k=g.keyframes[ab];var V,ad,a,e;if(k.keyframe==0){V=k.value.width;ad=k.value.height;v.appendRule("0% {"+kTransformPropertyName+": scaleX(1) scaleY(1); "+kAnimationTimingFunctionPropertyName+": "+k.timingFunction+";}")}else{a=k.value.width;e=k.value.height;v.appendRule(k.keyframe+"% {"+kTransformPropertyName+": scaleX("+a/V+") scaleY("+e/ad+"); "+kAnimationTimingFunctionPropertyName+": "+k.timingFunction+";}")}}}}}if(h.animationInfo.name!=="apple:ca-swing"&&(h.initialState.rotation!==0||h.initialState.scale!==1)){var l=document.getElementById(y.id);var H=window.getComputedStyle(l,null);var M=H.getPropertyValue(kTransformPropertyName);var N=parseTransformMatrix(M);var o="matrix(1,0,0,1,"+N[4]+","+N[5]+")";setElementProperty(l,kTransformPropertyName,o);var x=document.getElementById(y.id+"-"+escapeTextureId("transform.rotation.z"));if(x){setElementProperty(x,kTransformPropertyName,"rotateZ("+h.initialState.rotation+"rad)")}var F=document.getElementById(y.id+"-"+escapeTextureId("transform.scale.x"));if(F){setElementProperty(F,kTransformPropertyName,"scaleX("+h.initialState.scale+")")}var p=document.getElementById(y.id+"-"+escapeTextureId("transform.scale.y"));if(p){setElementProperty(p,kTransformPropertyName,"scaleY("+h.initialState.scale+")")}}for(var G in U.keyAnimations){var u=U.keyAnimations[G];var C=u.keyActions;var J=C[C.length-1];var I=u.keyframes[u.keyframes.length-1];var ai=this.cssPropertyNameForAction(G);var aa=this.cssPropertyValueForActionValue(G,I.value);var d=u.repeatCount;var n=T+"s";var D="";var R="";if(G==="isPlaying"){continue}if(K&&h.animationInfo.type==="actionBuild"&&kActionBuildKeyAnimations[h.animationInfo.name].indexOf(G)===-1){continue}if(G==="doubleSided"){var m=document.getElementById(y.id+"-"+escapeTextureId(G));if(m){setElementProperty(m,ai,aa)}continue}if(h.animationInfo.name==="apple:ca-swing"&&(G==="anchorPoint"||G==="transform.translation")){continue}if((h.animationInfo.name==="apple:ca-revolve"||h.animationInfo.name==="apple:3D-cube")&&h.transformOriginValue&&h.transformOriginZValue&&(G==="anchorPointZ"||G==="zPosition")){continue}switch(G){case"opacity":D=y.id+"-opacity";R=D;if(K){if(document.getElementById(D)==null){D=y.id}R="layer"+h.layerId+"-opacity"}else{setElementProperty(y,"opacity",1)}break;case"hidden":ai="opacity";if(aa==="hidden"){aa=0}else{y.style.visibility="visible";aa=1}D=y.id;R=D+"-hidden";if(K){R="layer"+h.layerId+"-hidden"}break;case"bounds":D=y.id+"-bounds";R=D;if(K){R="layer"+h.layerId+"-bounds"}var V,ad,w,L;var q=u.keyframes[0];var W=u.keyframes[u.keyframes.length-1];aa="scaleX("+W.value.width/q.value.width+") scaleY("+W.value.height/q.value.height+")";break;default:D=y.id+"-"+escapeTextureId(G);R=D;if(K){R="layer"+h.layerId+"-"+escapeTextureId(G)}break}if(G==="contents"){if(Z.type==="smartBuild"){var f=y.id+"-contents-canvas";var r=document.createElement("canvas");r.width=h.initialState.width;r.height=h.initialState.height;r.setAttribute("id",f);var Y=gShowController.scriptManager.slideIndexFromSceneIndex(this.sceneIndex);var b={canvasId:f,canvas:r,textureAssets:gShowController.textureManager.slideCache[Y].textureAssets,effect:Z,overallEndTime:T,element:y};var O=this.glContentsRenderer[f];if(!O){O=new KNWebGLRenderer(b);this.glContentsRenderer[f]=O}var ah=document.getElementById(y.id);ah.appendChild(r);var Q=Z.beginTime*1000;setTimeout(this.animateContentsWillBegin.bind(this,b),Q)}else{var X=y.id+"-contents-from";var ae=y.id+"-contents-to";var P=X;var t=ae;if(K){P="layer"+h.layerId+"-contents-from";t="layer"+h.layerId+"-contents-to"}var s=document.getElementById(X);var af=document.getElementById(ae);setElementProperty(s,"opacity",0);setElementProperty(s,kAnimationNamePropertyName,P);setElementProperty(s,kAnimationDurationPropertyName,n);setElementProperty(af,"opacity",1);setElementProperty(af,kAnimationNamePropertyName,t);setElementProperty(af,kAnimationDurationPropertyName,n)}continue}var c=document.getElementById(D);if(c){if(G==="anchorPoint"){var S={x:I.value.pointX,y:I.value.pointY};if(h.magicMoveOffsetValue){S.x=h.magicMoveOffsetValue.pointX;S.y=h.magicMoveOffsetValue.pointY}ai=kTransformPropertyName;aa="translateX("+S.x+"px) translateY("+S.y+"px)"}else{if(G==="anchorPointZ"){if(Prototype.Browser.Gecko||navigator.userAgent.lastIndexOf("Chrome/")>0){ai=kTransformPropertyName;aa="translateZ("+-h.transformOriginZValue+"px)"}else{ai=kTransformPropertyName;aa="translateZ("+h.transformOriginZValue+"px)"}}}if(G!=="hidden"){setElementProperty(c,ai,aa)}setElementProperty(c,kAnimationFillModePropertyName,J.fillMode==="removed"?"none":J.fillMode);setElementProperty(c,kAnimationNamePropertyName,R);setElementProperty(c,kAnimationDurationPropertyName,n);if(d>1&&(h.animationInfo.name==="apple:action-blink"||h.animationInfo.name==="apple:action-pulse")){setElementProperty(c,kAnimationIterationCountPropertyName,d)}}}},animateContentsWillBegin:function(d){var c=d.canvasId;var i=d.effect;var e=d.element;var g=this.glContentsRenderer[c];g.draw(i);if(!g.animationStarted){g.animate();g.animationStarted=true}var b=e.id+"-contents-from";var a=e.id+"-contents-to";var h=document.getElementById(b);var f=document.getElementById(a);setElementProperty(h,"opacity",0);setElementProperty(f,"opacity",0)},cssPropertyValueForActionValue:function(a,b){switch(a){case"hidden":if(b.scalar===true){return"hidden"}else{return"visible"}case"anchorPoint":return b.pointX+"% "+b.pointY+"%";case"anchorPointZ":return b.scalar;case"position":return"translate("+b.pointX+"px,"+b.pointY+"px)";case"zPosition":return"translateZ("+b.scalar+"px)";case"translationEmphasis":return"translateX("+b.translationEmphasis[0]+"px) translateY("+b.translationEmphasis[1]+"px) translateZ("+b.translationEmphasis[2]+")";case"rotationEmphasis":return"rotateZ("+b.rotationEmphasis[6]+"rad)";case"scaleEmphasis":return"scale3d("+ensureScaleFactorNotZero(b.scaleEmphasis[3])+","+ensureScaleFactorNotZero(b.scaleEmphasis[4])+","+ensureScaleFactorNotZero(b.scaleEmphasis[5])+")";case"transform.scale":case"transform.scale.xy":return"scale("+ensureScaleFactorNotZero(b.scalar)+")";case"transform.scale.x":return"scaleX("+ensureScaleFactorNotZero(b.scalar)+")";case"transform.scale.y":return"scaleY("+ensureScaleFactorNotZero(b.scalar)+")";case"transform.rotation.x":return"rotateX("+b.scalar+"rad)";case"transform.rotation.y":return"rotateY("+b.scalar+"rad)";case"transform.rotation.z":case"transform.rotation":return"rotateZ("+b.scalar+"rad)";case"transform.translation":return"translateX("+b.pointX+"px) translateY("+b.pointY+"px)";case"transform.translation.x":return"translateX("+b.scalar+"px)";case"transform.translation.y":return"translateY("+b.scalar+"px)";case"transform.translation.z":return"translateZ("+b.scalar+"px)";case"isPlaying":case"opacity":case"opacityMultiplier":return b.scalar+"";case"transform":return"matrix3d("+b.transform+")";case"doubleSided":if(b.scalar===false){return"hidden"}else{return"visible"}default:return"some value"}},cssPropertyNameForAction:function(a){switch(a){case"hidden":return kVisibilityPropertyName;case"anchorPoint":return kTransformOriginPropertyName;case"anchorPointZ":return kTransformOriginZPropertyName;case"opacityMultiplier":return kOpacityPropertyName;case"translationEmphasis":case"rotationEmphasis":case"scaleEmphasis":case"position":case"zPosition":case"transform":case"transform.scale":case"transform.scale.xy":case"transform.scale.x":case"transform.scale.y":case"transform.rotation.x":case"transform.rotation.y":case"transform.rotation.z":case"transform.rotation":case"transform.translation":case"transform.translation.x":case"transform.translation.y":case"transform.translation.z":case"bounds":return kTransformPropertyName;case"doubleSided":return kBackfaceVisibilityPropertyName;case"contents":return kBackgroundImagePropertyName;default:return a}},hideMoviePoster:function(a){a.style.visibility="hidden"},handleMovieDidStart:function(a,b){b.style.visibility="visible";setTimeout(this.hideMoviePoster.bind(this,a),120)},handleMovieDidEnd:function(a,b){if(!b.loop){b.isEnded=true}},startMovie:function(a){if(a){a.play();a.isPlaying=true}},stopMovie:function(a){if(a){a.pause()}}});var KPFLayer=Class.create({initialize:function(c,d,b){this.animationInfo=d;this.layerId=kpfLayerCounter;kpfLayerCounter=kpfLayerCounter+1;this.objectID=c.objectID!=null?c.objectID:null;this.textureId=c.texture?c.texture:null;this.animations=c.animations;this.initialState=c.initialState;this.isVideoLayer=c.isVideoLayer;this.hasHighlightedBulletAnimation=c.hasHighlightedBulletAnimation;this.cssAnimationRules=[];this.layers=[];this.affineTransform=this.initialState.affineTransform;this.position=this.initialState.position;this.textureTransform="";if(this.initialState.transform!=null&&this.initialState.transform!=undefined){this.textureTransform="matrix3D("+this.initialState.transform+")"}else{this.textureTransform="matrix("+this.affineTransform+")"}this.anchorPoint=this.initialState.anchorPoint;if(b==null){b={pointX:0,pointY:0}}var a=this.position.pointX-this.initialState.width/2-(this.anchorPoint.pointX-0.5)*this.initialState.width;var e=this.position.pointY-this.initialState.height/2-(this.anchorPoint.pointY-0.5)*this.initialState.height;a=Math.round(a*1000000)/1000000;e=Math.round(e*1000000)/1000000;this.bounds={width:this.initialState.width,height:this.initialState.height,origin:{pointX:this.affineTransform[4],pointY:this.affineTransform[5]},offset:{pointX:a,pointY:e},canvasOffset:{pointX:a+b.pointX,pointY:e+b.pointY}};this.sublayerTransform=this.initialState.sublayerTransform;this.contentsRect=this.initialState.contentsRect;this.hidden=this.initialState.hidden;this.opacity=this.initialState.opacity;this.visibility=this.hidden===true?"hidden":"visible";this.addSublayer(c.layers,d,this.bounds.offset);if(d.animationSupported){this.initLayerAnimations()}},destroy:function(){this.initialState=null;this.cssAnimationRules=null;this.affineTransform=null;this.textureTransform=null;this.anchorPoint=null;this.anchorPointZ=null;this.bounds=null;this.contentsRect=null;this.hidden=null;this.opacity=null},addSublayer:function(f,e,d){for(var a=0,b=f.length;a<b;a++){var c=new KPFLayer(f[a],e,d);this.layers.push(c)}},initLayerAnimations:function(){var l=false;var h=false;var b=false;var s=false;var g=false;var f=false;var d=false;var a=false;var p=false;var o=false;var m=false;var u=false;var x=false;var w=false;var c=false;var y=false;var r=false;var t=[];var e=false;var n=this.animationInfo;var k=n.type;var A=n.name;var q=["isPlaying","opacityMultiplier","hidden"];if(k==="actionBuild"){this.isActionBuild=true}else{if(k==="buildIn"){this.isBuildIn=true}else{if(k==="buildOut"){this.isBuildOut=true}else{if(k==="transition"){this.isTransition=true}}}}if(A==="apple:magic-move-implied-motion-path"){this.isMagicMove=true}else{if(A==="apple:ca-isometric"){e=true}else{if(A==="renderMovie"){this.isRenderMovie=true}else{if(kEmphasisEffects.indexOf(A)>-1){this.isEmphasisBuild=true}}}}if(this.animations.length>0){this.cssAnimation=new KPFCssAnimation(this.animations,this)}this.divNames=[];if(this.objectID&&this.isRenderMovie){this.divNames=["opacity","position","transform.rotation.z","transform.scale.x","transform.scale.y","bounds","contents"]}else{if(this.cssAnimation){for(var z in this.cssAnimation.keyAnimations){if(q.indexOf(z)>0){continue}if(z=="opacity"){h=true}else{if(z==="anchorPoint"){b=true}else{if(z==="anchorPointZ"){s=true}else{if(!e&&z==="transform.translation.x"){g=true}else{if(!e&&z==="transform.translation.y"){f=true}else{if(!e&&z==="transform.translation.z"){d=true}else{if(!e&&z==="transform.translation"){a=true}else{if(!e&&z==="transform.rotation.x"){p=true}else{if(!e&&z==="transform.rotation.y"){o=true}else{if(!e&&z==="transform.rotation.z"){m=true}else{if(!e&&z==="transform.rotation"){u=true}else{if(z==="transform.scale.x"){x=true}else{if(z==="transform.scale.y"){w=true}else{if(z==="transform.scale.xy"){c=true}else{if(z==="transform.scale"){y=true}else{if(z==="transform"){r=true}else{if(z==="doubleSided"){l=true}else{if(z==="contents"){this.hasContentsAnimation=true}else{if(z==="bounds"){this.hasBoundsAnimation=true}else{if(z==="position"){this.hasPosition=true}else{t.push(z)}}}}}}}}}}}}}}}}}}}}}if(h&&this.isActionBuild&&!this.isEmphasisBuild){this.divNames.push("opacity");for(var v=0,j=this.layers.length;v<j;v++){if(this.layers[v].animations.length===0){this.layers[v].divNames=["opacity","position","transform.rotation.z","transform.scale.x","transform.scale.y","bounds","contents"]}}}else{if((h||this.isActionBuild)&&this.divNames.indexOf("opacity")===-1){this.divNames.push("opacity")}if(r){this.divNames.push("transform")}if(this.hasPosition||this.isActionBuild){this.divNames.push("position")}if(b){this.divNames.push("anchorPoint")}if(s){this.divNames.push("anchorPointZ")}for(var v=0,j=t.length;v<j;v++){this.divNames.push(t[v])}if(g){this.divNames.push("transform.translation.x")}if(f){this.divNames.push("transform.translation.y")}if(a){this.divNames.push("transform.translation")}if(d){this.divNames.push("transform.translation.z")}if(p){this.divNames.push("transform.rotation.x")}if(o){this.divNames.push("transform.rotation.y")}if(m){this.divNames.push("transform.rotation.z")}if((this.initialState.rotation!==0||this.isActionBuild)&&this.divNames.indexOf("transform.rotation.z")===-1){this.divNames.push("transform.rotation.z")}if(u){this.divNames.push("transform.rotation")}if(x){this.divNames.push("transform.scale.x")}if(w){this.divNames.push("transform.scale.y")}if(this.initialState.scale!==1||this.isActionBuild){if(this.divNames.indexOf("transform.scale.x")===-1){this.divNames.push("transform.scale.x")}if(this.divNames.indexOf("transform.scale.y")===-1){this.divNames.push("transform.scale.y")}}if(c){this.divNames.push("transform.scale.xy")}if(y){this.divNames.push("transform.scale")}if(this.textureId&&(this.hasBoundsAnimation||this.isActionBuild)){this.divNames.push("bounds")}if(this.textureId&&(this.hasContentsAnimation||this.isActionBuild)){this.divNames.push("contents")}if(l){this.divNames.push("doubleSided")}}}}}});var KPFCssAnimation=Class.create({initialize:function(o,I){this.kDelta=0.0001;this.kRoundingFactor=10000;this.animations=[];this.keyAnimations={};for(var C=0,g=o.length;C<g;C++){var F=o[C];var v=F.beginTime;var b=F.duration;var d=F.timingFunction?F.timingFunction:"linear";var H;var G;var l;var f;var y;var w=v+b;this.overallEndTime=0;if(w>this.overallEndTime){this.overallEndTime=w}if(d=="custom"){H=F.timingControlPoint1x;G=F.timingControlPoint1y;l=F.timingControlPoint2x;f=F.timingControlPoint2y}if(F.animations!=null&&F.animations.length>0){var q=F.animations;var p=v;if(q[0].property==null){p=q[0].beginTime;q=q[0].animations}for(var z=0,e=q.length;z<e;z++){var a=q[z];var n=a.property;var B=this.keyAnimations[n];if(B==null){B={groupBeginTime:p,earliestBeginTime:p+a.beginTime,latestEndTime:-1,repeatCount:a.repeatCount,keyActions:[]};this.keyAnimations[n]=B}if(p+a.beginTime+a.duration>B.latestEndTime){B.latestEndTime=p+a.beginTime+a.duration}if(a.path){var E=F.path.length;for(var x=0;C<E-1;x++){var r=F.path[x];var c=F.path[x+1];var A=r.points[0];var h=c.points[0];var u={pointX:A[0],pointY:A[1]};var D={pointX:h[0],pointY:h[1]};switch(r.type){case"MoveToPoint":case"AddLine":case"AddCurve":case"AddQuadCurve":y={property:"position",from:u,to:D,fillMode:"forwards",beginTime:p+a.beginTime+(x/(E-1))*a.duration,duration:1/(E-1)*a.duration,timingFunction:"linear",groupTimingFunction:d,groupBeginTime:v,groupDuration:b,groupTimingControlPoint1x:H,groupTimingControlPoint1y:G,groupTimingControlPoint2x:l,groupTimingControlPoint2y:f};break}this.addAction(y,a)}}else{if(a.keyTimes){var t=a.keyTimes.length;for(var x=0;x<t-1;x++){var s=a.keyTimes[x];var m=a.keyTimes[x+1];y={property:a.property,from:a.values[x],to:a.values[x+1],fillMode:a.fillMode,beginTime:p+a.beginTime+(s/1*a.duration),duration:(m-s)*a.duration,timingFunction:a.timingFunctions?a.timingFunctions[x]:"linear",groupTimingFunction:d,groupBeginTime:v,groupDuration:b,groupTimingControlPoint1x:H,groupTimingControlPoint1y:G,groupTimingControlPoint2x:l,groupTimingControlPoint2y:f};this.addAction(y,a)}}else{y={property:a.property,from:a.from,to:a.to,fillMode:a.fillMode,beginTime:p+a.beginTime,duration:a.duration,timingFunction:a.timingFunction?a.timingFunction:"linear",groupTimingFunction:d,groupBeginTime:v,groupDuration:b,groupTimingControlPoint1x:H,groupTimingControlPoint1y:G,groupTimingControlPoint2x:l,groupTimingControlPoint2y:f};this.addAction(y,a)}}}}else{var n=F.property;var B=this.keyAnimations[n];if(B==null){B={groupBeginTime:0,earliestBeginTime:F.beginTime,latestEndTime:-1,repeatCount:F.repeatCount,keyActions:[]};this.keyAnimations[n]=B}if(F.beginTime+F.duration>B.latestEndTime){B.latestEndTime=F.beginTime+F.duration}if(F.path){var E=F.path.length;for(var x=0;x<E-1;x++){var r=F.path[x];var c=F.path[x+1];var A=r.points[0];var h=c.points[0];var u={pointX:A[0],pointY:A[1]};var D={pointX:h[0],pointY:h[1]};switch(r.type){case"MoveToPoint":case"AddLine":case"AddCurve":case"AddQuadCurve":y={property:"position",from:u,to:D,fillMode:"forwards",beginTime:v+x/(E-1)*b,duration:1/(E-1)*b,timingFunction:"linear"};break}this.addAction(y,F)}}else{if(F.keyTimes){var t=F.keyTimes.length;for(var x=0;x<t-1;x++){var s=F.keyTimes[x];var m=F.keyTimes[x+1];y={property:F.property,from:F.values[x],to:F.values[x+1],fillMode:F.fillMode,beginTime:v+s*b,duration:(m-s)*b,timingFunction:F.timingFunctions?F.timingFunctions[x]:"linear"};this.addAction(y,F)}}else{y={property:F.property,from:F.from,to:F.to,fillMode:F.fillMode,beginTime:v,duration:b,timingFunction:d?d:"linear"};this.addAction(y,F)}}}}this.createKeyActions();this.createAnimationRules(I);this.createAnimationRuleForKeyframes(I)},addAction:function(b,a){if(a.timingFunction==="custom"){b.timingControlPoint1x=a.timingControlPoint1x;b.timingControlPoint1y=a.timingControlPoint1y;b.timingControlPoint2x=a.timingControlPoint2x;b.timingControlPoint2y=a.timingControlPoint2y}else{if(b.timingFunction.timingFunction!=null){if(b.timingFunction.timingFunction==="custom"){b.timingControlPoint1x=b.timingFunction.timingControlPoint1x;b.timingControlPoint1y=b.timingFunction.timingControlPoint1y;b.timingControlPoint2x=b.timingFunction.timingControlPoint2x;b.timingControlPoint2y=b.timingFunction.timingControlPoint2y}b.timingFunction=b.timingFunction.timingFunction}}this.animations.push(b)},createKeyActions:function(){for(var e=0,a=this.animations.length;e<a;e++){var c=this.animations[e];var d=c.beginTime;var b=c.duration;var g=d+b;var n=c.property;var h=this.keyAnimations[n];var m=h.keyActions;var k=h.latestEndTime-h.earliestBeginTime;var l=0;var j=100;if(k>0){l=100*d/this.overallEndTime;j=100*g/this.overallEndTime}if(j>99.9999){j=100}var f={startKeyframe:l,endKeyframe:j,from:c.from,to:c.to,timingFunction:c.timingFunction};if(c.fillMode){f.fillMode=c.fillMode}if(c.timingFunction=="custom"){f.timingControlPoint1x=c.timingControlPoint1x;f.timingControlPoint1y=c.timingControlPoint1y;f.timingControlPoint2x=c.timingControlPoint2x;f.timingControlPoint2y=c.timingControlPoint2y}m.push(f);m.sort(this.sortAction)}},sortAction:function(b,a){return b.startKeyframe-a.startKeyframe},roundNum:function(a){return Math.round(a*this.kRoundingFactor)/this.kRoundingFactor},createAnimationRules:function(w){var f=this.kDelta;for(var h in this.keyAnimations){if(h=="playing"){continue}var q=this.keyAnimations[h];var g=q.keyActions;var j=false;q.keyframes=[];var o=g[0];var s=this.roundNum(o.startKeyframe);var m=this.roundNum(100*q.groupBeginTime/this.overallEndTime);if(h=="anchorPoint"){var c={};c.x=o.to.pointX;c.y=o.to.pointY;var n={pointX:-(o.from.pointX-w.anchorPoint.pointX)*w.bounds.width,pointY:-(o.from.pointY-w.anchorPoint.pointY)*w.bounds.height};if(w.isMagicMove){var u=this.anchorPointOffset(w,{x:o.from.pointX,y:o.from.pointY});var k={pointX:u.x,pointY:u.y};var d=this.anchorPointOffset(w,{x:o.to.pointX,y:o.to.pointY});var v={pointX:d.x,pointY:d.y};if(k.pointX!==v.pointX||k.pointY!=v.pointY){n={pointX:v.pointX-k.pointX,pointY:v.pointY-k.pointY};w.magicMoveOffsetValue=n}}if(s!=0){var t={pointX:0,pointY:0};if(m>0){this.insertInitialKeyframes(q,m-f,"position",t)}if(s-m>f){if(o.fillMode==="both"||o.fillMode==="backwards"){t=n}q.keyframes.push({keyframe:m,keyName:"position",value:t,timingFunction:"linear"});q.keyframes.push({keyframe:s-f,keyName:"position",value:t,timingFunction:"linear"})}}q.keyframes.push({keyframe:s,keyName:"position",value:n,timingFunction:"linear"});q.keyframes.push({keyframe:100,keyName:"position",value:n,timingFunction:"linear"});w.transformOriginValue=(c.x*100)+"% "+(c.y*100)+"%";continue}if(h=="anchorPointZ"){j=true;if(s!=0){var t=this.createInitialKeyframeValue(w,h,o.from,true);q.keyframes.push({keyframe:0,keyName:"zPosition",value:t,timingFunction:"linear"});q.keyframes.push({keyframe:s-f,keyName:"zPosition",value:t,timingFunction:"linear"})}q.keyframes.push({keyframe:s,keyName:"zPosition",value:o.from,timingFunction:"linear"});q.keyframes.push({keyframe:100,keyName:"zPosition",value:o.to,timingFunction:"linear"});w.transformOriginZValue=o.to.scalar;continue}if(o==null){continue}var l=0;var r=null;var e=null;if(s!=0){if(h==="hidden"){e={scalar:w.hidden};this.insertInitialKeyframes(q,s-f,h,e)}else{if(h==="opacity"){if(o.fillMode==="both"||o.fillMode==="backwards"){e=o.from}else{e={scalar:w.opacity}}this.insertInitialKeyframes(q,s-f,h,e)}else{if(h==="position"){if(w.isBuildIn||w.isBuildOut){if(m>0&&o.fillMode!=="both"&&o.fillMode!=="backwards"){e={pointX:0,pointY:0}}else{e={pointX:this.roundNum(o.from.pointX-w.initialState.position.pointX),pointY:this.roundNum(o.from.pointY-w.initialState.position.pointY)}}}else{e={pointX:0,pointY:0}}this.insertInitialKeyframes(q,s-f,h,e)}else{e=this.createInitialKeyframeValue(w,h,o.from,j);if(m>0){this.insertInitialKeyframes(q,m-f,h,e)}if(s-m>f){if(o.fillMode==="both"||o.fillMode==="backwards"){e=o.from}if(h==="transform.translation"){e.pointX=this.roundNum(e.pointX);e.pointY=this.roundNum(e.pointY)}q.keyframes.push({keyframe:m,keyName:h,value:e,timingFunction:"linear"});q.keyframes.push({keyframe:s-f,keyName:h,value:e,timingFunction:"linear"})}}}}l=o.startKeyframe;r=e}for(var p=0,b=g.length;p<b;p++){o=g[p];if(h=="position"){e=w.initialState.position;o.from={pointX:this.roundNum(o.from.pointX-e.pointX),pointY:this.roundNum(o.from.pointY-e.pointY)};o.to={pointX:this.roundNum(o.to.pointX-e.pointX),pointY:this.roundNum(o.to.pointY-e.pointY)}}if(Math.abs(o.startKeyframe-l)>f){q.keyframes.push({keyframe:this.roundNum(o.startKeyframe)-f,keyName:h,value:r,timingFunction:"linear"})}if(h==="transform.translation"){o.from.pointX=this.roundNum(o.from.pointX);o.from.pointY=this.roundNum(o.from.pointY);o.to.pointX=this.roundNum(o.to.pointX);o.to.pointY=this.roundNum(o.to.pointY)}var a=this.createTimingFunctionForAction(o);q.keyframes.push({keyframe:this.roundNum(o.startKeyframe),keyName:h,value:o.from,timingFunction:a});q.keyframes.push({keyframe:this.roundNum(o.endKeyframe)-(o.endKeyframe==100?0:f),keyName:h,value:o.to,timingFunction:a});r=o.to;l=o.endKeyframe}if(l!=100&&h!="hidden"){q.keyframes.push({keyframe:this.roundNum(l),keyName:h,value:r,timingFunction:"linear"});q.keyframes.push({keyframe:100,keyName:h,value:r,timingFunction:"linear"})}}},insertInitialKeyframes:function(b,c,d,a){b.keyframes.push({keyframe:0,keyName:d,value:a,timingFunction:"linear"});b.keyframes.push({keyframe:c,keyName:d,value:a,timingFunction:"linear"})},anchorPointOffset:function(c,e){var a={};var b={};var f={};var d=c.bounds;a.x=d.width/2;a.y=d.height/2;b.x=e.x*d.width;b.y=e.y*d.height;f.x=(a.x-b.x);f.y=(a.y-b.y);return f},createInitialKeyframeValue:function(a,c,e,b){var d={};switch(c){case"anchorPoint":d.pointX=(a.anchorPoint.pointX-0.5)*a.bounds.width;d.pointY=(a.anchorPoint.pointY-0.5)*a.bounds.height;break;case"anchorPointZ":if(Prototype.Browser.Gecko||Prototype.Browser.IE||isChrome||isIE||isEdge){d.scalar=0}else{d.scalar=e.scalar+e.scalar}break;case"opacity":case"opacityMultiplier":d.scalar=a.opacity;break;case"hidden":d.scalar=a.hidden;break;case"position":d.pointX=a.affineTransform[4];d.pointY=a.affineTransform[5];break;case"zPosition":d.scalar=0;break;case"transform.scale":case"transform.scale.xy":case"transform.scale.x":case"transform.scale.y":d.scalar=a.initialState.scale;break;case"transform.rotation.z":d.scalar=a.initialState.rotation;case"transform":d.transform=e.transform;break;case"bounds":d.pointX=0;d.pointY=0;d.width=a.initialState.width;d.height=a.initialState.height;break;default:d.scalar=0;d.pointX=0;d.pointY=0;break}return d},createTimingFunctionForAction:function(c){var b="";var a=c.timingFunction;var d=c;if(typeof a==="object"){a=a.timingFunction;d=c.timingFunction}switch(a.toLowerCase()){case"easein":b="ease-in";break;case"easeout":b="ease-out";break;case"easeinout":case"easeineaseout":b="ease-in-out";break;case"custom":b="cubic-bezier("+d.timingControlPoint1x+","+d.timingControlPoint1y+","+d.timingControlPoint2x+","+d.timingControlPoint2y+")";break;case"linear":b="linear";break;default:b="linear";break}return b},createAnimationRuleForKeyframes:function(d){for(var n in this.keyAnimations){var f=this.keyAnimations[n];var e="layer"+d.layerId+"-"+escapeTextureId(n);var b;var h="";var o;if(n==="contents"){var m=this.roundNum(f.keyActions[0].startKeyframe);b=gShowController.animationManager.createAnimation(e+"-from");var l="0% {opacity: 1; "+kAnimationTimingFunctionPropertyName+": linear;}";var k="49.999% {opacity: 1; "+kAnimationTimingFunctionPropertyName+": linear;}";var j="50% {opacity: 0; "+kAnimationTimingFunctionPropertyName+": linear;}";var g="100% {opacity: 0; "+kAnimationTimingFunctionPropertyName+": linear;}";if(m!==0){k=((100-m)/2+m-this.kDelta)-this.kDelta+"% {opacity: 1; "+kAnimationTimingFunctionPropertyName+": linear;}";j=((100-m)/2+m)+"% {opacity: 0; "+kAnimationTimingFunctionPropertyName+": linear;}"}b.appendRule(l);b.appendRule(k);b.appendRule(j);b.appendRule(g);b=gShowController.animationManager.createAnimation(e+"-to");l="0% {opacity: 0; "+kAnimationTimingFunctionPropertyName+": linear;}";k="49.999% {opacity: 0; "+kAnimationTimingFunctionPropertyName+": linear;}";j="50% {opacity: 1; "+kAnimationTimingFunctionPropertyName+": linear;}";g="100% {opacity: 1; "+kAnimationTimingFunctionPropertyName+": linear;}";if(m!==0){k=((100-m)/2+m-this.kDelta)-this.kDelta+"% {opacity: 0; "+kAnimationTimingFunctionPropertyName+": linear;}";j=((100-m)/2+m)+"% {opacity: 1; "+kAnimationTimingFunctionPropertyName+": linear;}"}b.appendRule(l);b.appendRule(k);b.appendRule(j);b.appendRule(g);d.cssAnimationRules.push(e);continue}if(!isIE){b=gShowController.animationManager.createAnimation(e);for(var c=0,a=f.keyframes.length;c<a;c++){o=f.keyframes[c];h=this.createAnimationRuleForKeyframe(n,o,d)+" ";b.appendRule(h)}d.cssAnimationRules.push(e)}else{if(browserVersion>=10){for(var c=0,a=f.keyframes.length;c<a;c++){o=f.keyframes[c];h+=this.createAnimationRuleForKeyframe(n,o,d)+" "}gShowController.animationManager.styleSheet.insertRule(kKeyframesPropertyName+" "+e+" {"+h+"}",0);d.cssAnimationRules.push(e)}}}},createAnimationRuleForKeyframe:function(l,m,g){var j=m.keyframe;var f=m.keyName;var k=m.value;var n=m.timingFunction;var d;var c=g.transformOriginValue;var e=g.transformOriginZValue;var h="";if(c){h=kTransformOriginPropertyName+": "+c+";"}if(g.animationInfo.name==="apple:ca-swing"&&f==="hidden"){h=""}if(f==="hidden"){var a={scalar:-1};if(k.scalar==false){a.scalar=1}else{a.scalar=0}f="opacity";d=this.cssPropertyValueForActionValue(l,f,a)}else{d=this.cssPropertyValueForActionValue(l,f,k)}var b;b=this.cssPropertyNameForAction(f)+": "+d+"; "+(j<100?kAnimationTimingFunctionPropertyName+": "+n+";":"");var i=j+"% {"+h+b+"}";return i},cssPropertyValueForActionValue:function(b,a,c){switch(a){case"hidden":if(c.scalar==true){return"hidden"}else{return"visible"}case"anchorPoint":return c.pointX+"% "+c.pointY+"%";case"anchorPointZ":return c.scalar;case"position":return"translate("+c.pointX+"px,"+c.pointY+"px)";case"zPosition":if(b=="anchorPointZ"&&(Prototype.Browser.Gecko||navigator.userAgent.lastIndexOf("Chrome/")>0)){return"translateZ("+-c.scalar+"px)"}else{return"translateZ("+c.scalar+"px)"}case"translationEmphasis":return"translateX("+c.translationEmphasis[0]+"px) translateY("+c.translationEmphasis[1]+"px) translateZ("+c.translationEmphasis[2]+")";case"rotationEmphasis":return"rotateZ("+c.rotationEmphasis[6]+"rad)";case"scaleEmphasis":return"scale3d("+ensureScaleFactorNotZero(c.scaleEmphasis[3])+","+ensureScaleFactorNotZero(c.scaleEmphasis[4])+","+ensureScaleFactorNotZero(c.scaleEmphasis[5])+")";case"transform.scale":case"transform.scale.xy":return"scale("+ensureScaleFactorNotZero(c.scalar)+")";case"transform.scale.x":return"scaleX("+ensureScaleFactorNotZero(c.scalar)+")";case"transform.scale.y":return"scaleY("+ensureScaleFactorNotZero(c.scalar)+")";case"transform.rotation.x":return"rotateX("+c.scalar+"rad)";case"transform.rotation.y":return"rotateY("+c.scalar+"rad)";case"transform.rotation.z":case"transform.rotation":return"rotateZ("+c.scalar+"rad)";case"transform.translation":return"translateX("+c.pointX+"px) translateY("+c.pointY+"px)";case"transform.translation.x":return"translateX("+c.scalar+"px)";case"transform.translation.y":return"translateY("+c.scalar+"px)";case"transform.translation.z":return"translateZ("+c.scalar+"px)";case"isPlaying":case"opacity":case"opacityMultiplier":return c.scalar+"";case"transform":return"matrix3d("+c.transform+")";case"doubleSided":if(c.scalar==false){return"hidden"}else{return"visible"}case"contents":return c.texture;default:return"some value"}},cssPropertyNameForAction:function(a){switch(a){case"hidden":return kVisibilityPropertyName;case"anchorPoint":return kTransformOriginPropertyName;case"anchorPointZ":return kTransformOriginZPropertyName;case"opacityMultiplier":return kOpacityPropertyName;case"translationEmphasis":case"rotationEmphasis":case"scaleEmphasis":case"position":case"zPosition":case"transform":case"transform.scale":case"transform.scale.xy":case"transform.scale.x":case"transform.scale.y":case"transform.rotation.x":case"transform.rotation.y":case"transform.rotation.z":case"transform.rotation":case"transform.translation":case"transform.translation.x":case"transform.translation.y":case"transform.translation.z":case"bounds":return kTransformPropertyName;case"doubleSided":return kBackfaceVisibilityPropertyName;case"contents":return kBackgroundImagePropertyName;default:return a}}});
 
 
assets/player/KeynoteDHTMLPlayer.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:627d0e596d63740c4601cacda44fe91f76e37e9a3baf58ce2b752059b873c5a9
3
- size 11670
 
1
+ var kDeviceUnknown="deviceUnknown";var kDeviceDesktop="deviceDesktop";var kDeviceMobile="deviceMobile";var kModeUnknown="modeUnknown";var kModeDesktop="modeDesktop";var kModeMobile="modeMobile";var kBrowserUnknown="browserUnknown";var kBrowserDesktopSafari="browserDesktopSafari";var kBrowserMobileSafari="browserMobileSafari";var kOrientationUnknown="orientationUnknown";var kOrientationLandscape="orientationLandscape";var kOrientationPortrait="orientationPortrait";var kShowModeNormal=0;var kShowModeAutoplay=1;var kShowModeHyperlinksOnly=2;var kSoundTrackModePlayOnce=0;var kSoundTrackModeLooping=1;var kSoundTrackModeOff=2;var kOpacityPropertyName="opacity";var kVisibilityPropertyName="visibility";var kZIndexPropertyName="z-index";var kDisplayPropertyName="display";var kDisplayBlockPropertyValue="block";var kDisplayNonePropertyValue="none";var kTransformOriginTopLeftPropertyValue="top left";var kTransformOriginCenterPropertyValue="center";var kTransformStylePreserve3DPropertyValue="preserve-3d";var kTransformStyleFlatPropertyValue="flat";var kPositionAbsolutePropertyValue="absolute";var kPositionRelativePropertyValue="relative";var kBackfaceVisibilityHiddenPropertyValue="hidden";var kiPhoneDeviceWidth=320;var kiPhoneDeviceHeight=480;var kiPhoneLandscapeButtonBarHeight=32;var kiPhonePortraitButtonBarHeight=44;var kiPhoneUrlBarHeight=60;var kiPhoneStatusBarHeight=20;var kiPadDeviceWidth=768;var kiPadDeviceHeight=1024;var kiPadLandscapeButtonBarHeight=32;var kiPadPortraitButtonBarHeight=44;var kiPadUrlBarHeight=0;var kiPadStatusBarHeight=0;var kiPadAddressBarHeight=30;var kiPadBookmarksBarHeight=30;var kiPadMaxMoviesPerScene=20;var kMaxSceneDownloadWaitTime=60000;var kMaxScriptDownloadWaitTime=60000;var kWaitingIndicatorFadeOutDuration=2000;var kHideAddressBarDelay=3000;var kSceneLoadPollInterval=100;var kSceneLoadDisplaySpinnerTime=3000;var kSceneLoadDisplaySpinnerPollCount=kSceneLoadDisplaySpinnerTime/kSceneLoadPollInterval;var kSceneLoadGiveUpTime=60000;var kSceneLoadGiveUpPollCount=kSceneLoadGiveUpTime/kSceneLoadPollInterval;var kPropertyName_currentSlide="currentSlide";var kKeyCode_Plus=107;var kKeyCode_Minus=109;var kKeyCode_Dot=110;var kKeyCode_F11=122;var kKeyCode_F12=123;var kKeyCode_Hyphen=189;var kKeyCode_Equal=187;var kKeyCode_Period=190;var kKeyCode_Slash=191;var kKeyCode_Space=32;var kKeyCode_Escape=27;var kKeyCode_LeftArrow=37;var kKeyCode_UpArrow=38;var kKeyCode_RightArrow=39;var kKeyCode_DownArrow=40;var kKeyCode_OpenBracket=219;var kKeyCode_CloseBracket=221;var kKeyCode_Home=36;var kKeyCode_End=35;var kKeyCode_PageUp=33;var kKeyCode_PageDown=34;var kKeyCode_Return=13;var kKeyCode_N=78;var kKeyCode_P=80;var kKeyCode_Q=81;var kKeyCode_S=83;var kKeyCode_Delete=8;var kKeyCode_0=48;var kKeyCode_9=57;var kKeyCode_Numeric_0=96;var kKeyCode_Numeric_9=105;var kKeyModifier_Shift=1000;var kKeyModifier_Ctrl=2000;var kKeyModifier_Alt=3000;var kKeyModifier_Meta=4000;var kHelpPlacardMainTitle=CoreDocs.loc("Keyboard Shortcuts","Keyboard Shortcuts");var kHelpPlacardNavigationTitle=CoreDocs.loc("Navigation","Navigation");var kHelpPlacardOtherTitle=CoreDocs.loc("Other","Other");var kHelpPlacardAdvanceToNextBuild=CoreDocs.loc("Advance to next build","Advance to next build");var kHelpPlacardGoBackToPreviousBuild=CoreDocs.loc("Go back to previous build","Go back to previous build");var kHelpPlacardAdvanceAndSkipBuild=CoreDocs.loc("Advance and skip build","Advance and skip build");var kHelpPlacardAdvanceToNextSlide=CoreDocs.loc("Advance to next slide","Advance to next slide");var kHelpPlacardGoBackToPreviousSlide=CoreDocs.loc("Go back to previous slide","Go back to previous slide");var kHelpPlacardGoToFirstSlide=CoreDocs.loc("Go to first slide","Go to first slide");var kHelpPlacardGoToLastSlide=CoreDocs.loc("Go to last slide","Go to last slide");var kHelpPlacardQuitPresentationMode=CoreDocs.loc("Quit presentation mode","Quit presentation mode");var kHelpPlacardGoToSpecificSlide=CoreDocs.loc("Go to specific slide","Go to specific slide");var kHelpPlacardShowOrHideKeyboardShortcuts=CoreDocs.loc("Show or hide Keyboard Shortcuts","Show or hide Keyboard Shortcuts");var kHelpPlacardShowOrHideTheCurrentSlideNumber=CoreDocs.loc("Show or hide the current slide number","Show or hide the current slide number");var kUnableToReachiWorkTryAgain=CoreDocs.loc("Slide couldn't be displayed.\nDo you want to try again?","alert text to display when we timeout trying to download resources from iWork.com");var kSlideLabel=CoreDocs.loc("Slide","Prefix label for 'Slide I/N' display");var kTapOrSwipeToAdvance=CoreDocs.loc("Tap or Swipe to advance","Help string for bottom of portrait mode on mobile device");var kOSUnknown="unknown";var kOSWindows="Windows";var kOSMacOSX="Mac OS X";var kOSiOS="iOS";var gTheoreticalMaxPixelCount=1024*1024*3;var gSafeMaxPixelCount=gTheoreticalMaxPixelCount*0.9;var gShowController=null;var gDevice=kDeviceUnknown;var gBrowser=kBrowserUnknown;var gMode=kModeUnknown;var gIpad=false;var gOS=kOSUnknown;var browserPrefix,browserVersion;var userAgentString=window.navigator.userAgent;var isMacOS=window.navigator.platform.indexOf("Mac")!==-1;var isChrome=false;var isEdge=false;var isIE=false;if(userAgentString.lastIndexOf("Edge/")>0){isEdge=true;browserPrefix="webkit";browserVersion=12}else{if(userAgentString.lastIndexOf("Trident/")>0){isIE=true;browserPrefix="ms";var revisionStringIE=userAgentString.substring(userAgentString.lastIndexOf("rv"),userAgentString.lastIndexOf(")"));var revisionIE=[];if(revisionStringIE.lastIndexOf(":")>0){revisionIE=revisionStringIE.split(":");browserVersion=parseFloat(revisionIE[1])}else{if(revisionStringIE.lastIndexOf(" ")>0){revisionIE=revisionStringIE.split(" ");browserVersion=parseFloat(revisionIE[1])}else{browserVersion=11}}}else{if(Prototype.Browser.WebKit){browserPrefix="webkit";if(userAgentString.lastIndexOf("Chrome/")>0){isChrome=true}}else{if(Prototype.Browser.Gecko){browserPrefix="moz"}else{if(Prototype.Browser.IE){isIE=true;browserPrefix="ms";browserVersion=parseFloat(navigator.appVersion.split("MSIE")[1])}}}}}var kKeyframesPropertyName="@-"+browserPrefix+"-keyframes";var kAnimationNamePropertyName="-"+browserPrefix+"-animation-name";var kAnimationDurationPropertyName="-"+browserPrefix+"-animation-duration";var kAnimationDelayPropertyName="-"+browserPrefix+"-animation-delay";var kAnimationFillModePropertyName="-"+browserPrefix+"-animation-fill-mode";var kAnimationTimingFunctionPropertyName="-"+browserPrefix+"-animation-timing-function";var kAnimationIterationCountPropertyName="-"+browserPrefix+"-animation-iteration-count";var kTransformPropertyName="-"+browserPrefix+"-transform";var kTransformOriginPropertyName="-"+browserPrefix+"-transform-origin";var kTransformOriginZPropertyName="-"+browserPrefix+"-transform-origin-z";var kTransitionPropertyName="-"+browserPrefix+"-transition-property";var kTransitionDurationName="-"+browserPrefix+"-transition-duration";var kTransformStylePropertyName="-"+browserPrefix+"-transform-style";var kTransitionPropertyName="-"+browserPrefix+"-transition";var kTransitionEndEventName=browserPrefix+"TransitionEnd";var kAnimationEndEventName=browserPrefix+"AnimationEnd";var kPerspectivePropertyName="-"+browserPrefix+"-perspective";var kPerspectiveOriginPropertyName="-"+browserPrefix+"-perspective-origin";var kBackfaceVisibilityPropertyName="-"+browserPrefix+"-backface-visibility";var kBoxShadowPropertyName="-"+browserPrefix+"-box-shadow";var kBorderPropertyName="border";var kBackgroundImagePropertyName="background-image";var kEmphasisEffects=["apple:action-pop","apple:action-pulse","apple:action-blink","apple:action-flip","apple:action-bounce","apple:action-jiggle"];var kActionBuildKeyAnimations={"apple:action-opacity":["opacity"],"apple:action-motion-path":["position"],"apple:action-rotation":["transform.rotation.z"],"apple:action-scale":["transform.scale.x","transform.scale.y","anchorPoint","contents","bounds"],"apple:action-blink":["opacity"],"apple:action-bounce":["anchorPoint","transform.scale.y","transform.translation.y","transform.scale.x"],"apple:action-flip":["transform.rotation.y","transform.scale.xy"],"apple:action-jiggle":["transform.rotation.z"],"apple:action-pop":["transform.scale.xy"],"apple:action-pulse":["transform.scale.xy"]};var kSupportedWebGLEffects=["apple:wipe-iris","com.apple.iWork.Keynote.BUKAnvil","com.apple.iWork.Keynote.BUKTwist","com.apple.iWork.Keynote.BUKFlop","com.apple.iWork.Keynote.KLNColorPlanes","com.apple.iWork.Keynote.KLNFlame","com.apple.iWork.Keynote.KLNConfetti","com.apple.iWork.Keynote.KLNDiffuse","com.apple.iWork.Keynote.KNFireworks","com.apple.iWork.Keynote.KLNShimmer","com.apple.iWork.Keynote.KLNSparkle"];var useWebGL=true;var usePDF=true;var pdfScaleFactor=1;var kFullscreenChangeEventName=browserPrefix+"fullscreenchange";window.addEventListener("load",setupShowController,false);function static_url(a){return a}function setupShowController(){var a=isMobileSafari();if(a){gBrowser=kBrowserMobileSafari;gDevice=kDeviceMobile;gMode=kModeMobile;gIpad=isiPad()}else{gBrowser=kBrowserDesktopSafari;gDevice=kDeviceDesktop;gMode=kModeDesktop}debugMessage(kDebugSetupShowController,"================================================================================");debugMessage(kDebugSetupShowController,"=== S T A R T O F S E S S I O N ===");debugMessage(kDebugSetupShowController,"================================================================================");debugMessage(kDebugSetupShowController,"userAgent: "+navigator.userAgent);debugMessage(kDebugSetupShowController,"url: "+window.location.href);if(navigator.userAgent.match(/Windows/)){gOS=kOSWindows}var b=getUrlParameter("pixelLimit");if(b!=""){gSafeMaxPixelCount=1024*1024*parseInt(b)}if(navigator.userAgent.indexOf("deviceDesktop")!=-1){debugMessage(kDebugSetupShowController,"Device was '"+gDevice+"', overriding device to be 'deviceDesktop'");gDevice=kDeviceDesktop}if(navigator.userAgent.indexOf("deviceMobile")!=-1){debugMessage(kDebugSetupShowController,"Device was '"+gDevice+"', overriding device to be 'deviceMobile'");gDevice=kDeviceMobile}if(navigator.userAgent.indexOf("modeDesktop")!=-1){debugMessage(kDebugSetupShowController,"Mode was '"+gMode+"', overriding device to be 'modeDesktop'");gMode=kModeDesktop}if(navigator.userAgent.indexOf("modeMobile")!=-1){debugMessage(kDebugSetupShowController,"Mode was '"+gMode+"', overriding device to be 'modeMobile'");gMode=kModeMobile}debugMessage(kDebugSetupShowController," gDevice: "+gDevice);debugMessage(kDebugSetupShowController," gBrowser: "+gBrowser);debugMessage(kDebugSetupShowController," gMode: "+gMode);debugMessage(kDebugSetupShowController," gOS: "+gOS);gShowController=new ShowController();gShowController.displayManager.showWaitingIndicator();gShowController.delegate.setPlaybackReadyHandler(function(){if(usePDF){if(window.location.protocol==="file:"){PDFJS.disableWorker=true}PDFJS.workerSrc="./pdfjs/pdf_worker.js";PDFJS.cMapUrl="./pdfjs/web/cmaps/";PDFJS.cMapPacked=true;var c=document.createElement("canvas");var d=c.getContext("webgl")||c.getContext("experimental-webgl");if(!d){useWebGL=false}}gShowController.startShow()})}function extractDelegateFromUrlParameter(){var d=getUrlParameter("delegate");var a;if((d=="")||(d==null)||(typeof(d)=="undefined")){a=new NullDelegate()}else{var c=d.indexOf(".");a=window;while(c!=-1){var b=d.substring(0,c);a=a[b];d=d.substring(c+1);c=d.indexOf(".")}a=a[d]}return a}var NullDelegate=Class.create({initialize:function(){},showDidLoad:function(){},showExited:function(){history.go(-1)},propertyChanged:function(b,a){},setPlaybackReadyHandler:function(a){a()}});
 
 
assets/player/NarrationManager.js CHANGED
@@ -1,3 +1,179 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:bd6737a3c215ff66cafb45dee9d26cec8cdba574ecb50e959d054717dc43017d
3
- size 6410
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * NarrationManager.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2013 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var NarrationManager = Class.create({
10
+ initialize: function(recording) {
11
+ // recording movies in an array
12
+ this.movieSegments = recording.movieSegments;
13
+
14
+ // total time of this recording
15
+ this.duration = recording.duration;
16
+
17
+ // navigation, movie and pause in eventTracks array
18
+ this.eventTracks = recording.eventTracks;
19
+
20
+ // current navigation event index
21
+ this.currentNavigationEventIndex = 0;
22
+
23
+ // last scene index
24
+ this.lastSceneIndex = 0;
25
+
26
+ for (var i = 0, length = this.eventTracks.length; i < length; i++) {
27
+ var eventTrack = this.eventTracks[i];
28
+
29
+ if (eventTrack.type === "navigation") {
30
+ this.navigationEvents = eventTrack.events;
31
+ } else if (eventTrack.type === "movie") {
32
+ this.movieEvents = eventTrack.events;
33
+ } else if (eventTrack.type === "pause") {
34
+ this.pauseEvents = eventTrack.events;
35
+ }
36
+ }
37
+
38
+ },
39
+
40
+ start: function() {
41
+ // set up media resources
42
+ var audio = new Audio();
43
+ audio.src = "../" + this.movieSegments[0].url;
44
+
45
+ // observe play event
46
+ Event.observe(audio, "playing", this.handleAudioDidStart.bind(this));
47
+ Event.observe(audio, "ended", this.handleAudioDidEnd.bind(this, 0));
48
+
49
+ audio.play();
50
+ },
51
+
52
+ handleAudioDidStart: function() {
53
+ // audio has started, now navigate to the first navigation event
54
+ setTimeout(this.navigate(this.navigationEvents[0], true), 100);
55
+ },
56
+
57
+ handleAudioDidEnd: function(audioIndex) {
58
+ var nextAudioIndex = audioIndex + 1;
59
+
60
+ if (this.movieSegments[nextAudioIndex]) {
61
+ var audio = new Audio();
62
+ audio.src = "../" + this.movieSegments[nextAudioIndex].url;
63
+ audio.play();
64
+
65
+ Event.stopObserving(audio, "ended");
66
+ Event.observe(audio, "ended", this.handleAudioDidEnd.bind(this, nextAudioIndex));
67
+ }
68
+ },
69
+
70
+ navigate: function(event, startup) {
71
+ var sceneIndex = this.sceneIndexFromNavigationEvent(event);
72
+
73
+ if (event.animationPhase === "start") {
74
+ // if event's slideIndex has been changed from lastScene's slide
75
+ // check to see if this is our next scene to play
76
+ var isNextScene = false;
77
+
78
+ if (gShowController.script.loopSlideshow) {
79
+ if (this.lastSceneIndex === gShowController.script.numScenes - 1) {
80
+ if (sceneIndex === 0) {
81
+ isNextScene = true;
82
+ }
83
+ }
84
+ } else {
85
+ if (this.lastSceneIndex + 1 === sceneIndex) {
86
+ isNextScene = true;
87
+ }
88
+ }
89
+
90
+ if (isNextScene) {
91
+ if (gShowController.state === kShowControllerState_IdleAtInitialState) {
92
+ gShowController.playCurrentScene();
93
+ } else if (gShowController.state === kShowControllerState_IdleAtFinalState) {
94
+ gShowController.jumpToScene(this.lastSceneIndex, true);
95
+ }
96
+ } else {
97
+ // this is the slide we are jumping to
98
+ var slideIndexToJump = gShowController.scriptManager.slideIndexFromSceneIndex(sceneIndex);
99
+ var sceneIndexOfHyperlink = this.lastSceneIndex;
100
+
101
+ // get hyperlink from slide, find the first occurrence of slideId in hyperlinks
102
+ var hyperlinks = gShowController.script.events[sceneIndexOfHyperlink].hyperlinks;
103
+ var hyperlink;
104
+ var hyperlinkEvent;
105
+
106
+ for (var i = 0, length = hyperlinks.length; i < length; i++) {
107
+ hyperlink = hyperlinks[i];
108
+ hyperlinkEvent = hyperlink.events[event.slide];
109
+
110
+ if (hyperlinkEvent) {
111
+ break;
112
+ }
113
+ }
114
+
115
+ if (hyperlink) {
116
+ // call jumpToHyperlinkSlide to play hyperlink transition
117
+ gShowController.jumpToHyperlinkSlide(slideIndexToJump, hyperlink);
118
+ } else {
119
+ // if no hyperlink event is found for any reason, we still want to jump
120
+ gShowController.jumpToScene(sceneIndex, false);
121
+ }
122
+ }
123
+ } else if (event.animationPhase === "none" && startup == null) {
124
+ gShowController.jumpToScene(sceneIndex, false);
125
+ }
126
+
127
+ // if there is any more event then set it to run next
128
+ var nextEvent = this.navigationEvents[this.currentNavigationEventIndex + 1];
129
+
130
+ if (nextEvent == null) {
131
+ return;
132
+ }
133
+
134
+ // set timeout to navigate to next event
135
+ var duration = nextEvent.startTime - event.startTime;
136
+ setTimeout(this.navigate.bind(this, nextEvent), duration * 1000);
137
+
138
+ this.lastSceneIndex = sceneIndex;
139
+ this.currentNavigationEventIndex = this.currentNavigationEventIndex + 1;
140
+ },
141
+
142
+ handleCurrentSceneDidComplete: function(sceneIndexToJump) {
143
+ // scene did complete, jump to next scene so we have more time to set it up
144
+ gShowController.jumpToScene(sceneIndexToJump, false);
145
+ },
146
+
147
+ sceneIndexFromNavigationEvent: function(event) {
148
+ // return sceneIndex from navigation event
149
+ var slideId = event.slide;
150
+ var slideList = gShowController.script.slideList;
151
+ var newSlideIndex = -1;
152
+
153
+ for (var i = 0, length = slideList.length; i < length; i++) {
154
+ if (slideList[i] === slideId) {
155
+ newSlideIndex = i;
156
+ break;
157
+ }
158
+ }
159
+
160
+ var sceneIndex = gShowController.scriptManager.sceneIndexFromSlideIndex(newSlideIndex);
161
+ var newSceneIndex = event.eventIndex + sceneIndex;
162
+
163
+ return newSceneIndex;
164
+ },
165
+
166
+ slideIndexFromSlideId: function(slideId) {
167
+ var slideList = gShowController.slideList;
168
+ var slideIndex = -1;
169
+
170
+ for (var i = 0, length = slideList.length; i < length; i++) {
171
+ if (slideList[i] === slideId) {
172
+ slideIndex = i;
173
+ break;
174
+ }
175
+ }
176
+
177
+ return slideIndex;
178
+ }
179
+ });
assets/player/NavigatorController.js CHANGED
@@ -1,3 +1,325 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:6c9d1ecaee3f7047ea117646ef469d50122f9fbda76f260042387ec93b3a4d90
3
- size 12436
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * NavigatorController.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var NavigatorController = Class.create({
10
+ initialize: function(domNode) {
11
+ // root node for the navigator control
12
+ this.domNode = domNode;
13
+
14
+ // initialize an instance of NavigatorThumbnailSidebar object
15
+ this.thumbnailSidebar = new NavigatorThumbnailSidebar();
16
+
17
+ // initialize an instance of NavigatorThumbnailScroller object
18
+ this.thumbnailScroller = new NavigatorThumbnailScroller();
19
+
20
+ // initialize an instance of NavigatorThumbnailSelection object
21
+ this.thumbnailSelection = new NavigatorThumbnailSelection();
22
+
23
+ // initialize an instance of NavigatorThumbnailContainer object
24
+ this.thumbnailContainer = new NavigatorThumbnailContainer();
25
+
26
+ this.thumbnailSidebar.domNode.appendChild(this.thumbnailScroller.domNode);
27
+ this.thumbnailScroller.domNode.appendChild(this.thumbnailSelection.domNode);
28
+ this.thumbnailScroller.domNode.appendChild(this.thumbnailContainer.domNode);
29
+ this.domNode.appendChild(this.thumbnailSidebar.domNode);
30
+
31
+ // create left sidebar to react to events
32
+ this.leftSidebar = new NavigatorLeftSidebar();
33
+ this.domNode.appendChild(this.leftSidebar.domNode);
34
+
35
+ // mouse events
36
+ Event.observe(this.domNode, "click", this.handleClickEvent.bind(this));
37
+ Event.observe(this.leftSidebar.domNode, "mouseover", this.handleMouseOverEvent.bind(this));
38
+ Event.observe(this.domNode, "mouseleave", this.handleMouseOutEvent.bind(this));
39
+
40
+ // events
41
+ document.observe(kSlideIndexDidChangeEvent, this.handleSlideIndexDidChangeEvent.bind(this));
42
+ document.observe(kScriptDidDownloadEvent, this.handleScriptDidDownloadEvent.bind(this));
43
+
44
+ this.slideThumbnail = null;
45
+ },
46
+
47
+ initScrollbar: function(){
48
+ if (this.thumbnailScroller.domNode.scrollHeight > this.thumbnailScroller.domNode.offsetHeight) {
49
+ this.thumbnailScroller.domNode.style.width = "126px";
50
+ } else {
51
+ this.thumbnailScroller.domNode.style.width = "129px";
52
+ }
53
+
54
+ // adjust navigator width for IE
55
+ // see <rdar://problem/12511461> IE9/10: Navigator scroll bar touching slide thumbnails while in show mode
56
+ if (browserPrefix === "ms") {
57
+ this.domNode.style.width = "148px";
58
+ this.thumbnailSidebar.domNode.style.left = "-148px";
59
+ this.thumbnailSidebar.domNode.style.width = "137px";
60
+ this.thumbnailScroller.domNode.style.width = "137px";
61
+ }
62
+ },
63
+
64
+ handleClickEvent: function(event) {
65
+ if (gShowController.isRecording) {
66
+ return;
67
+ }
68
+
69
+ event = event || window.event;
70
+ var target = event.target || event.srcElement;
71
+ var slideNumber;
72
+
73
+ // stop event from propagating up
74
+ if (browserPrefix === "ms") {
75
+ event.cancelBubble = true;
76
+ } else {
77
+ event.stopPropagation();
78
+ }
79
+
80
+ while ((target.slideNumber == null) && target.nodeName.toLowerCase() != 'body') {
81
+ target = target.parentNode;
82
+ }
83
+
84
+ if (target.slideNumber) {
85
+ this.selectedSlideIndex = target.slideNumber;
86
+ this.select(this.selectedSlideIndex);
87
+ }
88
+ },
89
+
90
+ select: function(slideIndex) {
91
+ gShowController.jumpToSlide(slideIndex);
92
+ },
93
+
94
+ handleMouseOverEvent: function(event) {
95
+ event = event || window.event;
96
+
97
+ // do not show navigator when the show is starting
98
+ var x = 0;
99
+ var y = 0;
100
+ if (event.pageX || event.pageY) {
101
+ x = event.pageX;
102
+ y = event.pageY;
103
+ } else if (event.clientX || event.clientY) {
104
+ x = event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
105
+ y = event.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
106
+ }
107
+
108
+ if (x === 0 && y === 0) {
109
+ return;
110
+ }
111
+
112
+ // calculate thumbnailScroller scrollTop position
113
+ var position = this.selectedSlideIndex * 76;
114
+ var scrollTop = this.thumbnailScroller.domNode.scrollTop;
115
+ var height = this.thumbnailScroller.domNode.clientHeight;
116
+
117
+ if (scrollTop > position) {
118
+ this.thumbnailScroller.domNode.scrollTop = position;
119
+ } else if (scrollTop + height < position + 76) {
120
+ var minimumScrollingAmount = position - scrollTop - height + 76;
121
+ this.thumbnailScroller.domNode.scrollTop = this.thumbnailScroller.domNode.scrollTop + minimumScrollingAmount;
122
+ }
123
+
124
+ clearTimeout(this.navigatorTimeout);
125
+ this.navigatorTimeout = setTimeout(this.thumbnailSidebar.show.bind(this.thumbnailSidebar, this.leftSidebar), 400);
126
+ },
127
+
128
+ handleMouseOutEvent: function(event) {
129
+ clearTimeout(this.navigatorTimeout);
130
+
131
+ this.navigatorTimeout = setTimeout(this.thumbnailSidebar.hide.bind(this.thumbnailSidebar, this.leftSidebar), 400);
132
+ },
133
+
134
+ handleSlideIndexDidChangeEvent: function(event) {
135
+ this.selectedSlideIndex = event.memo.slideIndex;
136
+
137
+ this.thumbnailSelection.select(this.selectedSlideIndex);
138
+ },
139
+
140
+ handleScriptDidDownloadEvent: function(event) {
141
+ var script = event.memo.script;
142
+
143
+ for (var i = 0, length = script.slideList.length; i < length; i++) {
144
+ var slideId = script.slideList[i];
145
+
146
+ // initialize thumbnail item
147
+ var thumbnailItem = new NavigatorThumbnailItem();
148
+ thumbnailItem.domNode.slideNumber = i + 1;
149
+ thumbnailItem.numberNode.innerHTML = i + 1;
150
+ setElementProperty(thumbnailItem.domNode, "top", i * 76 + "px");
151
+ this.thumbnailContainer.addItem(thumbnailItem);
152
+
153
+ // do not request thumbnails when delegate will be providing
154
+ if (gShowController.delegate.getKPFJsonStringForShow == null) {
155
+ // create slide img object
156
+ var src = "../" + slideId + "/thumbnail.jpeg";
157
+ var img = document.createElement("img");
158
+ Event.observe(img, "load", this.updateThumbnail.bind(this, i, img));
159
+ img.src = src;
160
+ } else {
161
+ gShowController.delegate.loadTextureBySlideIndex(
162
+ i,
163
+ {
164
+ "type": "slideThumbnail",
165
+ "state":"outgoing"
166
+ },
167
+ (function (slideIndex, domNode){
168
+ this.updateThumbnail(slideIndex, domNode);
169
+ }).bind(this, i));
170
+ }
171
+ }
172
+
173
+ this.initScrollbar();
174
+ },
175
+
176
+ updateThumbnail: function(slideIndex, domNode){
177
+ var canvasContainer = this.thumbnailContainer.thumbnailItems[slideIndex].canvasContainer;
178
+
179
+ if (this.slideThumbnail == null) {
180
+ var originalSlideWidth = gShowController.script.originalSlideWidth;
181
+ var originalSlideHeight = gShowController.script.originalSlideHeight;
182
+ var aspectRatio = originalSlideWidth / originalSlideHeight;
183
+ var width, height;
184
+
185
+ if (aspectRatio >= 4/3) {
186
+ width = 88;
187
+ height = Math.ceil(88 * (1/aspectRatio));
188
+ } else {
189
+ width = Math.ceil(66 * aspectRatio);
190
+ height = 66;
191
+ }
192
+
193
+ this.slideThumbnail = {
194
+ width: width,
195
+ height: height,
196
+ top: Math.ceil((66 - height)/2),
197
+ left: Math.ceil((88 - width)/2),
198
+ scaleX: width / originalSlideWidth,
199
+ scaleY: height / originalSlideHeight
200
+ }
201
+ }
202
+
203
+ if (domNode.nodeName.toLowerCase() === "svg") {
204
+ domNode.firstElementChild.setAttribute("transform", "matrix(" + this.slideThumbnail.scaleX + ",0,0," + this.slideThumbnail.scaleY + ",0,0)");
205
+ }
206
+
207
+ domNode.setAttribute("style", kTransitionPropertyName + ":opacity; " + kTransitionDurationName + ":500; width:" + this.slideThumbnail.width + "px; height:" + this.slideThumbnail.height + "px; left:" + this.slideThumbnail.left + "px; top:" + this.slideThumbnail.top + "px; opacity: 0; position: absolute;");
208
+
209
+ // prevent the thumbnail from being dragged
210
+ domNode.setAttribute("draggable", false);
211
+
212
+ if (browserPrefix === "moz") {
213
+ Event.observe(domNode, "dragstart", function(e){e.preventDefault();});
214
+ }
215
+
216
+ canvasContainer.appendChild(domNode);
217
+ domNode.style.opacity = 1;
218
+ }
219
+ });
220
+
221
+ var NavigatorLeftSidebar = Class.create({
222
+ initialize: function() {
223
+ this.domNode = document.createElement("div");
224
+ this.domNode.setAttribute("class", "navigatorLeftSidebar");
225
+ }
226
+ });
227
+
228
+ var NavigatorThumbnailSidebar = Class.create({
229
+ initialize: function() {
230
+ // root node for the sidebar
231
+ this.domNode = document.createElement("div");
232
+ this.domNode.setAttribute("class", "navigatorThumbnailSidebar");
233
+ },
234
+
235
+ show: function(leftSidebar) {
236
+ leftSidebar.domNode.style.visibility = "hidden";
237
+ this.domNode.style.left = "0px";
238
+ gShowController.displayManager.navigatorIsShowing = true;
239
+ gShowController.displayManager.clearTimeoutForCursor();
240
+ },
241
+
242
+ hide: function(leftSidebar) {
243
+ leftSidebar.domNode.style.visibility = "visible";
244
+ this.domNode.style.left = "-140px";
245
+ gShowController.displayManager.navigatorIsShowing = false;
246
+ gShowController.displayManager.setTimeoutForCursor();
247
+ }
248
+
249
+ });
250
+
251
+ var NavigatorThumbnailScroller = Class.create({
252
+ initialize: function() {
253
+ // root node for the scroller
254
+ this.domNode = document.createElement("div");
255
+ this.domNode.setAttribute("class", "navigatorThumbnailScroller");
256
+ }
257
+ });
258
+
259
+ var NavigatorThumbnailSelection = Class.create({
260
+ initialize: function(params) {
261
+ this.domNode = document.createElement("div");
262
+ this.domNode.setAttribute("class", "navigatorThumbnailSelection");
263
+ },
264
+
265
+ select: function(slideIndex) {
266
+ this.domNode.style.top = 76 * slideIndex + "px";
267
+ this.domNode.style.display = "block";
268
+ }
269
+
270
+ });
271
+
272
+ var NavigatorThumbnailContainer = Class.create({
273
+ initialize: function() {
274
+ // thumbnail container domNode
275
+ this.domNode = document.createElement("div");
276
+ this.domNode.setAttribute("class", "navigatorThumbnailContainer");
277
+
278
+ // item container
279
+ this.thumbnailItems = [];
280
+ },
281
+
282
+ addItem: function(thumbnailItem) {
283
+ this.thumbnailItems.push(thumbnailItem);
284
+ this.domNode.appendChild(thumbnailItem.domNode);
285
+ }
286
+
287
+ });
288
+
289
+ var NavigatorThumbnailItem = Class.create({
290
+ initialize: function() {
291
+ // thumbnail item root
292
+ this.domNode = document.createElement("div");
293
+ this.domNode.setAttribute("class", "navigatorThumbnailItem");
294
+
295
+ // thumbnail content node
296
+ this.thumbnailContentNode = document.createElement("div");
297
+ this.thumbnailContentNode.setAttribute("style", "position: absolute; height: 76px; width: 119px;");
298
+
299
+ // number node
300
+ this.numberNode = document.createElement("div");
301
+ this.numberNode.setAttribute("style", "position: absolute; bottom: 1px; width: 20px; height: 20px; text-align: right; font-weight: bold; color: white;");
302
+
303
+ // image node
304
+ this.imageNode = document.createElement("div");
305
+ this.imageNode.setAttribute("style", "position: absolute; left: 24px; width: 95px; height: 76px;");
306
+
307
+ // thumb node
308
+ this.thumb = document.createElement("div");
309
+ this.thumb.setAttribute("style", "position: absolute; top: 4px; width: 90px; height: 68px;");
310
+
311
+ // create canvas container object
312
+ this.canvasContainer = document.createElement("div");
313
+ this.canvasContainer.setAttribute("class", "navigatorThumbnailItemCanvasContainer");
314
+
315
+ // add thumbnail image
316
+ this.thumb.appendChild(this.canvasContainer);
317
+ this.imageNode.appendChild(this.thumb);
318
+
319
+ this.thumbnailContentNode.appendChild(this.numberNode);
320
+ this.thumbnailContentNode.appendChild(this.imageNode);
321
+
322
+ this.domNode.appendChild(this.thumbnailContentNode);
323
+ }
324
+
325
+ });
assets/player/OrientationController.js CHANGED
@@ -1,3 +1,40 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:f347818ecd75ccd374b981089305dd496a6427e81ba62e155d04bd9b2bc633f9
3
- size 1214
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * OrientationController.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Responsibility: Tungwei Cheng
6
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var kOrientationChangedEvent = "OrientationController:OrientationChangedEvent";
10
+
11
+ var OrientationController = Class.create({
12
+ initialize: function() {
13
+ if (gDevice == kDeviceMobile) {
14
+ Event.observe(window, "orientationchange", this.handleDeviceOrientationChangeEvent.bind(this));
15
+ this.handleDeviceOrientationChangeEvent();
16
+ }
17
+
18
+ this.orientation = kOrientationUnknown;
19
+ },
20
+
21
+ handleDeviceOrientationChangeEvent: function(event) {
22
+ var orientationInDegrees = window.orientation;
23
+ var newOrientation = kOrientationUnknown;
24
+
25
+ if ((orientationInDegrees === 0) || (orientationInDegrees === 180)) {
26
+ newOrientation = kOrientationPortrait;
27
+ } else {
28
+ newOrientation = kOrientationLandscape;
29
+ }
30
+ this.changeOrientation(newOrientation);
31
+ },
32
+
33
+ changeOrientation: function(newOrientation) {
34
+ this.orientation = newOrientation;
35
+
36
+ document.fire(kOrientationChangedEvent, {
37
+ orientation: this.orientation
38
+ });
39
+ }
40
+ });
assets/player/ScriptManager.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:1a581c64572e658d757efaed895f2d374231bb1d29efb30b1c193de87332fb6d
3
- size 24503
 
1
+ var kShowSizeDidChangeEvent="ScriptManager:ShowSizeDidChangeEvent";var kScriptDidDownloadEvent="ScriptManager:ScriptDidDownloadEvent";var kScriptDidNotDownloadEvent="ScriptManager:ScriptDidNotDownloadEvent";var kSlideDidDownloadEvent="SlideManager:SlideDidDownloadEvent";var kSlideDidNotDownloadEvent="SlideManager:SlideDidNotDownloadEvent";var ScriptManager=Class.create({initialize:function(a){this.script=null;this.showUrl=a;this.slideManager=null;document.observe(kSlideDidDownloadEvent,this.handleSlideDidDownloadEvent.bind(this));document.observe(kSlideDidNotDownloadEvent,this.handleSlideDidDownloadEvent.bind(this))},handleSlideDidDownloadEvent:function(c){var k=true;for(var l in this.slideManager.slides){if(this.slideManager.slides.hasOwnProperty(l)){if(!this.slideManager.slides[l].downloaded){k=false;break}}}if(k){this.script.events=[];this.script.originalEvents=[];this.script.slideIndexFromSceneIndexLookup={};this.script.sceneIndexFromSlideIndexLookup={};this.script.slides={};this.script.originalSlides={};var m,g,h,f,j=0,b=0,a=0;for(var l in this.slideManager.slides){if(this.slideManager.slides.hasOwnProperty(l)){h=this.slideManager.slides[l].script;f=this.slideManager.slides[l].originalScript;m=h.events;g=f.events;this.script.slides[l]=h;this.script.originalSlides[l]=f;this.script.sceneIndexFromSlideIndexLookup[j]=b;for(var e=0,d=m.length;e<d;e++){this.script.events.push(m[e]);this.script.originalEvents.push(g[e]);this.script.slideIndexFromSceneIndexLookup[a]=j;a+=1}j+=1;b=a}}this.script.numScenes=this.script.events.length;this.script.lastSceneIndex=this.script.numScenes-1;this.script.lastSlideIndex=this.script.slideList.length-1;this.script.originalSlideWidth=this.script.slideWidth;this.script.originalSlideHeight=this.script.slideHeight;if(isIE||isEdge){this.adjustScriptForIE()}else{this.adjustScript()}if(this.delegate.setViewScale){this.applyScaleFactor();this.delegate.setViewScale(this.scaleFactor)}document.fire(kScriptDidDownloadEvent,{script:this.script,delegate:this.delegate});document.fire(kShowSizeDidChangeEvent,{width:this.script.slideWidth,height:this.script.slideHeight})}},adjustScript:function(){for(var c=0,f=this.script.events.length;c<f;c++){var d=this.script.events[c];var e=this.script.originalEvents[c];for(var h=0,o=d.effects.length;h<o;h++){var s=d.effects[h];var m=e.effects[h];this.adjustEffects(s,m);this.adjustEmphasisBuilds(s,m);if(isChrome){this.adjustEffectsForChrome(s,m)}if(browserPrefix==="moz"){this.adjustEffectsForFirefox(s,m)}}for(var h=0,b=d.hyperlinks.length;h<b;h++){var q=d.hyperlinks[h];var n=e.hyperlinks[h];for(var r in q.events){var k=q.events[r];var l=n.events[r];for(var g=0,o=k.effects.length;g<o;g++){var p=k.effects[g];var a=l.effects[g];this.adjustEffects(p,a);this.adjustEmphasisBuilds(p,a);if(isChrome){this.adjustEffectsForChrome(s,m)}if(browserPrefix==="moz"){this.adjustEffectsForFirefox(s,m)}}}}}},adjustEffects:function(d,a){switch(d.name){case"com.apple.iWork.Keynote.BLTBlinds":if(d.type==="transition"){var c=a.baseLayer.layers[0];var f=d.baseLayer.layers[0];f.layers.splice(0,2);c.layers.splice(0,2)}break;case"apple:apple-grid":var c=a.baseLayer.layers[0];var f=d.baseLayer.layers[0];f.layers.splice(0,2);c.layers.splice(0,2);break;case"com.apple.iWork.Keynote.BLTSwoosh":var c=a.baseLayer.layers[0];var f=d.baseLayer.layers[0];if(d.type==="transition"){f.layers[1].layers[0].layers.splice(0,1);c.layers[1].layers[0].layers.splice(0,1);var b=c.layers[1];c.layers[1]=c.layers[2];c.layers[2]=b;var e=f.layers[1];f.layers[1]=f.layers[2];f.layers[2]=e}break;default:break}},adjustEmphasisBuilds:function(q,o){switch(q.name){case"apple:action-jiggle":var m=o.baseLayer.layers[0];var n=q.baseLayer.layers[0];if(!m.animations[0]){m=o.baseLayer.layers[0].layers[0];n=q.baseLayer.layers[0].layers[0]}var b=m.animations[0];var f=n.animations[0];var a=f.animations.length;for(var h=0;h<a;h++){var l=Math.ceil(f.duration/f.animations[h].duration);for(var g=0;g<l-1;g++){var p=JSON.parse(JSON.stringify(b.animations[h]));var e=JSON.parse(JSON.stringify(f.animations[h]));p.beginTime=b.animations[h].duration*(g+1);e.beginTime=f.animations[h].duration*(g+1);m.animations[0].animations.push(p);n.animations[0].animations.push(e);if(g===l-2){p.duration=f.duration-p.beginTime;e.duration=f.duration-e.beginTime;if(f.animations[h].property==="transform.rotation.z"){p.to.scalar=0;e.to.scalar=0}else{if(f.animations[h].property==="position"){p.to.pointX=(p.from.pointX+p.to.pointX)/2;e.to.pointX=(e.from.pointX+e.to.pointX)/2}}}}}break;default:break}for(var d=0,c=q.effects.length;d<c;d++){this.adjustEmphasisBuilds(q.effects[d],o.effects[d])}},adjustEffectsForChrome:function(m,o){switch(m.name){case"apple:fall":var k=o.baseLayer.layers[0];var g=m.baseLayer.layers[0];var l=k.layers[1].animations[0].beginTime;var i=k.layers[1].animations[0].duration;if(!k.layers[1].animations[0].animations){break}var d={animations:[],beginTime:l,duration:i-0.01,fillMode:"forwards",from:{scalar:1},property:"transform.translation.z",timingFunction:"linear",to:{scalar:1}};var n={animations:[],beginTime:i-0.01,duration:0.01,fillMode:"forwards",from:{scalar:-1},property:"transform.translation.z",timingFunction:"linear",to:{scalar:-1}};k.layers[1].animations[0].animations.push(d);g.layers[1].animations[0].animations.push(d);k.layers[1].animations[0].animations.push(n);g.layers[1].animations[0].animations.push(n);break;case"apple:scale":var k=o.baseLayer.layers[0];var g=m.baseLayer.layers[0];if(k.layers[0].animations.length>0){var t=k.layers[0];k.layers[0]=k.layers[1];k.layers[1]=t;k.layers[1].initialState.hidden=true;var p=g.layers[0];g.layers[0]=g.layers[1];g.layers[1]=p;g.layers[1].initialState.hidden=true;var l=k.layers[1].animations[0].beginTime;var i=k.layers[1].animations[0].duration;var q=k.layers[1].animations[0].animations[0].beginTime;var a=k.layers[1].animations[0].animations[0].duration;var c;if(l==q){for(var r=0,h=k.layers[1].animations[0].animations.length;r<h;r++){if(k.layers[1].animations[0].animations[r].property==="transform.translation.z"){k.layers[1].animations[0].animations.splice(r,1);g.layers[1].animations[0].animations.splice(r,1)}}c={animations:[],beginTime:l,duration:i,fillMode:"forwards",from:{scalar:false},property:"hidden",timingFunction:"linear",to:{scalar:false}};k.layers[1].animations[0].animations.push(c);g.layers[1].animations[0].animations.push(c)}else{for(var r=0,h=k.layers[1].animations[0].animations[0].animations.length;r<h;r++){if(k.layers[1].animations[0].animations[0].animations[r].property==="transform.translation.z"){k.layers[1].animations[0].animations[0].animations.splice(r,1);g.layers[1].animations[0].animations[0].animations.splice(r,1)}}c={animations:[],beginTime:k.layers[1].animations[0].animations[0].animations[0].beginTime+0.03,duration:k.layers[1].animations[0].animations[0].animations[0].duration,fillMode:"forwards",from:{scalar:false},property:"hidden",timingFunction:"linear",to:{scalar:false}};k.layers[1].animations[0].animations[0].animations.push(c);g.layers[1].animations[0].animations[0].animations.push(c)}}break;case"com.apple.iWork.Keynote.KLNSwap":var k=o.baseLayer.layers[0];var g=m.baseLayer.layers[0];var a,f,s,b,e;if(k.layers[1].animations[0].animations.length>1){for(var r=0,h=k.layers[1].animations[0].animations.length;r<h;r++){b=k.layers[1].animations[0].animations[r];e=g.layers[1].animations[0].animations[r];if(b.property==="opacity"){break}}a=k.layers[1].animations[0].duration}else{for(var r=0,h=k.layers[1].animations[0].animations[0].animations.length;r<h;r++){b=k.layers[1].animations[0].animations[0].animations[r];e=g.layers[1].animations[0].animations[0].animations[r];if(b.property==="opacity"){break}}a=k.layers[1].animations[0].animations[0].duration}f=a*0.4;s=a*0.4;b.to.scalar=0;b.beginTime=f;b.duration=s;e.to.scalar=0;e.beginTime=f;e.duration=s;break;default:break}},adjustEffectsForFirefox:function(r,m){switch(r.name){case"apple:scale":var q=m.baseLayer.layers[0];var k=r.baseLayer.layers[0];if(q.layers[0].animations.length>0){var l=q.layers[0];q.layers[0]=q.layers[1];q.layers[1]=l;q.layers[1].initialState.hidden=true;var f=k.layers[0];k.layers[0]=k.layers[1];k.layers[1]=f;k.layers[1].initialState.hidden=true;var a=q.layers[1].animations[0].beginTime;var c=q.layers[1].animations[0].duration;var h=q.layers[1].animations[0].animations[0].beginTime;var e=q.layers[1].animations[0].animations[0].duration;var i;if(a==h){for(var g=0,o=q.layers[1].animations[0].animations.length;g<o;g++){if(q.layers[1].animations[0].animations[g].property==="transform.translation.z"){q.layers[1].animations[0].animations.splice(g,1);k.layers[1].animations[0].animations.splice(g,1)}}i={animations:[],beginTime:a,duration:c,fillMode:"forwards",from:{scalar:false},property:"hidden",timingFunction:"linear",to:{scalar:false}};q.layers[1].animations[0].animations.push(i);k.layers[1].animations[0].animations.push(i)}else{for(var g=0,o=q.layers[1].animations[0].animations[0].animations.length;g<o;g++){if(q.layers[1].animations[0].animations[0].animations[g].property==="transform.translation.z"){q.layers[1].animations[0].animations[0].animations.splice(g,1);k.layers[1].animations[0].animations[0].animations.splice(g,1)}}i={animations:[],beginTime:q.layers[1].animations[0].animations[0].animations[0].beginTime+0.03,duration:q.layers[1].animations[0].animations[0].animations[0].duration,fillMode:"forwards",from:{scalar:false},property:"hidden",timingFunction:"linear",to:{scalar:false}};q.layers[1].animations[0].animations[0].animations.push(i);k.layers[1].animations[0].animations[0].animations.push(i)}}break;case"com.apple.iWork.Keynote.KLNSwap":var q=m.baseLayer.layers[0];var k=r.baseLayer.layers[0];var e,d,n,b,p;if(q.layers[1].animations[0].animations.length>1){for(var g=0,o=q.layers[1].animations[0].animations.length;g<o;g++){b=q.layers[1].animations[0].animations[g];p=k.layers[1].animations[0].animations[g];if(b.property==="opacity"){break}}e=q.layers[1].animations[0].duration}else{for(var g=0,o=q.layers[1].animations[0].animations[0].animations.length;g<o;g++){b=q.layers[1].animations[0].animations[0].animations[g];p=k.layers[1].animations[0].animations[0].animations[g];if(b.property==="opacity"){break}}e=q.layers[1].animations[0].animations[0].duration}d=e*0.4;n=e*0.4;b.to.scalar=0;b.beginTime=d;b.duration=n;p.to.scalar=0;p.beginTime=d;p.duration=n;break;default:break}},adjustScriptForIE:function(){for(var c=0,f=this.script.events.length;c<f;c++){var d=this.script.events[c];var e=this.script.originalEvents[c];for(var h=0,o=d.effects.length;h<o;h++){var s=d.effects[h];var m=e.effects[h];this.adjustEffectsForIE(s,m);this.adjustEmphasisBuilds(s,m)}for(var h=0,b=d.hyperlinks.length;h<b;h++){var q=d.hyperlinks[h];var n=e.hyperlinks[h];for(var r in q.events){var k=q.events[r];var l=n.events[r];for(var g=0,o=k.effects.length;g<o;g++){var p=k.effects[g];var a=l.effects[g];this.adjustEffectsForIE(p,a);this.adjustEmphasisBuilds(p,a)}}}}},adjustEffectsForIE:function(r,m){switch(r.name){case"apple:bounce":case"apple:slide":case"apple:pivot":case"apple:scale":var q=m.baseLayer.layers[0];var k=r.baseLayer.layers[0];if(q.layers[0].animations.length>0){var l=q.layers[0];q.layers[0]=q.layers[1];q.layers[1]=l;q.layers[1].initialState.hidden=true;var f=k.layers[0];k.layers[0]=k.layers[1];k.layers[1]=f;k.layers[1].initialState.hidden=true;var a=q.layers[1].animations[0].beginTime;var c=q.layers[1].animations[0].duration;var h=q.layers[1].animations[0].animations[0].beginTime;var e=q.layers[1].animations[0].animations[0].duration;var i;if(a==h){for(var g=0,o=q.layers[1].animations[0].animations.length;g<o;g++){if(q.layers[1].animations[0].animations[g].property==="transform.translation.z"){q.layers[1].animations[0].animations.splice(g,1);k.layers[1].animations[0].animations.splice(g,1)}}i={animations:[],beginTime:a,duration:c,fillMode:"forwards",from:{scalar:false},property:"hidden",timingFunction:"linear",to:{scalar:false}};q.layers[1].animations[0].animations.push(i);k.layers[1].animations[0].animations.push(i)}else{for(var g=0,o=q.layers[1].animations[0].animations[0].animations.length;g<o;g++){if(q.layers[1].animations[0].animations[0].animations[g].property==="transform.translation.z"){q.layers[1].animations[0].animations[0].animations.splice(g,1);k.layers[1].animations[0].animations[0].animations.splice(g,1)}}i={animations:[],beginTime:q.layers[1].animations[0].animations[0].animations[0].beginTime+0.03,duration:q.layers[1].animations[0].animations[0].animations[0].duration,fillMode:"forwards",from:{scalar:false},property:"hidden",timingFunction:"linear",to:{scalar:false}};q.layers[1].animations[0].animations[0].animations.push(i);k.layers[1].animations[0].animations[0].animations.push(i)}}break;case"apple:doorway":var q=m.baseLayer.layers[0];var k=r.baseLayer.layers[0];var a=q.layers[0].animations[0].beginTime;var c=q.layers[0].animations[0].duration;var h=q.layers[0].animations[0].animations[0].beginTime;var e=q.layers[0].animations[0].animations[0].duration;q.layers[0].layers=[];q.layers[0].animations=[];k.layers[0].layers=[];k.layers[0].animations=[];if(a==h){q.layers[1].animations[0].animations[0].beginTime=h;q.layers[1].animations[0].animations[0].duration=e;k.layers[1].animations[0].animations[0].beginTime=h;k.layers[1].animations[0].animations[0].duration=e}else{q.layers[1].animations[0].animations[0].animations[0].duration=e;k.layers[1].animations[0].animations[0].animations[0].duration=e}q.layers.splice(2,1);k.layers.splice(2,1);break;case"com.apple.iWork.Keynote.BLTBlinds":case"apple:3D-cube":case"com.apple.iWork.Keynote.BLTReflection":case"apple:revolve":case"com.apple.iWork.Keynote.BLTRevolvingDoor":var q=m.baseLayer.layers[0];var k=r.baseLayer.layers[0];var p;p={animations:[],beginTime:0,duration:m.duration,fillMode:"both",from:{scalar:1},property:"opacity",timingFunction:"easeInEaseOut",to:{scalar:0}};q.layers[0].layers=[];q.layers[0].animations=[];q.layers[1].layers=[];q.layers[1].animations=[];q.layers[1].animations.push(p);k.layers[0].layers=[];k.layers[0].animations=[];k.layers[1].layers=[];k.layers[1].animations=[];k.layers[1].animations.push(p);if(r.name==="com.apple.iWork.Keynote.BLTBlinds"){q.layers[0].initialState.hidden=false;q.layers[1].initialState.hidden=false;k.layers[0].initialState.hidden=false;k.layers[1].initialState.hidden=false;q.layers.splice(2,q.layers.length-2);k.layers.splice(2,k.layers.length-2)}break;case"com.apple.iWork.Keynote.KLNSwap":var q=m.baseLayer.layers[0];var k=r.baseLayer.layers[0];var e,d,n,b,p;if(q.layers[1].animations[0].animations.length>1){for(var g=0,o=q.layers[1].animations[0].animations.length;g<o;g++){b=q.layers[1].animations[0].animations[g];p=k.layers[1].animations[0].animations[g];if(b.property==="opacity"){break}}e=q.layers[1].animations[0].duration}else{for(var g=0,o=q.layers[1].animations[0].animations[0].animations.length;g<o;g++){b=q.layers[1].animations[0].animations[0].animations[g];p=k.layers[1].animations[0].animations[0].animations[g];if(b.property==="opacity"){break}}e=q.layers[1].animations[0].animations[0].duration}d=e*0.4;n=e*0.4;b.to.scalar=0;b.beginTime=d;b.duration=n;p.to.scalar=0;p.beginTime=d;p.duration=n;break;case"apple:FlipThrough":var q=m.baseLayer.layers[0];var k=r.baseLayer.layers[0];if(q.layers[0].animations.length>0){var l=JSON.parse(JSON.stringify(q.layers[1]));q.layers.splice(0,0,l);var f=JSON.parse(JSON.stringify(k.layers[1]));k.layers.splice(0,0,f);var a=q.layers[1].animations[0].beginTime;var c=q.layers[1].animations[0].duration;var h=q.layers[1].animations[0].animations[0].beginTime;var e=q.layers[1].animations[0].animations[0].duration;var i;if(a==h){for(var g=0,o=q.layers[1].animations[0].animations.length;g<o;g++){if(q.layers[1].animations[0].animations[g].property==="transform.translation.z"){q.layers[1].animations[0].animations.splice(g,1);k.layers[1].animations[0].animations.splice(g,1)}}i={animations:[],beginTime:a+c/2,duration:c/2,fillMode:"forwards",from:{scalar:true},property:"hidden",timingFunction:"linear",to:{scalar:true}};q.layers[2].animations[0].animations.push(i);k.layers[2].animations[0].animations.push(i)}else{for(var g=0,o=q.layers[1].animations[0].animations[0].animations.length;g<o;g++){if(q.layers[1].animations[0].animations[0].animations[g].property==="transform.translation.z"){q.layers[1].animations[0].animations[0].animations.splice(g,1);k.layers[1].animations[0].animations[0].animations.splice(g,1)}}i={animations:[],beginTime:q.layers[2].animations[0].animations[0].animations[0].beginTime+q.layers[2].animations[0].animations[0].animations[0].duration/2,duration:q.layers[2].animations[0].animations[0].animations[0].duration/2,fillMode:"forwards",from:{scalar:true},property:"hidden",timingFunction:"linear",to:{scalar:true}};q.layers[2].animations[0].animations[0].animations.push(i);k.layers[2].animations[0].animations[0].animations.push(i)}}break;default:break}},handleSlideDidNotDownloadEvent:function(a){this.scriptDidNotDownload.bind(this)},reapplyScaleFactor:function(){if(this.delegate.setViewScale){this.applyScaleFactor();this.delegate.setViewScale(this.scaleFactor)}},applyScaleFactorForAnimation:function(c,b,g){var h=c.property;if(c.path){for(var e=0,k=c.path.length;e<k;e++){var j=c.path[e].points;var d=b.path[e].points;j[0][0]=d[0][0]*g;j[0][1]=d[0][1]*g}}switch(h){case"anchorPointZ":case"zPosition":case"transform.translation.x":case"transform.translation.y":if(c.from){c.from.scalar=b.from.scalar*g}if(c.to){c.to.scalar=b.to.scalar*g}if(c.values){for(var e=0,f=c.values.length;e<f;e++){c.values[e].scalar=b.values[e].scalar*g}}break;case"transform.translation.z":if(c.from&&c.from.scalar!=1&&c.from.scalar!=0.01){c.from.scalar=b.from.scalar*g}if(c.to&&c.to.scalar!=1&&c.to.scalar!=0.01){c.to.scalar=b.to.scalar*g}if(c.values){for(var e=0,f=c.values.length;e<f;e++){c.values[e].scalar=b.values[e].scalar*g}}break;case"position":case"transform.translation":if(c.from){c.from.pointX=b.from.pointX*g;c.from.pointY=b.from.pointY*g}if(c.to){c.to.pointX=b.to.pointX*g;c.to.pointY=b.to.pointY*g}if(c.values){for(var e=0,f=c.values.length;e<f;e++){c.values[e].pointX=b.values[e].pointX*g;c.values[e].pointY=b.values[e].pointY*g}}break;case"transform":if(c.from){c.from.transform[12]=b.from.transform[12]*g;c.from.transform[13]=b.from.transform[13]*g;c.from.transform[14]=b.from.transform[14]*g}if(c.to){c.to.transform[12]=b.to.transform[12]*g;c.to.transform[13]=b.to.transform[13]*g;c.to.transform[14]=b.to.transform[14]*g}if(c.values){for(var e=0,f=c.values.length;e<f;e++){c.values[e].transform[12]=b.values[e].transform[12]*g;c.values[e].transform[13]=b.values[e].transform[13]*g;c.values[e].transform[14]=b.values[e].transform[14]*g}}break;case"bounds":if(c.from){c.from.width=b.from.width*g;c.from.height=b.from.height*g}if(c.to){c.to.width=b.to.width*g;c.to.height=b.to.height*g}break;case"transform.scale.xy":case"transform.scale.x":case"transform.scale.y":break}if(c.animations){for(var e=0,a=c.animations.length;e<a;e++){this.applyScaleFactorForAnimation(c.animations[e],b.animations[e],g)}}},applyScaleFactorForLayer:function(g,f,l,k,j,h){var b=g.initialState;var d=f.initialState;var c=d.contentsRect;b.affineTransform[4]=d.affineTransform[4]*l;b.affineTransform[5]=d.affineTransform[5]*l;b.width=d.width*l;b.height=d.height*l;b.position.pointX=d.position.pointX*l;b.position.pointY=d.position.pointY*l;switch(k){case"com.apple.iWork.Keynote.BLTBlinds":case"com.apple.iWork.Keynote.BLTMosaicFlip":this.adjustForCropAnimation(b,c,h.particleCount.x,h.particleCount.y);break;default:break}if(g.animations){for(var e=0,a=g.animations.length;e<a;e++){this.applyScaleFactorForAnimation(g.animations[e],f.animations[e],l)}}for(var e=0,a=g.layers.length;e<a;e++){this.applyScaleFactorForLayer(g.layers[e],f.layers[e],l,k,j,h)}},applyScaleFactorForBaseLayer:function(b,c,f){var a=b.initialState;var g=c.initialState;a.affineTransform[4]=g.affineTransform[4]*f;a.affineTransform[5]=g.affineTransform[5]*f;a.width=g.width*f;a.height=g.height*f;a.position.pointX=g.position.pointX*f;a.position.pointY=g.position.pointY*f;for(var d=0,e=b.layers.length;d<e;d++){this.applyScaleFactorForBaseLayer(b.layers[d],c.layers[d],f)}},applyScaleFactor:function(){var y=this.script.originalSlideWidth;var F=this.script.originalSlideHeight;var s=window.innerWidth;var B=window.innerHeight;var L=scaleSizeWithinSize(y,F,s,B);var f=L.width;var o=L.height;var k=o/F;this.scaleFactor=k;this.script.slideWidth=this.script.originalSlideWidth*k;this.script.slideHeight=this.script.originalSlideHeight*k;for(var Q=0,q=this.script.events.length;Q<q;Q++){var T=this.script.events[Q];var u=this.script.originalEvents[Q];var K=this.script.slideIndexFromSceneIndexLookup[Q];var I=this.script.slideList[K];this.applyScaleFactorForBaseLayer(T.baseLayer,u.baseLayer,k);for(var O=0,c=T.effects.length;O<c;O++){var M=T.effects[O];var n=u.effects[O];var C={};if(M.name==="com.apple.iWork.Keynote.BLTMosaicFlip"||M.name==="com.apple.iWork.Keynote.BLTBlinds"){var G=0,g=0;for(var b=0,J=M.baseLayer.layers[0].layers.length;b<J;b++){var d=n.baseLayer.layers[0].layers[b];var e=d.initialState.contentsRect;var l=Math.round(e.x/e.width);var z=Math.round(e.y/e.height);if(l>G){G=l}if(z>g){g=z}}C.particleCount={x:G+1,y:g+1}}this.applyScaleFactorForLayer(M.baseLayer,n.baseLayer,k,M.name,I,C)}for(var O=0,t=T.hyperlinks.length;O<t;O++){var h=T.hyperlinks[O];var w=u.hyperlinks[O];var A=h.targetRectangle;var D=w.targetRectangle;A.y=D.y*k;A.x=D.x*k;A.width=D.width*k;A.height=D.height*k;for(var H in h.events){var m=h.events[H];var x=w.events[H];for(var N=0,c=m.effects.length;N<c;N++){var R=m.effects[N];var S=x.effects[N];var C={};if(R.name==="com.apple.iWork.Keynote.BLTMosaicFlip"||R.name==="com.apple.iWork.Keynote.BLTBlinds"){var G=0,g=0;for(var b=0,J=R.baseLayer.layers[0].layers.length;b<J;b++){var d=R.baseLayer.layers[0].layers[b];var e=d.initialState.contentsRect;var l=Math.round(e.x/e.width);var z=Math.round(e.y/e.height);if(l>G){G=l}if(z>g){g=z}}C.particleCount={x:G+1,y:g+1}}this.applyScaleFactorForLayer(R.baseLayer,S.baseLayer,k,R.name,I,C)}}}}for(var p in this.script.slides){if(this.script.slides.hasOwnProperty(p)){var a=this.script.slides[p];var v=this.script.originalSlides[p];for(var E in a.assets){if(a.assets.hasOwnProperty(E)){var r=a.assets[E];var P=v.assets[E];r.width=P.width*k;r.height=P.height*k}}}}},adjustForCropAnimation:function(a,b,i,h){var d=this.script.slideWidth;var f=this.script.slideHeight;var j=Math.floor(d/i);var g=Math.floor(f/h);var e=Math.round(b.x/b.width);var c=Math.round(b.y/b.height);if(b.width!=1||b.height!=1){if(e!=i-1){a.width=j}else{a.width=d-j*(i-1)}if(c!=h-1){a.height=g}else{a.height=f-g*(h-1)}a.position.pointX=j*e+a.width/2;a.position.pointY=g*c+a.height/2;a.contentsRect.x=j*e/d;a.contentsRect.y=g*c/f;a.contentsRect.width=a.width/d;a.contentsRect.height=a.height/f}},downloadScript:function(b){this.delegate=b;if(this.delegate.getKPFJsonStringForShow){this.script=JSON.parse(this.delegate.getKPFJsonStringForShow());if(this.script==null){debugMessageAlways(kDebugScriptMangaer_DownloadScript,"An error occured on the server. KPF header json is null.");return}this.slideManager=new SlideManager({header:this.script});this.slideManager.getSlides(this.script.slideList,this.delegate);return}this.downloadTimeout=setTimeout(this.scriptDidNotDownload.bind(this),kMaxScriptDownloadWaitTime);this.downloadAlreadyFailed=false;var c=this.showUrl+"header.json";if(window.location.protocol==="file:"){c=c+"p";window.local_header=(function(d){this.scriptDidDownload(d,true)}).bind(this);var a=document.createElement("script");a.setAttribute("src",c);document.head.appendChild(a)}else{new Ajax.Request(c,{method:"get",onSuccess:this.scriptDidDownload.bind(this),onFailure:this.scriptDidNotDownload.bind(this)})}},scriptDidDownload:function(b,a){clearTimeout(this.downloadTimeout);if(a){this.script=b}else{this.script=JSON.parse(b.responseText)}this.slideManager=new SlideManager({header:this.script});this.slideManager.downloadSlides(this.script.slideList)},scriptDidNotDownload:function(a){this.downloadAlreadyFailed=true;if(a){clearTimeout(this.downloadTimeout)}document.fire(kScriptDidNotDownloadEvent,{})},sceneIndexFromSlideIndex:function(a){if((this.script==null)||(a<0)||(a>=this.script.slideList.length)){return -1}return this.script.sceneIndexFromSlideIndexLookup[a]},slideIndexFromSceneIndex:function(a){if((this.script==null)||(a<0)||(a>=this.script.events.length)){return -1}return this.script.slideIndexFromSceneIndexLookup[a]}});
 
 
assets/player/ShowController.js CHANGED
@@ -1,3 +1,2105 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:aaa997793776ce98cb12d49bb84f09c351f9ab2f44e8fc35835f3917091e21a9
3
- size 77484
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * ShowController.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Responsibility: Tungwei Cheng
6
+ * Copyright (c) 2009-2016 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var kShowControllerState_Stopped = "Stopped";
10
+ var kShowControllerState_Starting = "Starting";
11
+ var kShowControllerState_DownloadingScript = "DownloadingScipt";
12
+ var kShowControllerState_SettingUpScene = "SettingUpScene";
13
+ var kShowControllerState_IdleAtFinalState = "IdleAtFinalState";
14
+ var kShowControllerState_IdleAtInitialState = "IdleAtInitialState";
15
+ var kShowControllerState_WaitingToJump = "WaitingToJump";
16
+ var kShowControllerState_ReadyToJump = "ReadyToJump";
17
+ var kShowControllerState_WaitingToDisplay = "WaitingToDisplay";
18
+ var kShowControllerState_ReadyToDisplay = "ReadyToDisplay";
19
+ var kShowControllerState_WaitingToPlay = "WaitingToPlay";
20
+ var kShowControllerState_ReadyToPlay = "ReadyToPlay";
21
+ var kShowControllerState_Playing = "Playing";
22
+
23
+ // Events:
24
+ // -------
25
+ var kKeyDownEvent = "keydown";
26
+ var kSlideIndexDidChangeEvent = "ShowController:SlideIndexDidChangeEvent";
27
+
28
+ var ShowController = Class.create({
29
+ initialize: function() {
30
+ // extract delegate from url or create a default delegate
31
+ this.delegate = extractDelegateFromUrlParameter();
32
+ this.delegate.showDidLoad();
33
+
34
+ this.showUrl = "../";
35
+
36
+ // These must be created before the OrientationController as they
37
+ // subscribe to its event
38
+ this.displayManager = new DisplayManager();
39
+ this.scriptManager = new ScriptManager(this.showUrl);
40
+ this.textureManager = new TextureManager(this.showUrl);
41
+ this.stageManager = new StageManager(this.textureManager, this.scriptManager);
42
+ this.touchController = new TouchController();
43
+ this.animationManager = new AnimationManager();
44
+ this.orientationController = new OrientationController();
45
+
46
+ this.activeHyperlinks = new Array();
47
+ this.movieHyperlinks = new Array();
48
+
49
+ // initialize default values
50
+ this.script = null;
51
+ this.currentSceneIndex = -1;
52
+ this.nextSceneIndex = -1;
53
+ this.currentSlideIndex = -1;
54
+ this.previousSlideIndex = -1;
55
+ this.currentSoundTrackIndex = 0;
56
+ this.transformOriginValue = "";
57
+ this.accumulatingDigits = false;
58
+ this.digitAccumulator = 0;
59
+ this.firstSlide = true;
60
+ this.lastSlideViewedIndex = -1;
61
+
62
+ this.accountID = "";
63
+ this.guid = "";
64
+ this.locale = "EN";
65
+ this.isNavigationBarVisible = false;
66
+ this.isFullscreen = false;
67
+ this.volume = 3.0;
68
+ this.muted = false;
69
+
70
+ this.soundTrackPlayer = null;
71
+ this.sceneIndexOfPrebuiltAnimations = -1;
72
+
73
+ // store queued user action
74
+ this.queuedUserAction = null;
75
+
76
+ // events
77
+ document.observe(kScriptDidDownloadEvent, this.handleScriptDidDownloadEvent.bind(this));
78
+ document.observe(kScriptDidNotDownloadEvent, this.handleScriptDidNotDownloadEvent.bind(this));
79
+ document.observe(kStageIsReadyEvent, this.handleStageIsReadyEvent.bind(this));
80
+ document.observe(kStageSizeDidChangeEvent, this.handleStageSizeDidChangeEvent.bind(this));
81
+
82
+ // swipe and keydown events
83
+ document.observe(kKeyDownEvent, this.handleKeyDownEvent.bind(this));
84
+ document.observe(kSwipeEvent, this.handleSwipeEvent.bind(this));
85
+
86
+ // mouse event
87
+ Event.observe(this.displayManager.body, "click", this.handleClickEvent.bind(this));
88
+
89
+ // fullscreen change event
90
+ document.observe(kFullscreenChangeEventName, this.handleFullscreenChangeEvent.bind(this));
91
+
92
+ // windows resize event
93
+ Event.observe(window, "resize", this.handleWindowResizeEvent.bind(this));
94
+
95
+ // Can't use event observer for tap events
96
+ // - this would cause the handler to be on a seperate event loop
97
+ // invocation
98
+ // - this would prevent us from doing this like opening new tabs (popup
99
+ // blocker logic kicks in)
100
+ this.touchController.registerTapEventCallback(this.handleTapEvent.bind(this));
101
+
102
+ // Initialize state to Stopped
103
+ this.changeState(kShowControllerState_Stopped);
104
+
105
+ // movie cache to be used across different event timeline within one slide
106
+ this.movieCache = null;
107
+
108
+ // audio cache
109
+ this.audioCache = null;
110
+
111
+ // KPF playback controller
112
+ this.playbackController = new KPFPlaybackController({}, this.stageManager.stage);
113
+
114
+ // Navigator
115
+ this.navigatorController = new NavigatorController(document.getElementById("slideshowNavigator"));
116
+
117
+ // Slide number feedback
118
+ this.slideNumberController = new SlideNumberController(document.getElementById("slideNumberControl"));
119
+
120
+ // Slide number display
121
+ this.slideNumberDisplay = new SlideNumberDisplay(document.getElementById("slideNumberDisplay"));
122
+
123
+ // Help Placard
124
+ this.helpPlacard = new HelpPlacardController(document.getElementById("helpPlacard"));
125
+
126
+ // indicate if the show has recording
127
+ this.isRecording = false;
128
+
129
+ // a boolean to indicate if the recording is started
130
+ this.isRecordingStarted = false;
131
+
132
+ // IE9 does not support CSS animations
133
+ if (isIE && browserVersion < 10) {
134
+ this.animationSupported = false;
135
+ }
136
+ else {
137
+ this.animationSupported = true;
138
+ }
139
+
140
+ // disable mouse right click context menu
141
+ document.observe("contextmenu", this.handleContextMenuEvent.bind(this));
142
+
143
+ Event.observe(this.displayManager.previousButton, "click", this.goBackToPreviousSlide.bind(this, "tapPreviousButton"));
144
+ Event.observe(this.displayManager.nextButton, "click", this.advanceToNextBuild.bind(this, "tapNextButton"));
145
+ },
146
+
147
+ startShow: function() {
148
+ this.changeState(kShowControllerState_DownloadingScript);
149
+ this.scriptManager.downloadScript(this.delegate);
150
+ },
151
+
152
+ exitShow: function(endNow) {
153
+ clearTimeout(this.exitTimeout);
154
+
155
+ if (endNow) {
156
+ this.delegate.showExited();
157
+ } else {
158
+ this.exitTimeout = setTimeout((function(){
159
+ this.delegate.showExited();
160
+ }).bind(this), 750);
161
+ }
162
+ },
163
+
164
+ promptUserToTryAgain: function(message) {
165
+ var tryAgain = false;
166
+
167
+ tryAgain = confirm(message);
168
+ return tryAgain;
169
+ },
170
+
171
+ handleScriptDidDownloadEvent: function(event) {
172
+ switch (this.state) {
173
+ case kShowControllerState_DownloadingScript:
174
+ var script = this.script = event.memo.script;
175
+ var showMode = script.showMode;
176
+
177
+ if (showMode == kShowModeHyperlinksOnly) {
178
+ this.displayManager.setHyperlinksOnlyMode();
179
+ }
180
+
181
+ this.changeState(kShowControllerState_Starting);
182
+
183
+ // checking to see if a restarting scene index was specified in url...
184
+ var sceneIndex;
185
+ var restartingSceneIndex = parseInt(getUrlParameter("restartingSceneIndex"));
186
+
187
+ // also look for a fragment identifier which can also indicate scene index
188
+ var currentUrl = document.URL.split("?");
189
+ var fragments = currentUrl[0].split("#");
190
+ if (fragments[1]) {
191
+ restartingSceneIndex = parseInt(fragments[1]);
192
+ }
193
+
194
+ if (restartingSceneIndex) {
195
+ // found a restarting scene index, using that...restartingSceneIndex
196
+ sceneIndex = restartingSceneIndex;
197
+ } else {
198
+ // checking to see if a starting slide number was specified in url...
199
+ var startingSlide = getUrlParameter("currentSlide");
200
+ var startingSlideNumber;
201
+
202
+ if (startingSlide) {
203
+ startingSlideNumber = parseInt(startingSlide);
204
+ } else {
205
+ // nope, not there, use 1...
206
+ startingSlideNumber = 1;
207
+ }
208
+ sceneIndex = this.scriptManager.sceneIndexFromSlideIndex(startingSlideNumber - 1);
209
+ }
210
+
211
+ // if this show has recording, then we start the show in recording mode
212
+ if (script.recording) {
213
+ if (script.recording.eventTracks[0].type === "navigation") {
214
+ this.narrationManager = new NarrationManager(script.recording);
215
+ sceneIndex = this.narrationManager.sceneIndexFromNavigationEvent(this.narrationManager.navigationEvents[0]);
216
+ this.isRecording = true;
217
+ this.jumpToScene(sceneIndex, false);
218
+
219
+ break;
220
+ }
221
+ }
222
+
223
+ if (sceneIndex > script.lastSceneIndex) {
224
+ break;
225
+ }
226
+
227
+ if (showMode === kShowModeAutoplay) {
228
+ this.jumpToScene(sceneIndex, true);
229
+ } else {
230
+ var event = script.events[sceneIndex];
231
+ var automaticPlay = event.automaticPlay == 1 || event.automaticPlay == true;
232
+ this.jumpToScene(sceneIndex, automaticPlay);
233
+ }
234
+ break;
235
+
236
+ default:
237
+ debugMessage(kDebugShowController_HandleScriptDidDownloadEvent,
238
+ "- hmmm we seem to have arrived here from an unpredicted state");
239
+ break;
240
+ }
241
+ },
242
+
243
+ handleScriptDidNotDownloadEvent: function(event) {
244
+ debugMessage(kDebugShowController_HandleScriptDidNotDownloadEvent);
245
+
246
+ var tryAgain = this.promptUserToTryAgain(kUnableToReachiWorkTryAgain);
247
+
248
+ if (tryAgain) {
249
+ this.scriptManager.downloadScript();
250
+ } else {
251
+ this.displayManager.clearLaunchMode();
252
+ this.displayManager.hideWaitingIndicator();
253
+ }
254
+ },
255
+
256
+ handleStageIsReadyEvent: function(event) {
257
+ if (this.isFullscreen) {
258
+ setTimeout((function() {
259
+ this.displayManager.stageArea.style.opacity = 1;
260
+ }).bind(this), 50)
261
+ } else {
262
+ setTimeout((function() {
263
+ this.displayManager.stageArea.style.opacity = 1;
264
+ }).bind(this), 500)
265
+ }
266
+
267
+ this.positionSlideNumberControl();
268
+ this.positionSlideNumberDisplay();
269
+ this.positionHelpPlacard();
270
+ },
271
+
272
+ positionSlideNumberControl: function() {
273
+ var left = (this.displayManager.usableDisplayWidth - this.slideNumberController.width) / 2;
274
+ var top = this.displayManager.stageAreaTop + this.displayManager.stageAreaHeight - (this.slideNumberController.height + 16);
275
+
276
+ this.slideNumberController.setPosition(left, top);
277
+ },
278
+
279
+ positionSlideNumberDisplay: function() {
280
+ var left = (this.displayManager.usableDisplayWidth - this.slideNumberDisplay.width) / 2;
281
+ var top = this.displayManager.stageAreaTop + this.displayManager.stageAreaHeight - (this.slideNumberDisplay.height + 16);
282
+
283
+ this.slideNumberDisplay.setPosition(left, top);
284
+ },
285
+
286
+ positionHelpPlacard: function() {
287
+ var left = (this.displayManager.usableDisplayWidth - this.helpPlacard.width) / 2;
288
+ var top = (this.displayManager.usableDisplayHeight - this.helpPlacard.height) / 2;
289
+
290
+ this.helpPlacard.setPosition(left, top);
291
+ },
292
+
293
+ handleFullscreenChangeEvent: function() {
294
+ if (document.webkitIsFullScreen || document.mozFullScreen) {
295
+ this.isFullscreen = true;
296
+ } else {
297
+ this.isFullscreen = false;
298
+ }
299
+
300
+ setTimeout((function() {
301
+ this.displayManager.layoutDisplay();
302
+ }).bind(this), 0);
303
+ },
304
+
305
+ handleWindowResizeEvent: function() {
306
+ clearTimeout(this.resizeTimer);
307
+ this.resizeTimer = setTimeout(this.changeWindowSize.bind(this), 1000);
308
+ },
309
+
310
+ changeWindowSize: function() {
311
+ if (this.delegate.setViewScale) {
312
+ this.scriptManager.reapplyScaleFactor();
313
+
314
+ this.textureManager.slideCache = null;
315
+ this.textureManager.slideCache = {};
316
+
317
+ var sceneIndexToUse = this.currentSceneIndex;
318
+
319
+ if (this.state === kShowControllerState_IdleAtFinalState) {
320
+ if (this.currentSceneIndex < this.script.numScenes - 1) {
321
+ sceneIndexToUse = this.currentSceneIndex + 1;
322
+ } else {
323
+ if (this.script.loopSlideshow) {
324
+ sceneIndexToUse = 0;
325
+ }
326
+ }
327
+ }
328
+
329
+ this.jumpToScene(sceneIndexToUse, false);
330
+ }
331
+
332
+ document.fire(kShowSizeDidChangeEvent, {
333
+ width: this.script.slideWidth,
334
+ height: this.script.slideHeight
335
+ });
336
+ },
337
+
338
+ handleStageSizeDidChangeEvent: function(event) {
339
+ // update TouchController with new track area
340
+ this.touchController.setTrackArea(event.memo.left, event.memo.top, event.memo.width, event.memo.height);
341
+ },
342
+
343
+ handleKeyDownEvent: function(event) {
344
+ var key = event.charCode || event.keyCode;
345
+
346
+ // allow F11 and F12 to work on IE
347
+ if (key === kKeyCode_F11 || key === kKeyCode_F12) {
348
+ return;
349
+ }
350
+
351
+ var modifiers = {
352
+ altKey: !!event.altKey,
353
+ ctrlKey: !!event.ctrlKey,
354
+ shiftKey: !!event.shiftKey,
355
+ metaKey: !!event.metaKey
356
+ };
357
+
358
+ if (modifiers.metaKey) {
359
+ if (key === kKeyCode_Period || key === kKeyCode_Dot) {
360
+ // cmd - . to exit show
361
+ this.exitShow(true);
362
+ } else if (key != kKeyCode_Return) {
363
+ // allow browsers to handle cmd-key
364
+ return;
365
+ }
366
+ } else if (modifiers.ctrlKey) {
367
+ // allow browsers to handle ctrl-key
368
+ return;
369
+ }
370
+
371
+ event.stop();
372
+ this.onKeyPress(key, modifiers);
373
+ },
374
+
375
+ handleContextMenuEvent: function(event) {
376
+ event.stop();
377
+ },
378
+
379
+ handleClickEvent: function(event) {
380
+ if (this.isRecording) {
381
+ return;
382
+ }
383
+
384
+ var x, y;
385
+
386
+ if (event.pageX || event.pageY) {
387
+ x = event.pageX;
388
+ y = event.pageY;
389
+ } else {
390
+ x = event.clientX;
391
+ y = event.clientY;
392
+ }
393
+
394
+ var displayCoOrds = {
395
+ pointX: x,
396
+ pointY: y
397
+ };
398
+
399
+ // for IE make sure windows has focus
400
+ if (isIE) {
401
+ window.focus();
402
+ }
403
+
404
+ // For video element, let the event to propagate
405
+ if (event.target.nodeName.toLowerCase() === "video") {
406
+ return;
407
+ }
408
+
409
+ this.processClickOrTapAtDisplayCoOrds(displayCoOrds);
410
+ },
411
+
412
+ handleTapEvent: function(event) {
413
+ var displayCoOrds = {
414
+ pointX: event.memo.pointX,
415
+ pointY: event.memo.pointY
416
+ };
417
+
418
+ this.processClickOrTapAtDisplayCoOrds(displayCoOrds);
419
+ },
420
+
421
+ processClickOrTapAtDisplayCoOrds: function(displayCoOrds) {
422
+ var isHyperlink = false;
423
+ var hyperlink;
424
+
425
+ if (this.slideNumberController.isShowing) {
426
+ if (this.slideNumberTimeout) {
427
+ clearTimeout(this.slideNumberTimeout);
428
+ }
429
+ this.slideNumberTimeout = setTimeout(this.hideAndResetSlideNumberController.bind(this), 0);
430
+ return;
431
+ }
432
+
433
+ if (this.helpPlacard.isShowing) {
434
+ this.helpPlacard.hide();
435
+ return;
436
+ }
437
+
438
+ var showCoOrds = this.displayManager.convertDisplayCoOrdsToShowCoOrds(displayCoOrds);
439
+
440
+ if (showCoOrds.pointX != -1) {
441
+ hyperlink = this.findHyperlinkAtCoOrds(showCoOrds);
442
+ }
443
+
444
+ if (hyperlink) {
445
+ this.processHyperlink(hyperlink);
446
+ } else {
447
+ this.advanceToNextBuild("processClickOrTapAtDisplayCoOrds");
448
+ }
449
+ },
450
+
451
+ handleSwipeEvent: function(event) {
452
+ if (event.memo.direction === "left") {
453
+ switch (event.memo.fingers) {
454
+ case 1:
455
+ this.advanceToNextBuild("handleSwipeEvent");
456
+ break;
457
+ case 2:
458
+ this.advanceToNextSlide("handleSwipeEvent");
459
+ break;
460
+ default:
461
+ break;
462
+ }
463
+ } else if (event.memo.direction === "right") {
464
+ switch (event.memo.fingers) {
465
+ case 1:
466
+ this.goBackToPreviousSlide("handleSwipeEvent");
467
+ break;
468
+ case 2:
469
+ this.goBackToPreviousBuild("handleSwipeEvent");
470
+ break;
471
+ default:
472
+ break;
473
+ }
474
+ }
475
+ },
476
+
477
+ onMouseDown: function(mouseDownEvent) {
478
+ if (mouseDownEvent.leftClick) {
479
+ this.advanceToNextBuild("onMouseDown");
480
+ } else if (mouseDownEvent.rightClick) {
481
+ this.goBackToPreviousBuild("onMouseDown");
482
+ }
483
+ },
484
+
485
+ onKeyPress: function(key, modifier) {
486
+ if ((key >= kKeyCode_Numeric_0) && (key <= kKeyCode_Numeric_9)) {
487
+ key = kKeyCode_0 + (key - kKeyCode_Numeric_0);
488
+ }
489
+
490
+ key += (modifier.shiftKey ? kKeyModifier_Shift : 0);
491
+ key += (modifier.altKey ? kKeyModifier_Alt : 0);
492
+ key += (modifier.ctrlKey ? kKeyModifier_Ctrl : 0);
493
+ key += (modifier.metaKey ? kKeyModifier_Meta : 0);
494
+
495
+ if (this.isRecording) {
496
+ return;
497
+ }
498
+
499
+ var digitEncountered = false;
500
+ switch (key) {
501
+ case kKeyCode_Escape:
502
+ this.exitShow(true);
503
+ break;
504
+
505
+ /*
506
+ * case kKeyCode_Return + kKeyModifier_Ctrl:
507
+ * this.displayManager.showWaitingIndicator(); break;
508
+ *
509
+ * case kKeyCode_Return + kKeyModifier_Alt:
510
+ * this.displayManager.hideWaitingIndicator(); break;
511
+ *
512
+ * case kKeyCode_Return + kKeyModifier_Meta: this.debugDiagnosticDump();
513
+ * break;
514
+ */
515
+ case kKeyCode_Slash:
516
+ case kKeyCode_Slash + kKeyModifier_Shift:
517
+ if (this.helpPlacard.isShowing) {
518
+ this.helpPlacard.hide();
519
+ } else {
520
+ this.helpPlacard.show();
521
+ }
522
+ break;
523
+
524
+ case kKeyCode_Q:
525
+ this.exitShow(true);
526
+ break;
527
+
528
+ case kKeyCode_S:
529
+ if (this.slideNumberController.isShowing) {
530
+ if (this.slideNumberTimeout) {
531
+ clearTimeout(this.slideNumberTimeout);
532
+ }
533
+ this.slideNumberTimeout = setTimeout(this.hideAndResetSlideNumberController.bind(this), 0);
534
+ }
535
+
536
+ if (this.slideNumberDisplay.isShowing) {
537
+ this.slideNumberDisplay.hide();
538
+ } else {
539
+ this.slideNumberDisplay.setSlideNumber(this.currentSlideIndex + 1);
540
+ this.slideNumberDisplay.show();
541
+ }
542
+ break;
543
+
544
+ case kKeyCode_Return:
545
+ if (this.accumulatingDigits) {
546
+ // return pressed while accumulating digits.
547
+ this.accumulatingDigits = false;
548
+
549
+ if (this.script.showMode != kShowModeHyperlinksOnly) {
550
+ if (this.digitAccumulator > this.script.slideCount) {
551
+ this.digitAccumulator = this.script.slideCount;
552
+ }
553
+ else if (this.digitAccumulator < 1) {
554
+ this.digitAccumulator = 1;
555
+ }
556
+ this.slideNumberController.setSlideNumber(this.digitAccumulator);
557
+ this.jumpToSlide(this.digitAccumulator);
558
+ } else {
559
+ debugMessage(kDebugShowController_OnKeyPress, "- can't do it, we're in hyperlinks only mode");
560
+ }
561
+ break;
562
+ }
563
+ // fall through
564
+
565
+ case kKeyCode_N:
566
+ case kKeyCode_Space:
567
+ case kKeyCode_DownArrow:
568
+ case kKeyCode_RightArrow:
569
+ case kKeyCode_PageDown:
570
+ // advance to next build...
571
+ this.advanceToNextBuild("onKeyPress");
572
+ break;
573
+
574
+ case kKeyCode_RightArrow + kKeyModifier_Shift:
575
+ case kKeyCode_CloseBracket:
576
+ // advance and skip build...
577
+ this.advanceAndSkipBuild("onKeyPress");
578
+ break;
579
+
580
+ case kKeyCode_DownArrow + kKeyModifier_Shift:
581
+ case kKeyCode_PageDown + kKeyModifier_Shift:
582
+ case kKeyCode_CloseBracket:
583
+ case kKeyCode_Equal + kKeyModifier_Shift:
584
+ case kKeyCode_Equal:
585
+ case kKeyCode_Plus:
586
+ // advance to next slide...
587
+ this.advanceToNextSlide("onKeyPress");
588
+ break;
589
+
590
+ case kKeyCode_LeftArrow + kKeyModifier_Shift:
591
+ case kKeyCode_PageUp + kKeyModifier_Shift:
592
+ case kKeyCode_OpenBracket:
593
+ // go back to previous build...
594
+ this.goBackToPreviousBuild("onKeyPress");
595
+ break;
596
+
597
+ case kKeyCode_P:
598
+ case kKeyCode_PageUp:
599
+ case kKeyCode_LeftArrow:
600
+ case kKeyCode_UpArrow:
601
+ case kKeyCode_UpArrow + kKeyModifier_Shift:
602
+ case kKeyCode_Hyphen:
603
+ case kKeyCode_Minus:
604
+ // go back to previous slide...
605
+ this.goBackToPreviousSlide("onKeyPress");
606
+ break;
607
+
608
+ case kKeyCode_Delete:
609
+ digitEncountered = true;
610
+ if (this.accumulatingDigits) {
611
+ if (this.digitAccumulator < 10) {
612
+ if (this.slideNumberTimeout) {
613
+ clearTimeout(this.slideNumberTimeout);
614
+ }
615
+ this.slideNumberTimeout = setTimeout(this.hideAndResetSlideNumberController.bind(this), 0);
616
+ }
617
+ else {
618
+ if (this.slideNumberTimeout) {
619
+ clearTimeout(this.slideNumberTimeout);
620
+ }
621
+ this.slideNumberTimeout = setTimeout(this.hideAndResetSlideNumberController.bind(this), 7000);
622
+
623
+ var digit = this.digitAccumulator.toString();
624
+ this.digitAccumulator = parseInt(digit.substring(0, digit.length - 1));
625
+ this.slideNumberController.setSlideNumber(this.digitAccumulator);
626
+ }
627
+ }
628
+ break;
629
+
630
+ case kKeyCode_Home:
631
+ // go back to first slide...
632
+ if (this.script.showMode != kShowModeHyperlinksOnly) {
633
+ this.jumpToSlide(1);
634
+ } else {
635
+ debugMessage(kDebugShowController_OnKeyPress, "- can't do it, we're in hyperlinks only mode");
636
+ }
637
+ break;
638
+
639
+ case kKeyCode_End:
640
+ // go back to last slide...
641
+ if (this.script.showMode != kShowModeHyperlinksOnly) {
642
+ this.jumpToSlide(this.script.slideCount);
643
+ } else {
644
+ debugMessage(kDebugShowController_OnKeyPress, "- can't do it, we're in hyperlinks only mode");
645
+ }
646
+ break;
647
+
648
+ default:
649
+ if (this.slideNumberTimeout) {
650
+ clearTimeout(this.slideNumberTimeout);
651
+ }
652
+ this.slideNumberTimeout = setTimeout(this.hideAndResetSlideNumberController.bind(this), 7000);
653
+
654
+ if ((key >= kKeyCode_0) && (key <= kKeyCode_9)) {
655
+ if (this.slideNumberDisplay.isShowing) {
656
+ this.slideNumberDisplay.hide();
657
+ }
658
+
659
+ digitEncountered = true;
660
+ if (this.accumulatingDigits === false) {
661
+ // digit entered, start accumulating digits...
662
+ this.accumulatingDigits = true;
663
+ this.digitAccumulator = 0;
664
+ }
665
+
666
+ if (this.digitAccumulator.toString().length < 4) {
667
+ this.digitAccumulator *= 10;
668
+ this.digitAccumulator += (key - kKeyCode_0);
669
+
670
+ this.slideNumberController.setSlideNumber(this.digitAccumulator);
671
+ if (!this.slideNumberController.isShowing) {
672
+ this.slideNumberController.show();
673
+ }
674
+ }
675
+ }
676
+ else {
677
+ digitEncountered = true;
678
+ }
679
+ break;
680
+ }
681
+
682
+ if (this.accumulatingDigits && (digitEncountered === false)) {
683
+ // non-digit entered, stop accumulating digits...
684
+ //this.accumulatingDigits = false;
685
+ //this.digitAccumulator = 0;
686
+ }
687
+ },
688
+
689
+ hideAndResetSlideNumberController: function() {
690
+ if (this.slideNumberTimeout) {
691
+ clearTimeout(this.slideNumberTimeout);
692
+ }
693
+
694
+ this.accumulatingDigits = false;
695
+ this.digitAccumulator = 0;
696
+ this.slideNumberController.hide();
697
+ },
698
+
699
+ hideSlideNumberDisplay: function() {
700
+ this.slideNumberDisplay.hide();
701
+ },
702
+
703
+ toggleFullscreen: function() {
704
+ // IE does not support fullscreen mode, return for now
705
+ if (isIE) {
706
+ return;
707
+ }
708
+
709
+ setTimeout((function() {
710
+ this.displayManager.stageArea.style.opacity = 0;
711
+ }).bind(this), 0);
712
+
713
+ // hide hud immediately
714
+ this.displayManager.hideHUD(true);
715
+
716
+ if (document.webkitIsFullScreen || document.mozFullScreen) {
717
+ this.isFullscreen = false;
718
+ (document.webkitCancelFullScreen && document.webkitCancelFullScreen())
719
+ || (document.mozCancelFullScreen && document.mozCancelFullScreen());
720
+ } else {
721
+ this.isFullscreen = true;
722
+ (document.body.webkitRequestFullScreen && document.body.webkitRequestFullScreen())
723
+ || (document.body.mozRequestFullScreen && document.body.mozRequestFullScreen());
724
+ }
725
+ },
726
+
727
+ // State Management
728
+ // ================
729
+ changeState: function(newState) {
730
+ if (newState != this.state) {
731
+ //this.accumulatingDigits = false;
732
+ //this.digitAccumulator = 0;
733
+
734
+ this.leavingState();
735
+ this.state = newState;
736
+ this.enteringState();
737
+ }
738
+ },
739
+
740
+ leavingState: function() {
741
+ switch (this.state) {
742
+ case kShowControllerState_Stopped:
743
+ break;
744
+
745
+ case kShowControllerState_Starting:
746
+ break;
747
+
748
+ case kShowControllerState_SettingUpScene:
749
+ break;
750
+
751
+ case kShowControllerState_IdleAtFinalState:
752
+ break;
753
+
754
+ case kShowControllerState_IdleAtInitialState:
755
+ break;
756
+
757
+ case kShowControllerState_WaitingToJump:
758
+ break;
759
+
760
+ case kShowControllerState_ReadyToJump:
761
+ break;
762
+
763
+ case kShowControllerState_WaitingToPlay:
764
+ this.displayManager.hideWaitingIndicator();
765
+ break;
766
+
767
+ case kShowControllerState_ReadyToPlay:
768
+ break;
769
+
770
+ case kShowControllerState_Playing:
771
+ break;
772
+ }
773
+ },
774
+
775
+ enteringState: function() {
776
+ switch (this.state) {
777
+ case kShowControllerState_Stopped:
778
+ break;
779
+
780
+ case kShowControllerState_Starting:
781
+ this.displayManager.showWaitingIndicator();
782
+ break;
783
+
784
+ case kShowControllerState_SettingUpScene:
785
+ break;
786
+
787
+ case kShowControllerState_IdleAtFinalState:
788
+ // unload slide cache not next to the current slide
789
+ this.unloadTextures();
790
+
791
+ case kShowControllerState_IdleAtInitialState:
792
+ this.updateSlideNumber();
793
+
794
+ runInNextEventLoop(this.doIdleProcessing.bind(this));
795
+ break;
796
+
797
+ case kShowControllerState_WaitingToJump:
798
+ // don't show spinner here, do it in pollForSceneToLoad after a few
799
+ // polls so the spinner doesn't come up right away
800
+ break;
801
+
802
+ case kShowControllerState_ReadyToJump:
803
+ break;
804
+
805
+ case kShowControllerState_WaitingToPlay:
806
+ this.displayManager.showWaitingIndicator();
807
+ break;
808
+
809
+ case kShowControllerState_ReadyToPlay:
810
+ break;
811
+
812
+ case kShowControllerState_Playing:
813
+ break;
814
+ }
815
+ },
816
+
817
+ preloadTextures: function() {
818
+ var script = this.script;
819
+ var sceneIndexToUse = this.currentSceneIndex;
820
+
821
+ if (this.state === kShowControllerState_IdleAtFinalState) {
822
+ if (sceneIndexToUse < script.numScenes - 1) {
823
+ sceneIndexToUse = sceneIndexToUse + 1;
824
+ } else if (script.loopSlideshow) {
825
+ sceneIndexToUse = 0;
826
+ }
827
+ }
828
+
829
+ // preload textures
830
+ this.textureManager.loadScene(sceneIndexToUse);
831
+ },
832
+
833
+ unloadTextures: function() {
834
+ var script = this.script;
835
+ var sceneIndexToUse = this.currentSceneIndex;
836
+
837
+ if (this.state === kShowControllerState_IdleAtFinalState) {
838
+ if (sceneIndexToUse < script.numScenes - 1) {
839
+ sceneIndexToUse = sceneIndexToUse + 1;
840
+ } else if (script.loopSlideshow) {
841
+ sceneIndexToUse = 0;
842
+ }
843
+ }
844
+
845
+ var currentSlideIndex = script.slideIndexFromSceneIndexLookup[sceneIndexToUse];
846
+
847
+ var slideCache = this.textureManager.slideCache;
848
+
849
+ for (var index in slideCache) {
850
+ // detect current slide index and its previous and next slide in slideCache buffer
851
+ if (index < currentSlideIndex - 1 || index > currentSlideIndex + 1) {
852
+ // remove slide cache
853
+ var cache = slideCache[index];
854
+ for (var textureId in cache.textureAssets) {
855
+ var canvas = cache.textureAssets[textureId];
856
+ if (canvas) {
857
+ // clear canvas object
858
+ var context = canvas.getContext("2d");
859
+
860
+ if (context) {
861
+ context.clearRect(0, 0, canvas.width, canvas.height);
862
+ }
863
+
864
+ // remove reference
865
+ delete cache.textureAssets[textureId];
866
+ }
867
+ }
868
+
869
+ delete this.textureManager.slideCache[index].textureAssets;
870
+ delete this.textureManager.slideCache[index].textureRequests;
871
+ delete this.textureManager.slideCache[index].requested;
872
+
873
+ // call internal pdf document destroy method
874
+ if (cache.pdf) {
875
+ cache.pdf.destroy();
876
+ delete this.textureManager.slideCache[index].pdf;
877
+ }
878
+
879
+ // finally remove slide cache reference
880
+ delete this.textureManager.slideCache[index];
881
+ }
882
+ }
883
+ },
884
+
885
+ doIdleProcessing: function() {
886
+ // preload textures for next slide if applicable
887
+ this.preloadTextures();
888
+
889
+ if (this.queuedUserAction != null) {
890
+ // executing queued user action...
891
+ this.queuedUserAction();
892
+ this.queuedUserAction = null;
893
+ } else {
894
+ var stage = this.stageManager.stage;
895
+
896
+ if (stage.childNodes.length !== 0) {
897
+ this.updateNavigationButtons();
898
+ }
899
+ }
900
+
901
+ // create hyperlink in setTimeout using background thread
902
+ clearTimeout(this.createHyperlinksForCurrentStateTimeout);
903
+ this.createHyperlinksForCurrentStateTimeout = setTimeout((function() {this.createHyperlinksForCurrentState("idle");}).bind(this), 100);
904
+ },
905
+
906
+ truncatedSlideIndex: function(slideIndex) {
907
+ return this.truncatedIndex(slideIndex, this.script.lastSlideIndex, this.script.loopSlideshow);
908
+ },
909
+
910
+ truncatedSceneIndex: function(sceneIndex) {
911
+ return this.truncatedIndex(sceneIndex, this.script.lastSceneIndex, this.script.loopSlideshow);
912
+ },
913
+
914
+ truncatedIndex: function(index, lastIndex, isLooping) {
915
+ if (index < 0) {
916
+ if (isLooping) {
917
+ index = index + lastIndex + 1;
918
+ } else {
919
+ index = -1;
920
+ }
921
+ } else if (index > lastIndex) {
922
+ if (isLooping) {
923
+ index = index - lastIndex - 1;
924
+ } else {
925
+ index = -1;
926
+ }
927
+ }
928
+ return index;
929
+ },
930
+
931
+ advanceToNextBuild: function(context) {
932
+ // do not proceed if the script is not available
933
+ if (!this.script) {
934
+ return false;
935
+ }
936
+
937
+ if (this.script.showMode === kShowModeHyperlinksOnly && context != "currentSceneDidComplete") {
938
+ return false;
939
+ }
940
+
941
+ if (this.displayManager.infoPanelIsShowing) {
942
+ return false;
943
+ }
944
+
945
+ var result = false;
946
+
947
+ switch (this.state) {
948
+ case kShowControllerState_IdleAtFinalState:
949
+ if (this.nextSceneIndex === -1) {
950
+ if (this.delegate.getKPFJsonStringForShow) {
951
+ this.stopSoundTrack();
952
+ this.exitShow();
953
+ } else {
954
+ this.stopSoundTrack();
955
+ break;
956
+ }
957
+ }
958
+ // idle on final state, jump to next scene
959
+ result = true;
960
+ this.jumpToScene(this.nextSceneIndex, true);
961
+ break;
962
+
963
+ case kShowControllerState_IdleAtInitialState:
964
+ if (this.currentSceneIndex >= this.script.numScenes) {
965
+ if (this.script.loopSlideshow) {
966
+ // we're at the end but this IS a looping show, jump to start
967
+ result = true;
968
+ this.jumpToScene(0, false);
969
+ } else {
970
+ if (this.delegate.getKPFJsonStringForShow) {
971
+ this.stopSoundTrack();
972
+ this.exitShow();
973
+ } else {
974
+ this.stopSoundTrack();
975
+ break;
976
+ }
977
+ }
978
+ } else {
979
+ // we're sitting idle on initial state, preload next scene and play current scene
980
+ result = true;
981
+ this.playCurrentScene();
982
+ }
983
+ break;
984
+
985
+ default:
986
+ debugMessage(kDebugShowController_AdvanceToNextBuild, "nextSceneIndex: " + this.nextSceneIndex + " can't advance now, not in an idle state (currently in '" + this.state + "' state), queue up action to run in next idle time");
987
+
988
+ if (this.queuedUserAction == null) {
989
+ result = true;
990
+ this.queuedUserAction = this.advanceToNextBuild.bind(this, context);
991
+ }
992
+ break;
993
+ }
994
+
995
+ return result;
996
+ },
997
+
998
+ advanceToNextSlide: function(context) {
999
+ // do not proceed if the script is not available
1000
+ if (!this.script) {
1001
+ return false;
1002
+ }
1003
+
1004
+ if (this.script.showMode == kShowModeHyperlinksOnly) {
1005
+ return;
1006
+ }
1007
+
1008
+ if (this.displayManager.infoPanelIsShowing) {
1009
+ return;
1010
+ }
1011
+
1012
+ var sceneIndexToUse = this.currentSceneIndex;
1013
+
1014
+ switch (this.state) {
1015
+ case kShowControllerState_IdleAtFinalState:
1016
+ sceneIndexToUse = sceneIndexToUse + 1;
1017
+ // Fall through
1018
+
1019
+ case kShowControllerState_IdleAtInitialState:
1020
+ var currentSlideIndex = this.scriptManager.slideIndexFromSceneIndex(sceneIndexToUse);
1021
+ var nextSlideIndex ;
1022
+
1023
+ if (currentSlideIndex === this.script.slideCount - 1) {
1024
+ if (this.script.loopSlideshow) {
1025
+ nextSlideIndex = 0;
1026
+ } else {
1027
+ return;
1028
+ }
1029
+ } else {
1030
+ nextSlideIndex = this.currentSlideIndex + 1;
1031
+ }
1032
+
1033
+ var sceneIndex = this.scriptManager.sceneIndexFromSlideIndex(nextSlideIndex);
1034
+ var event = this.script.events[sceneIndex];
1035
+ var automaticPlay = event.automaticPlay == 1 || event.automaticPlay == true;
1036
+ this.jumpToSlide(nextSlideIndex + 1, automaticPlay);
1037
+
1038
+ break;
1039
+
1040
+ default:
1041
+ debugMessage(kDebugShowController_AdvanceToNextSlide, "can't advance now, not in an idle state (currently in '" + this.state + "' state), queue up action to run in next idle time");
1042
+
1043
+ if (this.queuedUserAction == null) {
1044
+ this.queuedUserAction = this.advanceToNextSlide.bind(this, context);
1045
+ }
1046
+ break;
1047
+ }
1048
+ },
1049
+
1050
+ goBackToPreviousBuild: function(context) {
1051
+ // do not proceed if the script is not available
1052
+ if (!this.script) {
1053
+ return false;
1054
+ }
1055
+
1056
+ // going back to previous build, remove all media cache
1057
+ this.resetMediaCache();
1058
+
1059
+ if (this.script.showMode == kShowModeHyperlinksOnly) {
1060
+ return;
1061
+ }
1062
+
1063
+ if (this.displayManager.infoPanelIsShowing) {
1064
+ return;
1065
+ }
1066
+
1067
+ var sceneIndexToUse = this.currentSceneIndex;
1068
+
1069
+ switch (this.state) {
1070
+ case kShowControllerState_IdleAtFinalState:
1071
+ sceneIndexToUse = sceneIndexToUse + 1;
1072
+ // Fall through
1073
+
1074
+ case kShowControllerState_Playing:
1075
+ case kShowControllerState_IdleAtInitialState:
1076
+ var previousSceneIndex ;
1077
+
1078
+ if (sceneIndexToUse === 0) {
1079
+ if (this.script.loopSlideshow) {
1080
+ previousSceneIndex = this.script.events.length - 1;
1081
+ } else {
1082
+ return;
1083
+ }
1084
+ } else {
1085
+ previousSceneIndex = sceneIndexToUse - 1;
1086
+ }
1087
+
1088
+ this.jumpToScene(previousSceneIndex, false);
1089
+
1090
+ break;
1091
+
1092
+ default:
1093
+ debugMessage(kDebugShowController_GoBackToPreviousBuild, "can't go back now, not in an idle state (currently in '" + this.state + "' state)");
1094
+
1095
+ if (this.queuedUserAction == null) {
1096
+ this.queuedUserAction = this.goBackToPreviousBuild.bind(this, context);
1097
+ }
1098
+ break;
1099
+ }
1100
+ },
1101
+
1102
+ advanceAndSkipBuild: function(context) {
1103
+ // do not proceed if the script is not available
1104
+ if (!this.script) {
1105
+ return false;
1106
+ }
1107
+
1108
+ if (this.script.showMode == kShowModeHyperlinksOnly) {
1109
+ return;
1110
+ }
1111
+
1112
+ var sceneIndexToUse = this.currentSceneIndex;
1113
+
1114
+ switch (this.state) {
1115
+ case kShowControllerState_IdleAtFinalState:
1116
+ sceneIndexToUse = sceneIndexToUse + 1;
1117
+ // Fall through
1118
+ case kShowControllerState_IdleAtInitialState:
1119
+ var nextSceneIndex;
1120
+
1121
+ if (sceneIndexToUse >= this.script.numScenes - 1) {
1122
+ if (this.script.loopSlideshow) {
1123
+ nextSceneIndex = 0;
1124
+ } else {
1125
+ return;
1126
+ }
1127
+ } else {
1128
+ nextSceneIndex = sceneIndexToUse + 1;
1129
+ }
1130
+
1131
+ this.jumpToScene(nextSceneIndex, false);
1132
+
1133
+ break;
1134
+
1135
+ default:
1136
+ debugMessage(kDebugShowController_GoBackToPreviousBuild, "can't go back now, not in an idle state (currently in '" + this.state + "' state)");
1137
+
1138
+ if (this.queuedUserAction == null) {
1139
+ this.queuedUserAction = this.advanceAndSkipBuild.bind(this, context);
1140
+ }
1141
+ break;
1142
+ }
1143
+ },
1144
+
1145
+ goBackToPreviousSlide: function(context) {
1146
+ // do not proceed if the script is not available
1147
+ if (!this.script) {
1148
+ return false;
1149
+ }
1150
+
1151
+ if (this.script.showMode == kShowModeHyperlinksOnly) {
1152
+ return;
1153
+ }
1154
+
1155
+ if (this.displayManager.infoPanelIsShowing) {
1156
+ return;
1157
+ }
1158
+
1159
+ var sceneIndexToUse = this.currentSceneIndex;
1160
+
1161
+ switch (this.state) {
1162
+ case kShowControllerState_IdleAtFinalState:
1163
+ sceneIndexToUse = sceneIndexToUse + 1;
1164
+ // Fall through
1165
+
1166
+ case kShowControllerState_Playing:
1167
+ case kShowControllerState_IdleAtInitialState:
1168
+ var currentSlideIndex = this.scriptManager.slideIndexFromSceneIndex(sceneIndexToUse);
1169
+ var sceneIndexForCurrentSlideIndex = this.scriptManager.sceneIndexFromSlideIndex(currentSlideIndex);
1170
+ var previousSlideIndex;
1171
+
1172
+ if (currentSlideIndex === 0) {
1173
+ if (sceneIndexToUse > 0) {
1174
+ // if we are not on first build of the slide, go back to first build of the slide
1175
+ previousSlideIndex = 0;
1176
+ } else {
1177
+ if (this.script.loopSlideshow) {
1178
+ previousSlideIndex = this.script.slideCount - 1;
1179
+ } else {
1180
+ previousSlideIndex = 0;
1181
+ }
1182
+ }
1183
+ } else if (currentSlideIndex === -1 && sceneIndexToUse > 0) {
1184
+ previousSlideIndex = this.script.slideCount - 1;
1185
+ } else {
1186
+ if (sceneIndexToUse > sceneIndexForCurrentSlideIndex) {
1187
+ // if we are not on first build of the slide, go back to first build of the slide
1188
+ previousSlideIndex = this.currentSlideIndex;
1189
+ } else {
1190
+ // if we are on first build of the slide, go back to previous slide
1191
+ previousSlideIndex = this.currentSlideIndex - 1;
1192
+ }
1193
+ }
1194
+
1195
+ this.jumpToSlide(previousSlideIndex + 1);
1196
+
1197
+ break;
1198
+
1199
+ default:
1200
+ debugMessage(kDebugShowController_GoBackToPreviousSlide, "can't go back now, not in an idle state (currently in '" + this.state + "' state)");
1201
+
1202
+ if (this.queuedUserAction == null) {
1203
+ this.queuedUserAction = this.goBackToPreviousSlide.bind(this, context);
1204
+ }
1205
+ break;
1206
+ }
1207
+ },
1208
+
1209
+ calculatePreviousSceneIndex: function(sceneIndex) {
1210
+ if (sceneIndex == -1) {
1211
+ previousSceneIndex = -1;
1212
+ }
1213
+ else {
1214
+ previousSceneIndex = sceneIndex - 1;
1215
+ }
1216
+
1217
+ return previousSceneIndex;
1218
+ },
1219
+
1220
+ jumpToSlide: function(slideNumber, automaticPlay) {
1221
+ var slideIndex = slideNumber - 1;
1222
+ var sceneIndex = this.scriptManager.sceneIndexFromSlideIndex(slideIndex);
1223
+
1224
+ // we are jumping to slide, remove all media cache
1225
+ this.resetMediaCache();
1226
+
1227
+ // enable automatic play when the slide it advances to has automatic play
1228
+ // see <rdar://problem/12781266> Next slide does not auto advance when using keyboard to advance without transiti
1229
+ if (automaticPlay == null) {
1230
+ automaticPlay = false;
1231
+ }
1232
+
1233
+ this.jumpToScene(sceneIndex, automaticPlay);
1234
+ },
1235
+
1236
+ jumpToScene: function(sceneIndex, playAnimations) {
1237
+ this.lastSlideViewedIndex = this.scriptManager.slideIndexFromSceneIndex(this.currentSceneIndex);
1238
+ if (sceneIndex === -1) {
1239
+ return;
1240
+ }
1241
+
1242
+ switch (this.state) {
1243
+ case kShowControllerState_Starting:
1244
+ // There is a bug in webkit - cursor not being able to change if sitting idle unless it has been moved
1245
+ // The workaround for the bug without moving the mouse cursor is to change DOM structure to force a redraw
1246
+ // References: http://code.google.com/p/chromium/issues/detail?id=26723
1247
+ var cssText = "position:absolute;background-color:transparent; left:0px; top:0px; width:" + this.displayManager.usableDisplayWidth +"px; height:" + this.displayManager.usableDisplayHeight + "px;";
1248
+ this.starting = true;
1249
+ this.maskElement = document.createElement("div");
1250
+ this.maskElement.setAttribute("style",cssText);
1251
+ document.body.appendChild(this.maskElement);
1252
+
1253
+ case kShowControllerState_IdleAtInitialState:
1254
+ case kShowControllerState_IdleAtFinalState:
1255
+ case kShowControllerState_ReadyToJump:
1256
+ break;
1257
+
1258
+ default:
1259
+ debugMessage(kDebugShowController_JumpToScene, "can't jump now, currently in '" + this.state + "' state which does not supports jumping...");
1260
+ return;
1261
+ }
1262
+
1263
+ if (this.textureManager.isScenePreloaded(sceneIndex) === false) {
1264
+ this.changeState(kShowControllerState_WaitingToJump);
1265
+
1266
+ // loadScene with callback handler and params
1267
+ var sceneToLoadInfo = {
1268
+ sceneIndex: sceneIndex,
1269
+ automaticPlay: playAnimations
1270
+ };
1271
+
1272
+ this.waitForSceneToLoadTimeout = setTimeout(this.handleSceneDidNotLoad.bind(this, sceneToLoadInfo), kMaxSceneDownloadWaitTime);
1273
+ this.textureManager.loadScene(sceneIndex, this.handleSceneDidLoad.bind(this, sceneToLoadInfo));
1274
+
1275
+ return;
1276
+ }
1277
+
1278
+ this.changeState(kShowControllerState_SettingUpScene);
1279
+
1280
+ runInNextEventLoop(this.jumpToScene_partThree.bind(this, sceneIndex, playAnimations));
1281
+ },
1282
+
1283
+ handleSceneDidLoad: function(sceneToLoadInfo) {
1284
+ clearTimeout(this.waitForSceneToLoadTimeout);
1285
+ this.displayManager.setNextButtonEnabled(this.currentSceneIndex < (this.script.pageCount - 1));
1286
+
1287
+ switch (this.state) {
1288
+ case kShowControllerState_WaitingToJump:
1289
+ this.changeState(kShowControllerState_ReadyToJump);
1290
+ this.jumpToScene_partTwo(sceneToLoadInfo.sceneIndex, sceneToLoadInfo.automaticPlay);
1291
+ break;
1292
+
1293
+ default:
1294
+ break;
1295
+ }
1296
+ },
1297
+
1298
+ handleSceneDidNotLoad: function(sceneToLoadInfo) {
1299
+ clearTimeout(this.waitForSceneToLoadTimeout);
1300
+ this.queuedUserAction = null;
1301
+
1302
+ var tryAgain = this.promptUserToTryAgain(kUnableToReachiWorkTryAgain);
1303
+
1304
+ if (tryAgain) {
1305
+ // restarting player with sceneIndex
1306
+ var currentUrl = window.location.href;
1307
+ var croppedUrl;
1308
+ var indexOfRestartParam = currentUrl.indexOf("&restartingSceneIndex");
1309
+
1310
+ if (indexOfRestartParam === -1) {
1311
+ croppedUrl = currentUrl;
1312
+ } else {
1313
+ croppedUrl = currentUrl.substring(0, indexOfRestartParam);
1314
+ }
1315
+
1316
+ var newUrl = croppedUrl + "&restartingSceneIndex=" + sceneToLoadInfo.sceneIndex;
1317
+ window.location.replace(newUrl);
1318
+ } else {
1319
+ this.changeState(kShowControllerState_IdleAtFinalState);
1320
+ }
1321
+ },
1322
+
1323
+ jumpToScene_partTwo: function(sceneIndex, playAnimations) {
1324
+ this.changeState(kShowControllerState_SettingUpScene);
1325
+
1326
+ // state changed (UI controls should disable), run partThree in next event loop
1327
+ runInNextEventLoop(this.jumpToScene_partThree.bind(this, sceneIndex, playAnimations));
1328
+ },
1329
+
1330
+ jumpToScene_partThree: function(sceneIndex, playAnimations) {
1331
+ var delayBeforeNextPart = false;
1332
+
1333
+ if (delayBeforeNextPart) {
1334
+ runInNextEventLoop(this.jumpToScene_partFour.bind(this, sceneIndex, playAnimations));
1335
+ } else {
1336
+ this.jumpToScene_partFour(sceneIndex, playAnimations);
1337
+ }
1338
+ },
1339
+
1340
+ jumpToScene_partFour: function(sceneIndex, playAnimations) {
1341
+ this.displayScene(sceneIndex);
1342
+
1343
+ if (this.starting) {
1344
+ // There is a bug in webkit - cursor not being able to change if sitting idle unless it has been moved
1345
+ // The workaround for the bug without moving the mouse cursor is to change DOM structure to force a redraw
1346
+ // References: http://code.google.com/p/chromium/issues/detail?id=26723
1347
+ if (this.maskElement != null) {
1348
+ document.body.removeChild(this.maskElement);
1349
+ this.maskElement = null;
1350
+ this.starting = false;
1351
+ }
1352
+
1353
+ window.focus();
1354
+ }
1355
+
1356
+ if (this.helpPlacard.isShowing) {
1357
+ this.helpPlacard.hide();
1358
+ }
1359
+
1360
+ if (this.slideNumberDisplay.isShowing) {
1361
+ this.slideNumberDisplay.hide();
1362
+ }
1363
+
1364
+ if (this.slideNumberController.isShowing) {
1365
+ if (this.slideNumberTimeout) {
1366
+ clearTimeout(this.slideNumberTimeout);
1367
+ }
1368
+ this.slideNumberTimeout = setTimeout(this.hideAndResetSlideNumberController.bind(this), 500);
1369
+ }
1370
+
1371
+ if (playAnimations) {
1372
+ var script = this.script;
1373
+
1374
+ if (script.showMode === kShowModeAutoplay) {
1375
+ var event = script.events[sceneIndex];
1376
+ var effects = event.effects;
1377
+
1378
+ if (effects && effects.length > 0) {
1379
+ var delay = effects[0].type === "transition" ? script.autoplayTransitionDelay : script.autoplayBuildDelay;
1380
+
1381
+ setTimeout((function(){this.playCurrentScene();}).bind(this), delay * 1000);
1382
+ } else {
1383
+ this.playCurrentScene();
1384
+ }
1385
+ } else {
1386
+ this.playCurrentScene();
1387
+ }
1388
+ } else {
1389
+ this.changeState(kShowControllerState_IdleAtInitialState);
1390
+
1391
+ if (this.isRecording && !this.isRecordingStarted) {
1392
+ this.narrationManager.start();
1393
+ this.isRecordingStarted = true;
1394
+ }
1395
+ }
1396
+ },
1397
+
1398
+ displayScene: function(sceneIndex, hyperlinkEvent) {
1399
+ if (sceneIndex === -1) {
1400
+ return;
1401
+ }
1402
+
1403
+ // remove all css
1404
+ this.animationManager.deleteAllAnimations();
1405
+
1406
+ // clean up media cache if we are advancing to different slide
1407
+ var outgoingSlideIndex = this.scriptManager.slideIndexFromSceneIndex(this.currentSceneIndex);
1408
+ var incomingSlideIndex = hyperlinkEvent ? hyperlinkEvent.slideIndex : this.scriptManager.slideIndexFromSceneIndex(sceneIndex);
1409
+
1410
+ if (outgoingSlideIndex !== incomingSlideIndex) {
1411
+ this.resetMediaCache();
1412
+ }
1413
+
1414
+ // set currentSceneIndex
1415
+ this.setCurrentSceneIndexTo(sceneIndex);
1416
+
1417
+ if (hyperlinkEvent) {
1418
+ this.playbackController.renderEvent(hyperlinkEvent);
1419
+ } else {
1420
+ var slideIndex = this.script.slideIndexFromSceneIndexLookup[sceneIndex];
1421
+ var slideId = this.script.slideList[slideIndex];
1422
+
1423
+ var kpfEvent = new KPFEvent({
1424
+ "slideId": slideId,
1425
+ "slideIndex": slideIndex,
1426
+ "sceneIndex": sceneIndex,
1427
+ "event": this.script.events[sceneIndex],
1428
+ "animationSupported": this.animationSupported
1429
+ });
1430
+
1431
+ this.playbackController.renderEvent(kpfEvent);
1432
+ }
1433
+
1434
+ this.updateNavigationButtons();
1435
+ },
1436
+
1437
+ setCurrentSceneIndexTo: function(sceneIndex) {
1438
+ this.currentSceneIndex = sceneIndex;
1439
+ this.assignNextSceneIndex();
1440
+
1441
+ this.updateSlideNumber();
1442
+ this.updateNavigationButtons();
1443
+ },
1444
+
1445
+ assignNextSceneIndex: function() {
1446
+ this.nextSceneIndex = this.calculateNextSceneIndex(this.currentSceneIndex);
1447
+ },
1448
+
1449
+ calculateNextSceneIndex: function(sceneIndex) {
1450
+ var nextSceneIndex = this.calculateNextSceneIndex_internal(sceneIndex);
1451
+
1452
+ return nextSceneIndex;
1453
+ },
1454
+
1455
+ calculateNextSceneIndex_internal: function(sceneIndex) {
1456
+ var nextSceneIndex = -1;
1457
+
1458
+ if (sceneIndex < this.script.lastSceneIndex) {
1459
+ nextSceneIndex = sceneIndex + 1;
1460
+ } else {
1461
+ if (this.script.loopSlideshow) {
1462
+ nextSceneIndex = 0;
1463
+ } else {
1464
+ nextSceneIndex = -1;
1465
+ }
1466
+ }
1467
+
1468
+ return nextSceneIndex;
1469
+ },
1470
+
1471
+ updateSlideNumber: function() {
1472
+ var adjustedSceneIndex = this.currentSceneIndex;
1473
+
1474
+ if (this.state === kShowControllerState_IdleAtFinalState) {
1475
+ // because we're waiting at end state, we need to add one...
1476
+ adjustedSceneIndex = this.nextSceneIndex;
1477
+ }
1478
+
1479
+ var newSlideIndex = this.scriptManager.slideIndexFromSceneIndex(adjustedSceneIndex);
1480
+
1481
+ if (this.firstSlide) {
1482
+ this.displayManager.hideWaitingIndicator();
1483
+
1484
+ runInNextEventLoop((function() {
1485
+ this.startSoundTrack();
1486
+ this.displayManager.clearLaunchMode();
1487
+ }).bind(this));
1488
+ this.firstSlide = false;
1489
+ }
1490
+
1491
+ if (this.currentSlideIndex != newSlideIndex) {
1492
+ this.previousSlideIndex = this.currentSlideIndex;
1493
+ this.currentSlideIndex = newSlideIndex;
1494
+
1495
+ this.displayManager.updateSlideNumber(this.currentSlideIndex + 1, this.script.slideCount);
1496
+ this.delegate.propertyChanged(kPropertyName_currentSlide, this.currentSlideIndex + 1);
1497
+
1498
+ // fire SlideIndexDidChangeEvent
1499
+ document.fire(kSlideIndexDidChangeEvent, {
1500
+ slideIndex: this.currentSlideIndex
1501
+ });
1502
+ }
1503
+ },
1504
+
1505
+ updateNavigationButtons: function() {
1506
+ var sceneIndexToUse = this.currentSceneIndex;
1507
+
1508
+ if (this.state === kShowControllerState_IdleAtFinalState) {
1509
+ sceneIndexToUse++;
1510
+ }
1511
+
1512
+ this.updateWindowHistory(sceneIndexToUse);
1513
+
1514
+ var enableBackwardButton = false;
1515
+ var enableForwardButton = false
1516
+
1517
+ if (this.script.lastSceneIndex === -1) {
1518
+ // this slideshow has only 1 slide with no builds, both buttons are
1519
+ // disabled
1520
+ enableForwardButton = false;
1521
+ enableBackwardButton = false;
1522
+ } else if (this.script.loopSlideshow) {
1523
+ // this is a looping slideshow, both buttons are ALWAYS enabled
1524
+ enableForwardButton = true;
1525
+ enableBackwardButton = true;
1526
+ } else {
1527
+ if (sceneIndexToUse > 0) {
1528
+ // sceneIndexToUse > 0, so enable backward button
1529
+ enableBackwardButton = true;
1530
+ }
1531
+
1532
+ if (sceneIndexToUse === 0 && this.script.lastSceneIndex === 0) {
1533
+ // sceneIndexToUse & lastSceneIndex are both 0 - show with 1
1534
+ // slide with 1 build, so enable forward button
1535
+ enableForwardButton = true;
1536
+ } else if (this.currentSceneIndex < this.script.lastSceneIndex) {
1537
+ // currentSceneIndex < lastSceneIndex, so enable forward button
1538
+ enableForwardButton = true;
1539
+ } else if (this.currentSceneIndex === this.script.lastSceneIndex) {
1540
+ if (this.state === kShowControllerState_IdleAtInitialState) {
1541
+ // currentSceneIndex === lastSceneIndex, but we're at the
1542
+ // intitial state, so enable forward button
1543
+ enableForwardButton = true;
1544
+ } else {
1545
+ // currentSceneIndex === lastSceneIndex, and we're at the
1546
+ // final state, so disable forward button
1547
+ enableForwardButton = false;
1548
+ }
1549
+ } else {
1550
+ // currentSceneIndex > lastSceneIndex, show with 1 slide and no
1551
+ // builds, so disable forward button
1552
+ enableForwardButton = false;
1553
+ }
1554
+ }
1555
+
1556
+ this.displayManager.setPreviousButtonEnabled(enableBackwardButton);
1557
+ this.displayManager.setNextButtonEnabled(enableForwardButton);
1558
+ },
1559
+
1560
+ playCurrentScene: function(hyperlinkEventInfo) {
1561
+ var previousState = this.state;
1562
+ var sceneIndexToJump;
1563
+ var delay = 0;
1564
+ var duration = this.playbackController.eventOverallEndTime();
1565
+
1566
+ this.changeState(kShowControllerState_Playing);
1567
+
1568
+ this.clearAllHyperlinks();
1569
+
1570
+ if (this.helpPlacard.isShowing) {
1571
+ this.helpPlacard.hide();
1572
+ }
1573
+
1574
+ if (this.slideNumberDisplay.isShowing) {
1575
+ this.slideNumberDisplay.hide();
1576
+ }
1577
+
1578
+ if (hyperlinkEventInfo) {
1579
+ sceneIndexToJump = hyperlinkEventInfo.sceneIndexToJump;
1580
+
1581
+ // clean up media cache if we are playing hyperlink transition
1582
+ this.resetMediaCache();
1583
+ } else {
1584
+ sceneIndexToJump = this.nextSceneIndex;
1585
+
1586
+ // clean up media cache if we are advancing to different slide
1587
+ var outgoingSlideIndex = this.scriptManager.slideIndexFromSceneIndex(this.currentSceneIndex);
1588
+ var incomingSlideIndex = this.scriptManager.slideIndexFromSceneIndex(sceneIndexToJump);
1589
+
1590
+ if (outgoingSlideIndex !== incomingSlideIndex) {
1591
+ this.resetMediaCache();
1592
+ }
1593
+
1594
+ // for transition, the delay time is no longer coded into animations.
1595
+ // set delay time and duration for automaticPlay transition
1596
+ if (this.playbackController.kpfEvent.event.automaticPlay == true && this.playbackController.kpfEvent.event.effects[0].type === "transition") {
1597
+ delay = this.playbackController.kpfEvent.event.effects[0].beginTime;
1598
+ duration = this.playbackController.kpfEvent.event.effects[0].duration;
1599
+ }
1600
+ }
1601
+
1602
+ if (this.animationSupported) {
1603
+ // animate events
1604
+ // Chrome chokes up in some animations if starting animations immediately after layer drawings all on the main thread
1605
+ // Start animations in a background thread will improve performance
1606
+ // see <rdar://problem/12636430> DEMO: Chrome performance issues with cube, flip, push
1607
+ clearTimeout(this.animateTimeout);
1608
+
1609
+ var effects = this.playbackController.kpfEvent.event.effects;
1610
+
1611
+ // if the event has no effects then no need to render effects
1612
+ if (effects.length === 0) {
1613
+ this.animateTimeout = setTimeout((function(){
1614
+ setTimeout(this.currentSceneDidComplete.bind(this, sceneIndexToJump), duration * 1000 + 100);
1615
+ }).bind(this), delay * 1000);
1616
+ } else {
1617
+ var renderedEffects;
1618
+ // for performance consideration, render the effects as soon as we start playing so the effects are prepared and ready to animate
1619
+ // for blinds there is an issue with incoming particles on top of ougoing particles
1620
+ // since we don't want to show incoming particles before the animations start, we will render the effect later after delay as an exception case
1621
+ if (effects[0].type === "transition") {
1622
+ if (isIE || isEdge) {
1623
+ // Blinds fallback to dissolve on IE so ok to render here without seeing particle in reverse order
1624
+ renderedEffects = this.playbackController.renderEffects();
1625
+ } else {
1626
+ if (effects[0].name != "com.apple.iWork.Keynote.BLTBlinds") {
1627
+ renderedEffects = this.playbackController.renderEffects();
1628
+ }
1629
+ }
1630
+ }
1631
+
1632
+ // account for transition delay and start animating the effects after transition delay
1633
+ this.animateTimeout = setTimeout((function(renderedEffects){
1634
+ if (renderedEffects == null) {
1635
+ renderedEffects = this.playbackController.renderEffects();
1636
+ }
1637
+ this.playbackController.animateEffects(renderedEffects);
1638
+ setTimeout(this.currentSceneDidComplete.bind(this, sceneIndexToJump), duration * 1000 + 100);
1639
+ }).bind(this, renderedEffects), delay * 1000);
1640
+ }
1641
+ } else {
1642
+ var automatic = this.script.events[this.currentSceneIndex].automaticPlay;
1643
+
1644
+ if (sceneIndexToJump === -1) {
1645
+ this.updateNavigationButtons();
1646
+ if (this.delegate.getKPFJsonStringForShow) {
1647
+ if (automatic) {
1648
+ setTimeout(this.exitShow.bind(this), 2000);
1649
+ } else {
1650
+ this.exitShow();
1651
+ }
1652
+ } else {
1653
+ this.changeState(kShowControllerState_IdleAtInitialState);
1654
+ }
1655
+ } else {
1656
+ // For IE9, animate current event means jump to next slide since there is no animated end state
1657
+ if (automatic) {
1658
+ // For IE9, do a flat 2 sec delay for any automatic event to jump to next scene
1659
+ setTimeout(
1660
+ (function(){
1661
+ this.changeState(kShowControllerState_IdleAtInitialState);
1662
+ this.jumpToScene(sceneIndexToJump, this.script.events[sceneIndexToJump].automaticPlay);
1663
+ }).bind(this), 2000);
1664
+ } else {
1665
+ // if it's not automatic then jump to next scene
1666
+ this.changeState(kShowControllerState_IdleAtInitialState);
1667
+ setTimeout(this.jumpToScene.bind(this, sceneIndexToJump, this.script.events[sceneIndexToJump].automaticPlay), 100);
1668
+ }
1669
+ }
1670
+ }
1671
+
1672
+ },
1673
+
1674
+ currentSceneDidComplete: function(sceneIndexToJump) {
1675
+ var script = this.script;
1676
+ var showMode = script.showMode;
1677
+
1678
+ // hide slide number display after playing current scene
1679
+ if (this.slideNumberDisplay.isShowing) {
1680
+ this.slideNumberDisplay.hide();
1681
+ }
1682
+
1683
+ // change state to final after animation completed
1684
+ this.changeState(kShowControllerState_IdleAtFinalState);
1685
+
1686
+ if (showMode == kShowModeHyperlinksOnly || (sceneIndexToJump != -1 && sceneIndexToJump != this.nextSceneIndex)) {
1687
+ // if the show mode is hyperlink only
1688
+ // or if we play hyperlink transition that jumps to a slide which is not its next slide
1689
+ // then jump to the slide after transition
1690
+ var event = script.events[sceneIndexToJump];
1691
+ var automaticPlay = event.automaticPlay == 1 || event.automaticPlay == true;
1692
+ this.jumpToScene(sceneIndexToJump, automaticPlay);
1693
+ } else if (this.nextSceneIndex === -1) {
1694
+ // if next index is -1
1695
+ this.updateNavigationButtons();
1696
+ if (this.delegate.getKPFJsonStringForShow) {
1697
+ this.stopSoundTrack();
1698
+ this.exitShow();
1699
+ } else {
1700
+ this.stopSoundTrack();
1701
+ }
1702
+ } else if (script.events[this.nextSceneIndex].automaticPlay || showMode === kShowModeAutoplay) {
1703
+ // invoking advanceToNextBuild() on next event loop
1704
+ runInNextEventLoop(this.advanceToNextBuild.bind(this, "currentSceneDidComplete"));
1705
+ }
1706
+ },
1707
+
1708
+ resetMediaCache: function() {
1709
+ this.resetMovieCache();
1710
+ this.resetAudioCache();
1711
+ },
1712
+
1713
+ resetMovieCache: function() {
1714
+ for (var movieId in this.movieCache) {
1715
+ delete this.movieCache[movieId].videoElement;
1716
+ delete this.movieCache[movieId];
1717
+ }
1718
+
1719
+ this.movieCache = null;
1720
+ },
1721
+
1722
+ resetAudioCache: function() {
1723
+ for (var audioId in this.audioCache) {
1724
+ this.audioCache[audioId].pause();
1725
+ this.audioCache[audioId].src = "";
1726
+
1727
+ delete this.audioCache[audioId];
1728
+ }
1729
+ this.audioCache = null;
1730
+ },
1731
+
1732
+ updateWindowHistory: function(sceneIndex) {
1733
+ // update url
1734
+ if (typeof(window.history.replaceState) != "undefined") {
1735
+ var currentUrl = document.URL.split("?");
1736
+ var fragments = currentUrl[0].split("#");
1737
+ if (window.location.protocol !== "file:") {
1738
+ window.history.replaceState(null, "Keynote", fragments[0] + "#" + sceneIndex + (currentUrl[1] ? "?" + currentUrl[1] : ""));
1739
+ }
1740
+ }
1741
+ },
1742
+
1743
+ startSoundTrack: function() {
1744
+ if (gMode === kModeMobile) {
1745
+ return;
1746
+ }
1747
+
1748
+ if (this.script.soundtrack == null) {
1749
+ return;
1750
+ }
1751
+
1752
+ if (this.script.soundtrack.tracks == null) {
1753
+ return;
1754
+ }
1755
+
1756
+ if (this.script.soundtrack.mode === kSoundTrackModeOff) {
1757
+ return;
1758
+ }
1759
+
1760
+ this.currentSoundTrackIndex = 0;
1761
+ this.playNextItemInSoundTrack();
1762
+ },
1763
+
1764
+ stopSoundTrack: function() {
1765
+ if (this.soundTrackPlayer) {
1766
+ this.soundTrackPlayer.stopObserving("ended");
1767
+ this.soundTrackPlayer.pause();
1768
+ this.soundTrackPlayer = null;
1769
+ }
1770
+ },
1771
+
1772
+ playNextItemInSoundTrack: function() {
1773
+ var soundtrackUrl = this.script.soundtrack.tracks[this.currentSoundTrackIndex];
1774
+
1775
+ this.soundTrackPlayer = new Audio();
1776
+ this.soundTrackPlayer.src = "../" + soundtrackUrl;
1777
+ this.soundTrackPlayer.volume = this.script.soundtrack.volume;
1778
+ this.soundTrackPlayer.observe("ended", this.soundTrackItemDidComplete.bind(this), false);
1779
+ this.soundTrackPlayer.load();
1780
+ this.soundTrackPlayer.play();
1781
+ },
1782
+
1783
+ soundTrackItemDidComplete: function() {
1784
+ // check to see if there's anything else to play
1785
+ this.currentSoundTrackIndex++;
1786
+ if (this.currentSoundTrackIndex < this.script.soundtrack.tracks.length) {
1787
+ this.playNextItemInSoundTrack();
1788
+ } else {
1789
+ if (this.script.soundtrack.mode === kSoundTrackModePlayOnce) {
1790
+ this.soundTrackPlayer = null;
1791
+ } else if (this.script.soundtrack.mode === kSoundTrackModeLooping) {
1792
+ // nope, but we're in loop mode so take it from the top
1793
+ this.startSoundTrack();
1794
+ }
1795
+ }
1796
+ },
1797
+
1798
+ processHyperlink: function(hyperlink) {
1799
+ var hyperlinkUrl = hyperlink.url;
1800
+ var hyperlinkEffect;
1801
+
1802
+ // perform hyperlink jump
1803
+ if (hyperlinkUrl.indexOf("?slide=") === 0) {
1804
+ var key = hyperlinkUrl.substring(7);
1805
+ var newSlideIndex = -1;
1806
+
1807
+ if (key === "first") {
1808
+ newSlideIndex = 0;
1809
+ } else if (key === "last") {
1810
+ newSlideIndex = this.script.slideCount - 1;
1811
+ } else {
1812
+ var sceneIndexToUse = this.currentSceneIndex;
1813
+ var nextSlideIndex = -1;
1814
+ switch (this.state) {
1815
+ case kShowControllerState_IdleAtFinalState:
1816
+ sceneIndexToUse = sceneIndexToUse + 1;
1817
+ case kShowControllerState_IdleAtInitialState:
1818
+ var currentSlideIndex = this.scriptManager.slideIndexFromSceneIndex(sceneIndexToUse);
1819
+ if (key === "next") {
1820
+ if (currentSlideIndex === this.script.slideCount - 1) {
1821
+ if (this.script.loopSlideshow) {
1822
+ nextSlideIndex = 0;
1823
+ } else {
1824
+ if (this.delegate.getKPFJsonStringForShow) {
1825
+ this.exitShow();
1826
+ }
1827
+ }
1828
+ } else {
1829
+ nextSlideIndex = currentSlideIndex + 1;
1830
+ }
1831
+ } else if (key === "previous") {
1832
+ if (currentSlideIndex === 0) {
1833
+ if (this.script.loopSlideshow) {
1834
+ nextSlideIndex = this.script.slideCount - 1;
1835
+ } else {
1836
+ nextSlideIndex = 0;
1837
+ }
1838
+ } else {
1839
+ nextSlideIndex = currentSlideIndex - 1;
1840
+ }
1841
+ }
1842
+ break;
1843
+
1844
+ default:
1845
+ break;
1846
+ }
1847
+ newSlideIndex = nextSlideIndex;
1848
+
1849
+ }
1850
+
1851
+ if (newSlideIndex != -1) {
1852
+ this.jumpToHyperlinkSlide(newSlideIndex, hyperlink);
1853
+ }
1854
+ } else if (hyperlinkUrl.indexOf("?slideid=") === 0) {
1855
+ // find by slideId
1856
+ var slideId = hyperlinkUrl.substring(9);
1857
+ var slideList = this.script.slideList;
1858
+ var newSlideIndex = -1;
1859
+
1860
+ for (var i = 0, length = slideList.length; i < length; i++) {
1861
+ if (slideList[i] === slideId) {
1862
+ newSlideIndex = i;
1863
+ break;
1864
+ }
1865
+ }
1866
+
1867
+ if (newSlideIndex != -1) {
1868
+ this.jumpToHyperlinkSlide(newSlideIndex, hyperlink);
1869
+ }
1870
+ } else if (hyperlinkUrl.indexOf("?action=retreat") === 0) {
1871
+ // jump to the last slide viewed
1872
+ if (this.lastSlideViewedIndex != -1) {
1873
+ this.jumpToHyperlinkSlide(this.lastSlideViewedIndex, hyperlink);
1874
+ }
1875
+ } else if (hyperlinkUrl.indexOf("?action=exitpresentation") === 0) {
1876
+ // exit show
1877
+ this.exitShow();
1878
+ } else if (hyperlinkUrl.indexOf("http:") === 0 || hyperlinkUrl.indexOf("https:") === 0) {
1879
+ // jump to a web page
1880
+ window.open(hyperlinkUrl, "_blank", null);
1881
+ } else if (hyperlinkUrl.indexOf("mailto:") === 0) {
1882
+ // email link
1883
+ window.location = hyperlinkUrl;
1884
+ }
1885
+ },
1886
+
1887
+ jumpToHyperlinkSlide: function(slideIndexToJump, hyperlink) {
1888
+ //var hyperlinkEffects = hyperlink.effects;
1889
+ var hyperlinkEvents = hyperlink.events;
1890
+ var sceneIndexToJump = this.script.sceneIndexFromSlideIndexLookup[slideIndexToJump];
1891
+
1892
+ if (hyperlinkEvents) {
1893
+ // if hyperlink has effect then display scene and use hyperlink event
1894
+ var slideIdToJump = this.script.slideList[slideIndexToJump];
1895
+ var hyperlinkEvent = hyperlinkEvents[slideIdToJump];
1896
+
1897
+ if (hyperlinkEvent) {
1898
+ var sceneIndexOfHyperlink = this.currentSceneIndex;
1899
+
1900
+ switch (this.state) {
1901
+ case kShowControllerState_IdleAtFinalState:
1902
+ if (sceneIndexOfHyperlink < this.script.numScenes - 1) {
1903
+ sceneIndexOfHyperlink = sceneIndexOfHyperlink + 1;
1904
+ } else {
1905
+ if (this.script.loopSlideshow) {
1906
+ sceneIndexOfHyperlink = 0;
1907
+ }
1908
+ }
1909
+ case kShowControllerState_IdleAtInitialState:
1910
+ var slideIndexOfHyperlink = this.script.slideIndexFromSceneIndexLookup[sceneIndexOfHyperlink];
1911
+ var slideIdOfHyperlink = this.script.slideList[slideIndexOfHyperlink];
1912
+
1913
+ var kpfEvent = new KPFEvent({
1914
+ "slideId": slideIdOfHyperlink,
1915
+ "slideIndex": slideIndexOfHyperlink,
1916
+ "sceneIndex": sceneIndexOfHyperlink,
1917
+ "event": hyperlinkEvent,
1918
+ "animationSupported": this.animationSupported
1919
+ });
1920
+
1921
+ // display scene that contains hyperlink and use hyperlink event
1922
+ this.displayScene(sceneIndexOfHyperlink, kpfEvent);
1923
+
1924
+ // play current hyperlink scene
1925
+ this.playCurrentScene({"sceneIndexToJump": sceneIndexToJump});
1926
+
1927
+ break;
1928
+
1929
+ default:
1930
+ return;
1931
+ }
1932
+ } else {
1933
+ // if no hyperlink effect, just jump to slide
1934
+ var event = this.script.events[sceneIndexToJump];
1935
+ var automaticPlay = event.automaticPlay == 1 || event.automaticPlay == true;
1936
+ this.jumpToSlide(slideIndexToJump + 1, automaticPlay);
1937
+ }
1938
+ } else {
1939
+ // if no hyperlink effect, just jump to slide
1940
+ var event = this.script.events[sceneIndexToJump];
1941
+ var automaticPlay = event.automaticPlay == 1 || event.automaticPlay == true;
1942
+ this.jumpToSlide(slideIndexToJump + 1, automaticPlay);
1943
+ }
1944
+ },
1945
+
1946
+ addMovieHyperlink: function(targetRectangle, url) {
1947
+ var newHyperlink = {
1948
+ targetRectangle: targetRectangle,
1949
+ url: url
1950
+ };
1951
+ this.movieHyperlinks.push(newHyperlink);
1952
+ },
1953
+
1954
+ clearMovieHyperlinks: function() {
1955
+ delete this.movieHyperlinks;
1956
+ this.movieHyperlinks = new Array();
1957
+ },
1958
+
1959
+ clearAllHyperlinks: function() {
1960
+ this.stageManager.clearAllHyperlinks();
1961
+
1962
+ delete this.activeHyperlinks;
1963
+ this.activeHyperlinks = new Array();
1964
+ },
1965
+
1966
+ findHyperlinkAtCoOrds: function(showCoOrds) {
1967
+ var numHyperlinks = this.activeHyperlinks != null ? this.activeHyperlinks.length : 0;
1968
+
1969
+ for (var i = numHyperlinks; i > 0; i--) {
1970
+ var hyperlink = this.activeHyperlinks[i - 1];
1971
+ var hyperlinkRect = hyperlink.targetRectangle;
1972
+
1973
+ hyperlinkLeft = Math.floor(hyperlinkRect.x);
1974
+ hyperlinkTop = Math.floor(hyperlinkRect.y);
1975
+ hyperlinkRight = hyperlinkLeft + Math.floor(hyperlinkRect.width);
1976
+ hyperlinkBottom = hyperlinkTop + Math.floor(hyperlinkRect.height);
1977
+
1978
+ if ((showCoOrds.pointX >= hyperlinkLeft) && (showCoOrds.pointX <= hyperlinkRight)
1979
+ && (showCoOrds.pointY >= hyperlinkTop) && (showCoOrds.pointY <= hyperlinkBottom)) {
1980
+ return hyperlink;
1981
+ }
1982
+ }
1983
+
1984
+ return null;
1985
+ },
1986
+
1987
+ createHyperlinksForCurrentState: function(context) {
1988
+ var sceneIndexOfHyperlinks = -1;
1989
+
1990
+ switch (this.state) {
1991
+ case kShowControllerState_IdleAtInitialState:
1992
+ // use current scene index
1993
+ sceneIndexOfHyperlinks = this.currentSceneIndex;
1994
+ break;
1995
+
1996
+ case kShowControllerState_IdleAtFinalState:
1997
+ // idle at final state, grab hyperlink from appropriate scene
1998
+ if (this.currentSceneIndex < this.script.lastSceneIndex) {
1999
+ sceneIndexOfHyperlinks = this.currentSceneIndex + 1;
2000
+ } else {
2001
+ // check if hyperlinks only mode
2002
+ if (this.script.showMode == kShowModeHyperlinksOnly) {
2003
+ sceneIndexOfHyperlinks = this.currentSceneIndex;
2004
+ } else {
2005
+ // check if loop slide show
2006
+ if (this.script.loopSlideshow) {
2007
+ sceneIndexOfHyperlinks = 0;
2008
+ }
2009
+ }
2010
+ }
2011
+ break;
2012
+
2013
+ default:
2014
+ break;
2015
+ }
2016
+
2017
+ if (sceneIndexOfHyperlinks != -1) {
2018
+ this.clearAllHyperlinks();
2019
+ this.createHyperlinks(sceneIndexOfHyperlinks);
2020
+ }
2021
+ },
2022
+
2023
+ createHyperlinks: function(hyperlinkSceneIndex) {
2024
+ if (hyperlinkSceneIndex === -1) {
2025
+ return;
2026
+ }
2027
+
2028
+ var eventTimeLine = this.script.events[hyperlinkSceneIndex];
2029
+ if (eventTimeLine == null) {
2030
+ return;
2031
+ }
2032
+
2033
+ var hyperlinks = eventTimeLine.hyperlinks;
2034
+ if (hyperlinks == null) {
2035
+ return;
2036
+ }
2037
+
2038
+ var numHyperlinks = hyperlinks.length;
2039
+ var iHyperlink;
2040
+ var kMinHyperlinkWidth = 150;
2041
+ var kMinHyperlinkHeight = 50;
2042
+ var showWidth = this.displayManager.showWidth;
2043
+ var showHeight = this.displayManager.showHeight;
2044
+
2045
+ for (iHyperlink = 0; iHyperlink < numHyperlinks; iHyperlink++) {
2046
+ var hyperlink = hyperlinks[iHyperlink];
2047
+ var hyperlinkRect = hyperlink.targetRectangle;
2048
+
2049
+ var activeHyperlink = {
2050
+ targetRectangle: hyperlinkRect,
2051
+ events: hyperlink.events,
2052
+ url: hyperlink.url
2053
+ };
2054
+
2055
+ var spaceOnLeft = hyperlinkRect.x;
2056
+ var spaceOnTop = hyperlinkRect.y;
2057
+ var spaceOnRight = showWidth - (hyperlinkRect.x + hyperlinkRect.width);
2058
+ var spaceOnBottom = showHeight - (hyperlinkRect.y + hyperlinkRect.top);
2059
+
2060
+ if (gMode === kModeMobile) {
2061
+ if (hyperlinkRect.width < kMinHyperlinkWidth) {
2062
+ var deltaWidth = kMinHyperlinkWidth - hyperlinkRect.width;
2063
+ var leftShift = deltaWidth / 2;
2064
+ var rightShift = deltaWidth / 2;
2065
+
2066
+ if (spaceOnLeft < leftShift) {
2067
+ leftShift = spaceOnLeft;
2068
+ } else if (spaceOnRight < rightShift) {
2069
+ leftShift = leftShift + (rightShift - spaceOnRight);
2070
+ }
2071
+
2072
+ activeHyperlink.targetRectangle.x -= leftShift;
2073
+ activeHyperlink.targetRectangle.width += deltaWidth;
2074
+ }
2075
+
2076
+ if (hyperlinkRect.height < kMinHyperlinkHeight) {
2077
+ var deltaHeight = kMinHyperlinkHeight - hyperlinkRect.height;
2078
+ var topShift = deltaHeight / 2;
2079
+ var bottomShift = deltaHeight / 2;
2080
+
2081
+ if (spaceOnTop < topShift) {
2082
+ topShift = spaceOnTop;
2083
+ } else if (spaceOnBottom < bottomShift) {
2084
+ topShift = topShift + (rightShift - spaceOnRight);
2085
+ }
2086
+
2087
+ activeHyperlink.targetRectangle.y -= topShift;
2088
+ activeHyperlink.targetRectangle.height += deltaHeight;
2089
+ }
2090
+ }
2091
+ this.stageManager.addHyperlink(activeHyperlink.targetRectangle);
2092
+ this.activeHyperlinks[iHyperlink] = activeHyperlink;
2093
+ }
2094
+
2095
+ if (this.movieHyperlinks.length > 0) {
2096
+ for (var iMovieHyperlink = 0; iMovieHyperlink < this.movieHyperlinks.length; iMovieHyperlink++) {
2097
+ var movieHyperlink = this.movieHyperlinks[iMovieHyperlink];
2098
+
2099
+ this.stageManager.addHyperlink(movieHyperlink.targetRectangle);
2100
+ this.activeHyperlinks[iHyperlink++] = movieHyperlink;
2101
+ }
2102
+ }
2103
+ }
2104
+
2105
+ });
assets/player/SlideManager.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:9f45437168a14fc80c5963c21c38fa40f11af08a57189b52bd33a185557ddad4
3
- size 1603
 
1
+ var SlideManager=Class.create({initialize:function(c){this.header=c.header;this.slides={};for(var a=0,b=this.header.slideList.length;a<b;a++){this.slides[this.header.slideList[a]]={downloaded:false,script:{},retry:0}}},getSlides:function(d,b){for(var a=0,c=d.length;a<c;a++){var e=d[a];this.slides[e].downloaded=true;this.slides[e].script=JSON.parse(b.getKPFJsonStringForSlideIndex(a));this.slides[e].originalScript=JSON.parse(b.getKPFJsonStringForSlideIndex(a));document.fire(kSlideDidDownloadEvent,{id:e})}},downloadSlides:function(c){for(var a=0,b=c.length;a<b;a++){this.downloadSlide(c[a])}},downloadSlide:function(b){var c="../"+b+"/"+b+".json";if(window.location.protocol==="file:"){c=c+"p";if(window.local_slide==null||window.local_slide==undefined){window.local_slide=(function(d){this.slideDidDownload(null,d,true)}).bind(this)}var a=document.createElement("script");a.setAttribute("src",c);document.head.appendChild(a)}else{new Ajax.Request(c,{method:"get",onSuccess:this.slideDidDownload.bind(this,b),onFailure:this.slideDidNotDownload.bind(this,b)})}},slideDidDownload:function(c,b,a){if(a){c=b.name;this.slides[c].script=b.json;this.slides[c].originalScript=JSON.parse(JSON.stringify(b.json))}else{this.slides[c].script=JSON.parse(b.responseText);this.slides[c].originalScript=JSON.parse(b.responseText)}this.slides[c].downloaded=true;document.fire(kSlideDidDownloadEvent,{id:c})},slideDidNotDownload:function(){var a=arguments[0];if(arguments[1].status!=200){if(this.slides[a].retry<1){this.downloadSlide(a);this.slides[a].retry++}else{document.fire(kSlideDidNotDownloadEvent,{id:a})}}}});
 
 
assets/player/SlideNumberController.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:804f3d0fb6dfbb0773a2f6f1906656da3305e02907f4a923e2b3aa82ba390e17
3
- size 1574
 
1
+ var SlideNumberController=Class.create({initialize:function(a,b){this.domNode=a;this.width=120;this.height=110;this.slideNumberLabel=document.createElement("div");this.slideNumberLabel.setAttribute("class","slideNumberLabel");if(b){this.slideNumberLabel.innerHTML=b}else{this.slideNumberLabel.innerHTML="Press Return to go to slide:"}this.slideNumberDigit=document.createElement("div");this.slideNumberDigit.setAttribute("class","slideNumberDigit");this.domNode.appendChild(this.slideNumberLabel);this.domNode.appendChild(this.slideNumberDigit);this.isShowing=false},setPosition:function(b,a){this.domNode.style.left=b+"px";this.domNode.style.top=a+"px"},setSlideNumber:function(a){this.slideNumberDigit.innerHTML=a},show:function(){this.isShowing=true;this.domNode.style.display="block";this.domNode.style.opacity=1},hide:function(){this.isShowing=false;this.domNode.style.display="none";this.domNode.style.opacity=0}});var SlideNumberDisplay=Class.create({initialize:function(a){this.domNode=a;this.width=100;this.height=100;this.slideNumberDigit=document.createElement("div");this.slideNumberDigit.setAttribute("class","slideNumberDisplayDigit");this.domNode.appendChild(this.slideNumberDigit);this.isShowing=false},setPosition:function(b,a){this.domNode.style.left=b+"px";this.domNode.style.top=a+"px"},setSlideNumber:function(a){this.slideNumberDigit.innerHTML=a},show:function(a){this.isShowing=true;this.domNode.style.display="block";this.domNode.style.opacity=1},hide:function(){this.isShowing=false;this.domNode.style.display="none";this.domNode.style.opacity=0}});
 
 
assets/player/StageManager.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:6632cecf853f8167cc684c80fa9d0495fbf16ea15ab1a6863b3f28c7cd7b2b86
3
- size 2482
 
1
+ var kStageIsReadyEvent="StageManager:StageIsReadyEvent";var StageManager=Class.create({initialize:function(a,b){this.textureManager=a;this.scriptManager=b;this.stage=document.getElementById("stage");this.hyperlinkPlane=document.getElementById("hyperlinkPlane");this.stageWidth=0;this.stageHeight=0;this.showWidth=0;this.showHeight=0;this.audioTrackOffset=0;this.audioTrackIconSize=0;document.observe(kShowSizeDidChangeEvent,this.handleShowSizeDidChangeEvent.bind(this));document.observe(kStageSizeDidChangeEvent,this.handleStageSizeDidChangeEvent.bind(this))},removeTexture:function(a){a.parentNode.removeChild(a)},addHyperlink:function(b){var a=document.createElement("div");setElementProperty(a,"pointer-events","all");a.setAttribute("class","hyperlink");a.style.left=b.x+"px";a.style.top=b.y+"px";a.style.width=b.width+"px";a.style.height=b.height+"px";this.hyperlinkPlane.appendChild(a)},clearAllHyperlinks:function(){var a;while(this.hyperlinkPlane.childNodes.length>0){this.hyperlinkPlane.removeChild(this.hyperlinkPlane.firstChild)}this.audioTrackOffset=this.audioTrackSpacer},handleStageSizeDidChangeEvent:function(a){this.stageWidth=a.memo.width;this.stageHeight=a.memo.height;this.adjustStageToFit(this.stage);this.adjustStageToFit(this.hyperlinkPlane)},handleShowSizeDidChangeEvent:function(a){this.showWidth=a.memo.width;this.showHeight=a.memo.height;this.adjustStageToFit(this.stage);this.adjustStageToFit(this.hyperlinkPlane);this.audioTrackIconSize=this.showHeight/4;this.audioTrackSpacer=this.audioTrackIconSize/4;this.audioTrackOffset=this.audioTrackSpacer},adjustStageToFit:function(b){if((this.showWidth!=0)&&(this.stageWidth!=0)){var d=this.stageHeight/this.showHeight;var f=this.stageWidth/this.showWidth;var a="scaleX("+f+") scaleY("+d+")";var e=20;var c=Math.tan(Math.PI/180*e/2)*15*(this.showWidth>this.showHeight?this.showHeight:this.showWidth);this.perspective=c;setElementProperty(b,kTransformOriginPropertyName,kTransformOriginCenterPropertyValue);setElementProperty(b,kTransformPropertyName,a);setElementProperty(b,kPerspectiveOriginPropertyName,kTransformOriginCenterPropertyValue);setElementProperty(b,kTransformStylePropertyName,kTransformStylePreserve3DPropertyValue);setElementPosition(b,(d-1)*this.showHeight/2,(f-1)*this.showWidth/2,this.showWidth,this.showHeight);document.fire(kStageIsReadyEvent,{})}},debugGetStageStatistics:function(){var a={numTextures:0,numPixels:0,numDegraded:0};this.debugRecursivelyWalkDomFrom(this.stage,a);return a}});
 
 
assets/player/TSDAnimation.js CHANGED
@@ -1,3 +1,92 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:29167429c82725b33836870ce65eed621dc28a0bb023f34a61ac3fe1317faea5
3
- size 2761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TSDAnimation.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2016 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ // Stuff from TSDAnimation.h
10
+
11
+ // Common acceleration values.
12
+ var KNAnimationActionAcceleration = {
13
+ kSFXActionAccelerationNone: 0,
14
+ kSFXActionAccelerationEaseIn: 1,
15
+ kSFXActionAccelerationEaseOut: 2,
16
+ kSFXActionAccelerationEaseBoth: 3,
17
+ kSFXActionAccelerationCustom: 4
18
+ };
19
+
20
+ //Standard action build effect names.
21
+ var KNActionOpacityName = "apple:action-opacity";
22
+ var KNActionMotionPathName = "apple:action-motion-path";
23
+ var KNActionRotationName = "apple:action-rotation";
24
+ var KNActionScaleName = "apple:action-scale";
25
+
26
+ // Emphasis action build effect names.
27
+ var KNActionPopName = "apple:action-pop";
28
+ var KNActionPulseName = "apple:action-pulse";
29
+ var KNActionBlinkName = "apple:action-blink";
30
+ var KNActionFlipName = "apple:action-flip";
31
+ var KNActionBounceName = "apple:action-bounce";
32
+ var KNActionJiggleName = "apple:action-jiggle";
33
+
34
+ //Global directions
35
+ var KNDirection = {
36
+ kKNDirectionNone: 0,
37
+ kKNDirectionLeftToRight: 11,
38
+ kKNDirectionRightToLeft: 12,
39
+ kKNDirectionTopToBottom: 13,
40
+ kKNDirectionBottomToTop: 14,
41
+ kKNDirectionUpperLeftToBottomRight: 21,
42
+ kKNDirectionUpperRightToBottomLeft: 22,
43
+ kKNDirectionLowerLeftToUpperRight: 23,
44
+ kKNDirectionLowerRightToUpperLeft: 24,
45
+ kKNDirectionClockwise: 31,
46
+ kKNDirectionCounterclockwise: 32,
47
+ kKNDirectionIn: 41,
48
+ kKNDirectionOut: 42,
49
+ kKNDirectionUp: 43,
50
+ kKNDirectionDown: 44,
51
+ kKNDirectionStartToEnd: 51,
52
+ kKNDirectionEndToStart: 52,
53
+ kKNDirectionMiddleToEnds: 53,
54
+ kKNDirectionEndsToMiddle: 54,
55
+ kKNDirectionRandom: 91,
56
+ kKNDirectionAlternating: 92,
57
+ kKNDirectionSimultaneous: 93,
58
+ kKNDirectionBCForward: 111,
59
+ kKNDirectionBCBackward: 112,
60
+ kKNDirectionBCRandom: 113,
61
+ kKNDirectionBCCenter: 114,
62
+ kKNDirectionBCEdges: 115,
63
+ kKNDirectionGravity: 121,
64
+ kKNDirectionNoGravity: 122
65
+ };
66
+
67
+ // end of TSDAnimation.h
68
+
69
+ // Stuff from TSDAnimation.m
70
+ var kKNAnimationStringTypeNone = "None";
71
+ var kKNAnimationStringTypeBuildIn = "In";
72
+ var kKNAnimationStringTypeBuildOut = "Out";
73
+ var kKNAnimationStringTypeTransition = "Transition";
74
+ var kKNAnimationStringTypeActionBuild = "Action";
75
+
76
+ function KNEffectIsActionEffect(effect) {
77
+ if ([KNActionOpacityName, KNActionMotionPathName, KNActionRotationName, KNActionScaleName].indexOf(effect) > -1) {
78
+ return true;
79
+ } else {
80
+ return false;
81
+ }
82
+ }
83
+
84
+ function KNEffectIsEmphasisEffect(effect) {
85
+ if ([KNActionPopName, KNActionPulseName, KNActionBlinkName, KNActionFlipName, KNActionBounceName, KNActionJiggleName].indexOf(effect) > -1) {
86
+ return true;
87
+ } else {
88
+ return false;
89
+ }
90
+ }
91
+
92
+ // end of TSDAnimation.m
assets/player/TextureManager.js CHANGED
@@ -1,3 +1 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0fa34c7e1e40e795a04f8aabb1404f78603e8b4ca5c8c5f43c3147a3c3a3290e
3
- size 8074
 
1
+ var TextureManager=Class.create({initialize:function(a){this.script=null;this.showUrl=a;this.slideCache={};this.sceneDidLoadCallbackHandler=null;this.viewScale=1;document.observe(kScriptDidDownloadEvent,(function(b){this.handleScriptDidDownloadEvent(b)}).bind(this),false)},setSceneDidLoadCallbackHandler:function(a,b){this.sceneDidLoadCallbackHandler={handler:a,sceneIndex:b}},processTextureDidLoadCallback:function(d,b){if(this.sceneDidLoadCallbackHandler==null){return}var c=this.sceneDidLoadCallbackHandler.sceneIndex;var a=this.script.slideIndexFromSceneIndexLookup[c];if(a!=b){return}if(this.isSlidePreloaded(b)){this.callSceneDidLoadCallback();setTimeout(function(){this.destroyPDFDocument(b)}.bind(this),5000)}},destroyPDFDocument:function(c){var b=this.slideCache[c];if(b){var a=b.pdf;if(a){a.destroy();delete this.slideCache[c].pdf}}},processSlideDidLoadCallback:function(b){if(this.sceneDidLoadCallbackHandler==null){return}var c=this.sceneDidLoadCallbackHandler.sceneIndex;var a=this.script.slideIndexFromSceneIndexLookup[c];if(a!=b){return}this.callSceneDidLoadCallback()},processSceneDidLoadCallback:function(a){if(this.sceneDidLoadCallbackHandler&&a===this.sceneDidLoadCallbackHandler.sceneIndex&&this.isScenePreloaded(a)){this.callSceneDidLoadCallback()}},callSceneDidLoadCallback:function(){this.sceneDidLoadCallbackHandler.handler();this.sceneDidLoadCallbackHandler=null},loadScene:function(c,a){if(c<0||c>this.script.numScenes){return}if(a){this.setSceneDidLoadCallbackHandler(a,c)}var b=this.script.slideIndexFromSceneIndexLookup[c];if(usePDF){this.requestPdfDocument(b)}else{this.requestSlideSvgmap(b)}},preloadScenes:function(a){for(var c in a){var b=this.script.slideIndexFromSceneIndexLookup[c];if(b==null){continue}if(this.slideCache.hasOwnProperty(b)===false){this.loadScene(c)}}},isSlidePreloaded:function(b){var a=false;if(this.slideCache[b]){a=true;for(var c in this.slideCache[b].textureRequests){if(this.slideCache[b].textureRequests[c]===false){a=false;break}}}return a},isScenePreloaded:function(c){var b=this.script.slideIndexFromSceneIndexLookup[c];var a=this.isSlidePreloaded(b);return a},handleScriptDidDownloadEvent:function(a){this.script=a.memo.script;this.delegate=a.memo.delegate},requestPdfDocument:function(g){if(!this.slideCache[g]){this.slideCache[g]={textureAssets:{},textureRequests:{},pdf:null,requested:false}}var f=this.script.slideList[g];if(!this.slideCache[g].requested){var d=this.script.slides[f];var i=d.assets;for(var a in i){var e=i[a];if(e.type==="texture"){this.slideCache[g].textureRequests[a]=false}}}else{if(this.isSlidePreloaded(g)){this.processSlideDidLoadCallback(g)}return}var b=this.showUrl+f+"/assets/"+f+".pdf";var c={slideId:f,slideIndex:g};this.slideCache[g].requested=true;if(window.location.protocol==="file:"){b=b+"p";if(window.local_pdf==null||window.local_pdf==undefined){window.local_pdf=function(j){this.handleRequestLocalPdfCallback(j)}.bind(this)}var h=document.createElement("script");h.setAttribute("src",b);document.head.appendChild(h)}else{PDFJS.getDocument(b).then(this.handleRequestPdfDocumentCompleted.bind(this,c))}},handleRequestLocalPdfCallback:function(b){var a=b.slide;var d=this.script.slideList.indexOf(a);var e=atob(b.pdf);var c={slideId:a,slideIndex:d};PDFJS.getDocument({data:e}).then(this.handleRequestPdfDocumentCompleted.bind(this,c))},handleRequestPdfDocumentCompleted:function(d,b){var i=d.slideId;var j=d.slideIndex;var f=this.script.slides[i];var l=f.assets;this.slideCache[j]["pdf"]=b;for(var a in l){var h=l[a];if(h.type!=="texture"){continue}var g=this.urlForTexture(a,i);var m=/(?:\.([^.]+))?$/;var c=m.exec(g)[1];if(c.toLowerCase()==="pdf"){var k=h.index+1;b.getPage(k).then(this.handleRequestPdfPageCompleted.bind(this,a,j))}else{var e=new Image();Event.observe(e,"load",this.handleImageOnloadEvent.bind(this,a,j));e.src=g}}},handleRequestPdfPageCompleted:function(a,i,h){var g=h.getViewport(pdfScaleFactor);var d=document.createElement("canvas");var c=d.getContext("2d");d.height=g.height;d.width=g.width;var e={canvasContext:c,background:"rgba(0, 0, 0, 0)",viewport:g};var f=this;var b=h.render(e);var j=b._internalRenderTask.callback;b._internalRenderTask.callback=function(k){j.call(this,k);f.slideCache[i].textureAssets[a]=d;f.slideCache[i].textureRequests[a]=true;f.processTextureDidLoadCallback(a,i)}},requestSlideSvgmap:function(g){if(!this.slideCache[g]){this.slideCache[g]={};this.slideCache[g].textureAssets={};this.slideCache[g].textureRequests={}}var f=this.script.slideList[g];if(!this.slideCache[g]["svgmap"]){var d=this.script.slides[f];var i=d.assets;for(var a in i){var e=i[a];if(e.type==="texture"){this.slideCache[g].textureRequests[a]=false}}}else{if(this.isSlidePreloaded(g)){this.processSlideDidLoadCallback(g)}return}var c=this.showUrl+f+"/assets/"+f+".svgmap";if(window.location.protocol==="file:"){c=c+"p";if(window.svgmap==null||window.svgmap==undefined){window.svgmap=this.handleRequestSlideSvgmapCompleted.bind(this,null,true)}var h=document.createElement("script");h.setAttribute("src",c);document.head.appendChild(h)}else{var b={slideId:f,slideIndex:g};new Ajax.Request(c,{method:"get",onSuccess:this.handleRequestSlideSvgmapCompleted.bind(this,b,false)})}},handleRequestSlideSvgmapCompleted:function(n,l,f){var d;var a;if(l){d=f.slide;a=f.svg}else{d=n.slideId;a=JSON.parse(f.responseText)}var o=this.script.slideList.indexOf(d);var b=this.script.slides[d];var e=b.assets;this.slideCache[o]["svgmap"]=a;for(var r in e){var j=e[r];if(j.type!=="texture"){continue}var h=this.urlForTexture(r,d);var m=h.split("/");var g=m.length;var c=m[g-1];var p=c.split(".");var i=p[p.length-1];if(i==="svgmap"){var k=a[j.index];var n={textureId:r,slideId:d,slideIndex:o};this.handleFetchCompleted(n,k)}else{var q=new Image();Event.observe(q,"load",this.handleImageOnloadEvent.bind(this,r,o));q.src=h}}},handleFetchCompleted:function(q,k){var a=this.viewScale;var s=q.textureId;var b=q.slideId;var r=q.slideIndex;var c=new DOMParser();var l=this.showUrl+b+"/assets/";var h=c.parseFromString(k,"text/xml");var g=h.documentElement.getAttribute("viewBox").split(" ");var f=g[2];var m=g[3];var d=h.getElementsByTagName("image");for(var n=0,e=d.length;n<e;n++){var p=d[n];var o=p.getAttributeNS("http://www.w3.org/1999/xlink","href");p.setAttributeNS("http://www.w3.org/1999/xlink","href",l+o)}var j=document.importNode(h.documentElement,true);j.setAttributeNS("http://www.w3.org/2000/svg","width",f);j.setAttributeNS("http://www.w3.org/2000/svg","height",m);this.slideCache[r].textureAssets[s]=j;this.slideCache[r].textureRequests[s]=true;this.processTextureDidLoadCallback(s,r)},handleImageOnloadEvent:function(d,c,b){b=b||window.event;var a=b.target||b.srcElement;this.slideCache[c].textureAssets[d]=a;this.slideCache[c].textureRequests[d]=true;this.processTextureDidLoadCallback(d,c)},getTextureObject:function(d,c){var a;var b=this.script.slideIndexFromSceneIndexLookup[d];if(this.slideCache[b]){a=this.slideCache[b].textureAssets[c]}return a},getTextureInfo:function(e,d){var c=this.script.slideIndexFromSceneIndexLookup[e];if(c==null){return null}var a=this.script.slideList[c];var b=this.script.slides[a].assets[d];return b},getTextureUrl:function(d,c){var b=this.script.slideIndexFromSceneIndexLookup[d];if(b==null){return null}var a=this.script.slideList[b];return this.urlForTexture(c,a)},getMovieUrl:function(d,c){var b=this.script.slideIndexFromSceneIndexLookup[d];if(b==null){return null}var a=this.script.slideList[b];return this.urlForAsset(c,a)},urlForAsset:function(e,c){var b="";var d=this.script.slides[c].assets[e];if(d==null){return b}var a;if(usePDF){a=d.url["native"]}else{a=d.url.web}if((a!=null)&&(a!="")){if(a.toLowerCase().substring(0,4)==="http"){b=a}else{b=this.showUrl+(c?c+"/":"")+a}}return b},urlForTexture:function(b,a){return this.generateUrl(b,a,false)},generateUrl:function(e,b){var a="";var c="";var d=this.script.slides[b].assets[e];if(!d){return a}if(usePDF){c=d.url["native"]}else{c=d.url.web}if((c!=null)&&(c!="")){if(c.toLowerCase().substring(0,4)==="http"){a=c}else{a=this.showUrl+(b?b+"/":"")+c}}return a}});
 
 
assets/player/TouchController.js CHANGED
@@ -1,3 +1,276 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:3303249ccf4e718f93b6d7e1116906841d52fe36c70dbbdfcac4c5e6d66d1cf1
3
- size 10850
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TouchController.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Responsibility: Tungwei Cheng
6
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ // iPhone Event Name Constants:
10
+ // -----------------------------
11
+ var kTouchStartEventName = "touchstart";
12
+ var kTouchMoveEventName = "touchmove";
13
+ var kTouchEndEventName = "touchend";
14
+ var kTouchCancelEventName = "touchcancel";
15
+ var kGestureStartEventName = "gesturestart";
16
+ var kGestureEndEventName = "gestureend";
17
+
18
+ // Class: TouchController
19
+ // ===============================================================
20
+ var kSwipeEvent = "TouchController:SwipeEvent";
21
+ var kTapEvent = "TouchController:TapeEvent";
22
+
23
+ var TouchController = Class.create({
24
+ initialize: function() {
25
+ // observe touch events
26
+ document.observe(kTouchStartEventName, this.handleTouchStartEvent.bind(this));
27
+ document.observe(kTouchMoveEventName, this.handleTouchMoveEvent.bind(this));
28
+ document.observe(kTouchEndEventName, this.handleTouchEndEvent.bind(this));
29
+ document.observe(kTouchCancelEventName, this.handleTouchCancelEvent.bind(this));
30
+
31
+ // observe gesture events
32
+ document.observe(kGestureStartEventName, this.handleGestureStartEvent.bind(this));
33
+ document.observe(kGestureEndEventName, this.handleGestureEndEvent.bind(this));
34
+
35
+ this.swipeInProgress = false;
36
+ this.swipeFingerCount = 0;
37
+
38
+ this.swipeStartTime = 0;
39
+ this.swipeStartX = 0;
40
+ this.swipeStartY = 0;
41
+
42
+ this.preventDefault = true;
43
+
44
+ this.tapEventCallback = null;
45
+
46
+ this.setTrackArea(0, 0, 0, 0);
47
+
48
+ this.enableTouchTracking = true;
49
+ },
50
+
51
+ setTouchTrackingEnabled: function(isEnabled) {
52
+ this.enableTouchTracking = isEnabled;
53
+ },
54
+
55
+ setTrackArea: function(left, top, width, height) {
56
+ debugMessage(kDebugTouchController_SetTrackArea, "left: " + left + " top: " + top + " width: " + width + " height: " + height);
57
+
58
+ this.trackAreaLeft = left;
59
+ this.trackAreaTop = top;
60
+ this.trackAreaRight = left + width;
61
+ this.trackAreaBottom = top + height;
62
+ },
63
+
64
+ registerTapEventCallback: function(tapEventCallback) {
65
+ this.tapEventCallback = tapEventCallback;
66
+ },
67
+
68
+ isTouchWithinTrackArea: function(touch) {
69
+ debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "checking...");
70
+
71
+ if (this.enableTouchTracking === false) {
72
+ debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, tracking is disabled");
73
+ return false;
74
+ }
75
+
76
+ if (touch.clientX < this.trackAreaLeft) {
77
+ debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, x < left");
78
+ return false;
79
+ }
80
+
81
+ if (touch.clientX > this.trackAreaRight) {
82
+ debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, x > right");
83
+ return false;
84
+ }
85
+
86
+ if (touch.clientY < this.trackAreaTop) {
87
+ debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, y < top");
88
+ return false;
89
+ }
90
+
91
+ if (touch.clientY > this.trackAreaBottom) {
92
+ debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- nope, y > bottom");
93
+ return false;
94
+ }
95
+
96
+ debugMessage(kDebugTouchController_IsTouchWithinTrackArea, "- yes it is!");
97
+ return true;
98
+ },
99
+
100
+ handleTouchStartEvent: function(event) {
101
+ debugMessage(kDebugTouchController_HandleTouchStartEvent, "touch event has " + event.touches.length + " fingers...");
102
+
103
+ if (this.swipeInProgress === false) {
104
+ debugMessage(kDebugTouchController_HandleTouchStartEvent, "- this is the first finger down event...");
105
+
106
+ var startTouch = event.touches[0];
107
+
108
+ if (this.isTouchWithinTrackArea(startTouch)) {
109
+ debugMessage(kDebugTouchController_HandleTouchStartEvent, "- start tracking a swipt event...");
110
+
111
+ if (this.preventDefault) {
112
+ event.preventDefault();
113
+ }
114
+
115
+ this.swipeInProgress = true;
116
+ this.swipeFingerCount = event.touches.length;
117
+
118
+ this.swipeStartTime = new Date();
119
+ this.swipeStartX = startTouch.clientX;
120
+ this.swipeStartY = startTouch.clientY;
121
+
122
+ } else {
123
+ debugMessage(kDebugTouchController_HandleTouchStartEvent, "- but it is outside of the track area");
124
+ }
125
+ } else {
126
+ debugMessage(kDebugTouchController_HandleTouchStartEvent, "- this is a subsequent finger down event. update finger count...");
127
+ if (event.touches.length > this.swipeFingerCount) {
128
+ this.swipeFingerCount = event.touches.length;
129
+ debugMessage(kDebugTouchController_HandleTouchStartEvent, "- this.swipeFingerCount:" + this.swipeFingerCount);
130
+ }
131
+ }
132
+ },
133
+
134
+ handleTouchMoveEvent: function(event) {
135
+ if (this.preventDefault) {
136
+ event.preventDefault();
137
+ }
138
+
139
+ debugMessage(kDebugTouchController_HandleTouchCancelEvent, "");
140
+ },
141
+
142
+ handleTouchEndEvent: function(event) {
143
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "touch event has " + event.touches.length + " fingers...");
144
+
145
+ if (this.swipeInProgress) {
146
+ if (this.preventDefault) {
147
+ event.preventDefault();
148
+ }
149
+
150
+ if (event.touches.length === 0) {
151
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- " + this.swipeFingerCount + " finger swipe is complete.");
152
+
153
+ var endTouch = event.changedTouches[0];
154
+
155
+ var viewport = document.viewport.getDimensions();
156
+ var minSwipeDistance = viewport.width / 3.0;
157
+ var maxVerticalMagnitude = viewport.height / 3.0;
158
+ var maxHorizontalMagnitude = viewport.width / 3.0;
159
+
160
+ var deltaX = endTouch.clientX - this.swipeStartX;
161
+ var deltaY = endTouch.clientY - this.swipeStartY;
162
+
163
+ var magnitudeX = Math.abs(deltaX);
164
+ var magnitudeY = Math.abs(deltaY);
165
+
166
+ var touchEndTime = new Date();
167
+
168
+ var elapsedTime = touchEndTime - this.swipeStartTime;
169
+ var tapIsGood = false;
170
+ var swipeIsGood = false;
171
+
172
+ // First Check for a "tap"
173
+
174
+ var kMaxTapTime = 400;
175
+ var kMaxTapMagnitude = 20;
176
+
177
+ if (elapsedTime < kMaxTapTime) {
178
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- elapsed time was short enough to be a tap, check its magnitude...");
179
+
180
+ if ((magnitudeX < kMaxTapMagnitude) && (magnitudeY < kMaxTapMagnitude)) {
181
+ tapIsGood = true;
182
+ } else {
183
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- magnitude time too big to be a tap, check if it's a swipe...");
184
+ }
185
+ } else {
186
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- elapsed time too long to be a tap, check if it's a swipe...");
187
+ }
188
+
189
+ if (elapsedTime > 800) {
190
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- elapsed time too long to be a swipe, ignoring...");
191
+ } else {
192
+ if (magnitudeX > magnitudeY) {
193
+ if (magnitudeY > maxVerticalMagnitude) {
194
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- vertical magnitude too high, ignoring...");
195
+ } else {
196
+ swipeIsGood = true;
197
+ }
198
+ } else {
199
+ if (magnitudeX > maxHorizontalMagnitude) {
200
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- horizontal magnitude too high, ignoring...");
201
+ } else {
202
+ swipeIsGood = true;
203
+ }
204
+ }
205
+ }
206
+
207
+ if (tapIsGood) {
208
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- it's a " + this.swipeFingerCount + " finger tap");
209
+
210
+ if (this.tapEventCallback) {
211
+ var event = {};
212
+
213
+ event.memo = {};
214
+ event.memo.fingers = this.swipeFingerCount;
215
+ event.memo.pointX = endTouch.clientX;
216
+ event.memo.pointY = endTouch.clientY;
217
+
218
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- invoking callback with pointX: " + endTouch.clientX + " pointY: " + endTouch.clientY + "...");
219
+
220
+ this.tapEventCallback(event);
221
+
222
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- back from callback");
223
+ } else {
224
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- firing TapEvent...");
225
+
226
+ document.fire(kTapEvent, {
227
+ fingers: this.swipeFingerCount,
228
+ pointX: endTouch.clientX,
229
+ pointY: endTouch.clientY
230
+ });
231
+ }
232
+ } else if (swipeIsGood) {
233
+ var direction;
234
+
235
+ if (magnitudeX > magnitudeY) {
236
+ direction = (deltaX < 0 ? "left" : "right");
237
+ } else {
238
+ direction = (deltaY < 0 ? "up" : "down");
239
+ }
240
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- it's a " + this.swipeFingerCount + " finger swipe in the " + direction + " direction");
241
+ document.fire(kSwipeEvent, {
242
+ direction: direction,
243
+ fingers: this.swipeFingerCount
244
+ });
245
+ }
246
+
247
+ this.swipeInProgress = false;
248
+ this.swipeFingerCount = 0;
249
+ }
250
+ } else {
251
+ debugMessage(kDebugTouchController_HandleTouchEndEvent, "- false alarm. swipe has already ended.");
252
+ }
253
+ },
254
+
255
+ handleTouchCancelEvent: function(event) {
256
+ debugMessage(kDebugTouchController_HandleTouchCancelEvent, "");
257
+
258
+ this.swipeInProgress = false;
259
+ },
260
+
261
+ handleGestureStartEvent: function(event) {
262
+ debugMessage(kDebugTouchController_HandleGestureStartEvent, "");
263
+
264
+ if (this.preventDefault) {
265
+ event.preventDefault();
266
+ }
267
+ },
268
+
269
+ handleGestureEndEvent: function(event) {
270
+ debugMessage(kDebugTouchController_HandleGestureEndEvent, "");
271
+
272
+ if (this.preventDefault) {
273
+ event.preventDefault();
274
+ }
275
+ }
276
+ });
assets/player/Utilities.js CHANGED
@@ -1,3 +1,286 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e2ffd6d21f60babb4d01bf9866579e8356287624daf588dbe0c5eef192b28bab
3
- size 8162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Utilities.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Responsibility: Tungwei Cheng
6
+ * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var s = Class.create({
10
+ initialize: function(){}
11
+ });
12
+
13
+ function getMobileOSVersionInfo() {
14
+ var match = navigator.userAgent.match(/iPhone OS ([\d_]+)/) || navigator.userAgent.match(/iPad OS ([\d_]+)/) || navigator.userAgent.match(/CPU OS ([\d_]+)/);
15
+ var versionInfo = { major: 0, minor: 0, point: 0 };
16
+
17
+ if (match) {
18
+ var release = match[1].split('_');
19
+ versionInfo.major = parseInt(release[0]);
20
+
21
+ if (release.length > 1) {
22
+ versionInfo.minor = parseInt(release[1]);
23
+ }
24
+
25
+ if (release.length > 2) {
26
+ versionInfo.point = parseInt(release[2]);
27
+ }
28
+ }
29
+
30
+ return versionInfo;
31
+ }
32
+
33
+ function isMobileSafari() {
34
+ if (navigator.userAgent.indexOf('iPod') != -1) {
35
+ return true;
36
+ }
37
+ else if (navigator.userAgent.indexOf('iPhone') != -1) {
38
+ return true;
39
+ }
40
+ else if (navigator.userAgent.indexOf('iPad') != -1) {
41
+ return true;
42
+ }
43
+ else {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ function isiPad() {
49
+ return (navigator.userAgent.indexOf('iPad') != -1);
50
+ }
51
+
52
+ function getUrlParameter(paramterName) {
53
+ paramterName = paramterName.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
54
+
55
+ var regExpPattern = "[\\?&]" + paramterName + "=([^&#]*)";
56
+ var regExp = new RegExp(regExpPattern);
57
+ var results = regExp.exec(window.location.href);
58
+
59
+ if (results == null) {
60
+ return "";
61
+ } else {
62
+ return results[1];
63
+ }
64
+ }
65
+
66
+ function setElementProperty(node, propertyName, propertyValue) {
67
+ if (browserPrefix == "ms") {
68
+ node.style[propertyName] = propertyValue;
69
+ } else {
70
+ node.style.setProperty(propertyName, propertyValue, null);
71
+ }
72
+ }
73
+
74
+ function setElementOpaque(element) {
75
+ element.style.opacity = 1;
76
+ }
77
+
78
+ function setElementTransparent(element) {
79
+ element.style.opacity = 0;
80
+ }
81
+
82
+ function setElementPosition(element, top, left, width, height) {
83
+ if (element == null) {
84
+ window.console.log("null element passed to setElementPosition " + top + ", " + left + ", " + width + ", " + height);
85
+ return;
86
+ }
87
+ element.style.top = top + "px";
88
+ element.style.left = left + "px";
89
+ element.style.width = width + "px";
90
+ element.style.height = height + "px";
91
+ }
92
+
93
+ function setElementRect(element, rect) {
94
+ if (element == null) {
95
+ return;
96
+ }
97
+ element.style.top = rect.y;
98
+ element.style.left = rect.x;
99
+ element.style.width = rect.width;
100
+ element.style.height = rect.height;
101
+ }
102
+
103
+ function centerElementInDiv (element, elementWidth, elementHeight, divWidth, divHeight) {
104
+ if (element == null) {
105
+ return;
106
+ }
107
+
108
+ var top = (divHeight - elementHeight) / 2;
109
+ var left = (divWidth - elementWidth) / 2;
110
+
111
+ setElementPosition( element, top, left, elementWidth, elementHeight );
112
+ }
113
+
114
+ function showElement(element) {
115
+ if (element == null) {
116
+ return;
117
+ }
118
+ element.style.visibility = "visible";
119
+ }
120
+
121
+ function hideElement(element) {
122
+ if (element == null) {
123
+ return;
124
+ }
125
+ element.style.visibility = "hidden";
126
+ }
127
+
128
+ function runInNextEventLoop(codeBlock) {
129
+ setTimeout(codeBlock, 100);
130
+ }
131
+
132
+ function ensureScaleFactorNotZero(scaleFactor) {
133
+ // Mobile Safari doesn't like scale values of 0, force them to be 0.01
134
+ if (scaleFactor == 0) {
135
+ return 0.000001;
136
+ } else {
137
+ return scaleFactor;
138
+ }
139
+ }
140
+
141
+ function scaleSizeWithinSize(sourceWidth, sourceHeight, destinationWidth, destinationHeight) {
142
+ var scaledSize = {};
143
+ var sourceAspectRatio = sourceWidth / sourceHeight;
144
+ var destinationAspectRatio = destinationWidth / destinationHeight;
145
+
146
+ if (sourceAspectRatio > destinationAspectRatio) {
147
+ scaledSize.width = destinationWidth;
148
+ scaledSize.height = sourceHeight * ( destinationWidth / sourceWidth );
149
+ } else if (sourceAspectRatio < destinationAspectRatio) {
150
+ scaledSize.width = sourceWidth * ( destinationHeight / sourceHeight );
151
+ scaledSize.height = destinationHeight
152
+ } else {
153
+ scaledSize.width = destinationWidth;
154
+ scaledSize.height = destinationHeight
155
+ }
156
+
157
+ return scaledSize;
158
+ }
159
+
160
+ function parseTransformMatrix(transformMatrix) {
161
+ var parsedMatrix = [1,0,0,1,0,0];
162
+
163
+ if (transformMatrix.indexOf( "matrix(" ) == 0) {
164
+ var arrayString = transformMatrix.substring(7, transformMatrix.length - 1);
165
+
166
+ parsedMatrix = arrayString.split(",");
167
+ }
168
+
169
+ return parsedMatrix;
170
+ }
171
+
172
+ function escapeTextureId(textureId) {
173
+ var escapedTextureId = textureId.replace( /\./g, "-" );
174
+
175
+ return escapedTextureId;
176
+ }
177
+
178
+ function unEscapeTextureId(textureId) {
179
+ var escapedTextureId = textureId.replace( /\-/g, "." );
180
+
181
+ return escapedTextureId;
182
+ }
183
+
184
+ var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
185
+ var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
186
+ function LZ(x) {return(x<0||x>9?"":"0")+x;}
187
+
188
+ Object.extend(Date.prototype, {
189
+ // ------------------------------------------------------------------
190
+ // formatDate (date_object, format)
191
+ // Returns a date in the output format specified.
192
+ // The format string uses the same abbreviations as in getDateFromFormat()
193
+ //
194
+ // ------------------------------------------------------------------
195
+ format: function(format) {
196
+ format=format+"";
197
+ var date = this ;
198
+ var result="";
199
+ var i_format=0;
200
+ var c="";
201
+ var token="";
202
+ var y=date.getFullYear()+"";
203
+ var M=date.getMonth()+1;
204
+ var d=date.getDate();
205
+ var E=date.getDay();
206
+ var H=date.getHours();
207
+ var m=date.getMinutes();
208
+ var s=date.getSeconds();
209
+ var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
210
+ // Convert real date parts into formatted versions
211
+ var value=new Object();
212
+ if (y.length < 4) {
213
+ y=""+(y-0+1900);
214
+ }
215
+ value["y"]=""+y;
216
+ value["yyyy"]=y;
217
+ value["yy"]=y.substring(2,4);
218
+ value["M"]=M;
219
+ value["MM"]=LZ(M);
220
+ value["MMM"]=MONTH_NAMES[M-1];
221
+ value["NNN"]=MONTH_NAMES[M+11];
222
+ value["d"]=d;
223
+ value["dd"]=LZ(d);
224
+ value["E"]=DAY_NAMES[E+7];
225
+ value["EE"]=DAY_NAMES[E];
226
+ value["H"]=H;
227
+ value["HH"]=LZ(H);
228
+ if (H==0) {
229
+ value["h"]=12;
230
+ } else if (H>12) {
231
+ value["h"]=H-12;
232
+ } else {
233
+ value["h"]=H;
234
+ }
235
+ value["hh"]=LZ(value["h"]);
236
+ if (H>11) {
237
+ value["K"]=H-12;
238
+ } else {
239
+ value["K"]=H;
240
+ }
241
+ value["k"]=H+1;
242
+ value["KK"]=LZ(value["K"]);
243
+ value["kk"]=LZ(value["k"]);
244
+ if (H > 11) {
245
+ value["a"]="PM";
246
+ } else {
247
+ value["a"]="AM";
248
+ }
249
+ value["m"]=m;
250
+ value["mm"]=LZ(m);
251
+ value["s"]=s;
252
+ value["ss"]=LZ(s);
253
+ while (i_format < format.length) {
254
+ c=format.charAt(i_format);
255
+ token="";
256
+ while ((format.charAt(i_format)==c) && (i_format < format.length)) {
257
+ token += format.charAt(i_format++);
258
+ }
259
+
260
+ if (value[token] != null) {
261
+ result=result + value[token];
262
+ } else {
263
+ result=result + token;
264
+ }
265
+ }
266
+ return result;
267
+ }
268
+ });
269
+
270
+ function getHecklerElementsByTagName(xml, tagName) {
271
+ return getElementsByTagNameNS(xml, tagName, 'urn:iwork:property', 'X:');
272
+ }
273
+
274
+ function getElementsByTagNameNS(xml, tagName, ns, prefix) {
275
+ var nodes = null;
276
+ if (xml.getElementsByTagNameNS) {
277
+ nodes = xml.getElementsByTagNameNS(ns, tagName);
278
+ } else {
279
+ // IE7 Does not support getElementsByTagNameNS
280
+ // So we have to do this silly IE7 workaround and prefix the Heckler
281
+ // namespace to everything
282
+ nodes = xml.getElementsByTagName(prefix + tagName);
283
+ }
284
+
285
+ return nodes;
286
+ }
assets/player/gl/KNWebGLObjects.js CHANGED
The diff for this file is too large to render. See raw diff
 
assets/player/gl/KNWebGLParticleObjects.js CHANGED
The diff for this file is too large to render. See raw diff
 
assets/player/gl/KNWebGLShader.js CHANGED
@@ -1,3 +1,1326 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:868ffc1c835e6df17f57be4ffaac1ee23baa791aacc3cff9eb74fcb2a1857cef
3
- size 47318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * KNWebGLShader.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2016-2018 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var KNWebGLShader = {};
10
+
11
+ KNWebGLShader.defaultTexture = {
12
+ attribNames: ["Position", "TexCoord"],
13
+ uniformNames: ["MVPMatrix", "Texture"],
14
+ vertex: "\
15
+ #ifdef GL_ES\n\
16
+ precision highp float;\n\
17
+ #endif\n\
18
+ uniform mat4 MVPMatrix;\n\
19
+ attribute vec4 Position;\n\
20
+ attribute vec2 TexCoord;\n\
21
+ varying vec2 v_TexCoord;\n\
22
+ void main()\n\
23
+ {\n\
24
+ v_TexCoord = TexCoord;\n\
25
+ gl_Position = (MVPMatrix * Position);\n\
26
+ }\
27
+ ",
28
+ fragment: "\
29
+ #ifdef GL_ES\n\
30
+ precision mediump float;\n\
31
+ #endif\n\
32
+ uniform sampler2D Texture;\n\
33
+ varying vec2 v_TexCoord;\n\
34
+ void main()\n\
35
+ {\n\
36
+ gl_FragColor = texture2D(Texture, v_TexCoord);\n\
37
+ }\
38
+ "
39
+ };
40
+
41
+ KNWebGLShader.defaultTextureAndOpacity = {
42
+ attribNames: ["Position", "TexCoord"],
43
+ uniformNames: ["MVPMatrix", "Texture", "Opacity"],
44
+ vertex: "\
45
+ #ifdef GL_ES\n\
46
+ precision highp float;\n\
47
+ #endif\n\
48
+ uniform mat4 MVPMatrix;\n\
49
+ attribute vec4 Position;\n\
50
+ attribute vec2 TexCoord;\n\
51
+ varying vec2 v_TexCoord;\n\
52
+ void main()\n\
53
+ {\n\
54
+ v_TexCoord = TexCoord;\n\
55
+ gl_Position = (MVPMatrix * Position);\n\
56
+ }\
57
+ ",
58
+ fragment: "\
59
+ #ifdef GL_ES\n\
60
+ precision mediump float;\n\
61
+ #endif\n\
62
+ uniform sampler2D Texture;\n\
63
+ uniform float Opacity;\n\
64
+ varying vec2 v_TexCoord;\n\
65
+ void main()\n\
66
+ {\n\
67
+ vec4 texColor = texture2D(Texture, v_TexCoord);\n\
68
+ gl_FragColor = vec4(Opacity) * texColor;\n\
69
+ }\
70
+ "
71
+ };
72
+
73
+ KNWebGLShader.contents = {
74
+ attribNames: ["Position", "TexCoord"],
75
+ uniformNames: ["MVPMatrix", "Texture", "Texture2", "mixFactor"],
76
+ vertex: "\
77
+ #ifdef GL_ES\n\
78
+ precision highp float;\n\
79
+ #endif\n\
80
+ uniform mat4 MVPMatrix;\n\
81
+ attribute vec4 Position;\n\
82
+ attribute vec2 TexCoord;\n\
83
+ varying vec2 v_TexCoord;\n\
84
+ void main()\n\
85
+ {\n\
86
+ v_TexCoord = TexCoord;\n\
87
+ gl_Position = (MVPMatrix * Position);\n\
88
+ }\
89
+ ",
90
+ fragment: "\
91
+ #ifdef GL_ES\n\
92
+ precision mediump float;\n\
93
+ #endif\n\
94
+ uniform sampler2D Texture;\n\
95
+ uniform sampler2D Texture2;\n\
96
+ uniform float mixFactor;\n\
97
+ varying vec2 v_TexCoord;\n\
98
+ void main()\n\
99
+ {\n\
100
+ vec4 outgoingColor = texture2D(Texture2, v_TexCoord);\n\
101
+ vec4 incomingColor = texture2D(Texture, v_TexCoord);\n\
102
+ vec4 result = mix(outgoingColor, incomingColor, mixFactor);\n\
103
+ gl_FragColor = result;\n\
104
+ }\
105
+ "
106
+ };
107
+
108
+ KNWebGLShader.iris = {
109
+ attribNames: ["Position", "TexCoord"],
110
+ uniformNames: ["PercentForAlpha", "Scale", "Mix", "Texture", "MVPMatrix", "Opacity"],
111
+ vertex: "\
112
+ #ifdef GL_ES\n\
113
+ precision highp float;\n\
114
+ #endif\n\
115
+ uniform mat4 MVPMatrix;\n\
116
+ attribute vec4 Position;\n\
117
+ attribute vec2 TexCoord;\n\
118
+ varying vec2 v_TexCoord;\n\
119
+ void main()\n\
120
+ {\n\
121
+ v_TexCoord = TexCoord;\n\
122
+ gl_Position = MVPMatrix * Position;\n\
123
+ }\
124
+ ",
125
+ fragment: "\
126
+ #ifdef GL_ES\n\
127
+ precision mediump float;\n\
128
+ #endif\n\
129
+ uniform sampler2D Texture;\n\
130
+ uniform float Opacity;\n\
131
+ uniform float PercentForAlpha;\n\
132
+ uniform float Scale;\n\
133
+ uniform float Mix;\n\
134
+ varying vec2 v_TexCoord;\n\
135
+ void main()\n\
136
+ {\n\
137
+ vec4 incomingTexColor = texture2D(Texture, v_TexCoord);\n\
138
+ vec4 clear = vec4(0.0, 0.0, 0.0, 0.0);\n\
139
+ float tolerance = PercentForAlpha/5.0;\n\
140
+ vec2 powers = vec2((v_TexCoord.x - 0.5) * Scale,v_TexCoord.y - 0.5);\n\
141
+ powers *= powers;\n\
142
+ float radiusSqrd = PercentForAlpha * PercentForAlpha;\n\
143
+ float dist = (powers.x+powers.y)/((0.5*Scale)*(0.5*Scale)+0.25);\n\
144
+ float gradient = smoothstep(radiusSqrd, radiusSqrd+tolerance, dist);\n\
145
+ gl_FragColor = vec4(Opacity) * mix(clear, incomingTexColor, abs(Mix - gradient));\n\
146
+ }\
147
+ "
148
+ };
149
+
150
+ KNWebGLShader.twist = {
151
+ attribNames: ["Position", "TexCoord", "Normal"],
152
+ uniformNames: ["TextureMatrix", "SpecularColor", "FlipNormals", "MVPMatrix", "Texture"],
153
+ vertex: "\
154
+ #ifdef GL_ES\n\
155
+ precision highp float;\n\
156
+ #endif\n\
157
+ uniform mat4 MVPMatrix;\n\
158
+ uniform mat3 TextureMatrix;\n\
159
+ uniform float SpecularColor;\n\
160
+ uniform mediump float FlipNormals;\n\
161
+ attribute vec3 Position;\n\
162
+ attribute vec3 Normal;\n\
163
+ attribute vec2 TexCoord;\n\
164
+ varying vec2 v_TexCoord;\n\
165
+ varying vec3 v_DiffuseColor;\n\
166
+ varying vec3 v_SpecularColor;\n\
167
+ const vec3 c_AmbientColor = vec3(0.2);\n\
168
+ const vec3 c_DiffuseColor = vec3(1);\n\
169
+ const float c_LightExponent = 32.0;\n\
170
+ const vec3 c_LightDirection = vec3(0.1580, +0.5925, 0.7900);\n\
171
+ const vec3 c_LightHalfPlane = vec3(0.0835, +0.3131, 0.9460);\n\
172
+ void main()\n\
173
+ {\n\
174
+ vec3 thisNormal = Normal * FlipNormals;\n\
175
+ // Lighting\n\
176
+ float ndotl = max(0.0, dot(thisNormal, c_LightDirection));\n\
177
+ float ndoth = max(0.0, dot(thisNormal, c_LightHalfPlane));\n\
178
+ v_DiffuseColor = (c_AmbientColor + ndotl * c_DiffuseColor);\n\
179
+ v_SpecularColor = (ndoth <= 0.0) ? vec3(0) : (pow(ndoth, c_LightExponent) * vec3(SpecularColor));\n\
180
+ gl_Position = MVPMatrix * vec4(Position, 1.0);\n\
181
+ v_TexCoord = (TextureMatrix * vec3(TexCoord,1.0)).xy;\n\
182
+ }\
183
+ ",
184
+ fragment: "\
185
+ #ifdef GL_ES\n\
186
+ precision mediump float;\n\
187
+ #endif\n\
188
+ uniform sampler2D Texture;\n\
189
+ varying vec2 v_TexCoord;\n\
190
+ varying vec3 v_DiffuseColor;\n\
191
+ varying vec3 v_SpecularColor;\n\
192
+ void main()\n\
193
+ {\n\
194
+ vec4 texColor = texture2D(Texture, v_TexCoord);\n\
195
+ // Lighting\n\
196
+ texColor.xyz = texColor.xyz * v_DiffuseColor + v_SpecularColor;\n\
197
+ gl_FragColor = texColor;\n\
198
+ }\
199
+ "
200
+ };
201
+
202
+ KNWebGLShader.colorPlanes = {
203
+ attribNames: ["Position", "TexCoord"],
204
+ uniformNames: ["MVPMatrix", "FlipTexCoords", "Texture", "ColorMask"],
205
+ vertex: "\
206
+ #ifdef GL_ES\n\
207
+ precision highp float;\n\
208
+ #endif\n\
209
+ uniform mat4 MVPMatrix;\n\
210
+ uniform vec2 FlipTexCoords;\n\
211
+ attribute vec2 Position;\n\
212
+ attribute vec2 TexCoord;\n\
213
+ varying vec2 v_TexCoord;\n\
214
+ void main()\n\
215
+ {\n\
216
+ v_TexCoord = vec2(FlipTexCoords.x == 0.0 ? TexCoord.x : 1.0-TexCoord.x, FlipTexCoords.y == 0.0 ? TexCoord.y : 1.0-TexCoord.y);\n\
217
+ gl_Position = MVPMatrix * vec4(Position, 0,1);\n\
218
+ }\
219
+ ",
220
+ fragment: "\
221
+ #ifdef GL_ES\n\
222
+ precision mediump float;\n\
223
+ #endif\n\
224
+ uniform sampler2D Texture;\n\
225
+ uniform vec4 ColorMask;\n\
226
+ varying vec2 v_TexCoord;\n\
227
+ void main()\n\
228
+ {\n\
229
+ vec4 texColor = texture2D(Texture, v_TexCoord);\n\
230
+ texColor *= ColorMask;\n\
231
+ gl_FragColor = texColor;\n\
232
+ }\
233
+ "
234
+ };
235
+
236
+ KNWebGLShader.flop = {
237
+ attribNames: ["Position", "TexCoord", "Normal"],
238
+ uniformNames: ["TextureMatrix", "FlipNormals", "MVPMatrix", "Texture"],
239
+ vertex: "\
240
+ \n\
241
+ #ifdef GL_ES\n\
242
+ precision highp float;\n\
243
+ #endif\n\
244
+ \n\
245
+ uniform mat4 MVPMatrix;\n\
246
+ uniform mat3 TextureMatrix;\n\
247
+ uniform float FlipNormals;\n\
248
+ \n\
249
+ attribute vec3 Position;\n\
250
+ attribute vec3 Normal;\n\
251
+ attribute vec2 TexCoord;\n\
252
+ \n\
253
+ varying vec2 v_TexCoord;\n\
254
+ varying vec3 v_DiffuseColor;\n\
255
+ \n\
256
+ const vec3 c_AmbientColor = vec3(0.1);\n\
257
+ const vec3 c_DiffuseColor = vec3(1);\n\
258
+ const float c_LightExponent = 32.0;\n\
259
+ \n\
260
+ const vec3 c_LightDirection = vec3(0.000, +0.000, 0.900);\n\
261
+ \n\
262
+ void main()\n\
263
+ {\n\
264
+ vec3 thisNormal = Normal * FlipNormals;\n\
265
+ \n\
266
+ // Lighting\n\
267
+ vec3 lightDirection = vec3(c_LightDirection.x,c_LightDirection.y,c_LightDirection.z);\n\
268
+ \n\
269
+ float ndotl = max(0.0, dot(thisNormal, lightDirection));\n\
270
+ \n\
271
+ v_DiffuseColor = (c_AmbientColor + ndotl * c_DiffuseColor);\n\
272
+ \n\
273
+ gl_Position = MVPMatrix * vec4(Position, 1);\n\
274
+ v_TexCoord = (TextureMatrix * vec3(TexCoord,1)).xy;\n\
275
+ }\
276
+ ",
277
+ fragment: "\
278
+ \n\
279
+ #ifdef GL_ES\n\
280
+ precision mediump float;\n\
281
+ #endif\n\
282
+ \n\
283
+ uniform sampler2D Texture;\n\
284
+ \n\
285
+ varying vec2 v_TexCoord;\n\
286
+ varying vec3 v_DiffuseColor;\n\
287
+ \n\
288
+ void main()\n\
289
+ {\n\
290
+ vec4 texColor = texture2D(Texture, v_TexCoord);\n\
291
+ \n\
292
+ // Lighting\n\
293
+ texColor.xyz = texColor.xyz * v_DiffuseColor;\n\
294
+ gl_FragColor = texColor;\n\
295
+ }\
296
+ "
297
+ };
298
+
299
+ KNWebGLShader.anvilsmoke = {
300
+ attribNames: ["Rotation", "Speed", "Scale", "LifeSpan", "ParticleTexCoord", "Center", "Position"],
301
+ uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix"],
302
+ vertex: "\
303
+ \n\
304
+ uniform mat4 MVPMatrix;\n\
305
+ uniform float Percent;\n\
306
+ uniform float Opacity;\n\
307
+ \n\
308
+ attribute vec2 Position;\n\
309
+ attribute vec2 Center;\n\
310
+ attribute vec2 ParticleTexCoord;\n\
311
+ attribute vec3 Rotation;\n\
312
+ attribute vec3 Speed;\n\
313
+ attribute float Scale;\n\
314
+ attribute vec2 LifeSpan;\n\
315
+ \n\
316
+ varying vec4 v_Color;\n\
317
+ varying vec2 v_TexCoord;\n\
318
+ \n\
319
+ const float Pi = 3.1415926;\n\
320
+ const float Pi_2 = 1.5707963;\n\
321
+ const float TwoPi = 6.2831852;\n\
322
+ \n\
323
+ const float sineConstB = 1.2732396; /* = 4./Pi; */\n\
324
+ const float sineConstC = -0.40528476; /* = -4./(Pi*Pi); */\n\
325
+ \n\
326
+ vec3 fastSine(vec3 angle)\n\
327
+ {\n\
328
+ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\
329
+ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\
330
+ }\n\
331
+ \n\
332
+ mat3 fastRotationMatrix(vec3 theRotation)\n\
333
+ {\n\
334
+ vec3 sinXYZ = fastSine(theRotation);\n\
335
+ vec3 cosXYZ = fastSine(Pi_2 - theRotation);\n\
336
+ mat3 rotMatrix = mat3( cosXYZ.y*cosXYZ.z, sinXYZ.x*sinXYZ.y*cosXYZ.z+cosXYZ.x*sinXYZ.z, -cosXYZ.x*sinXYZ.y*cosXYZ.z+sinXYZ.x*sinXYZ.z,\n\
337
+ -cosXYZ.y*sinXYZ.z, -sinXYZ.x*sinXYZ.y*sinXYZ.z+cosXYZ.x*cosXYZ.z, cosXYZ.x*sinXYZ.y*sinXYZ.z+sinXYZ.x*cosXYZ.z,\n\
338
+ sinXYZ.y, -sinXYZ.x*cosXYZ.y, cosXYZ.x*cosXYZ.y);\n\
339
+ return rotMatrix;\n\
340
+ }\n\
341
+ \n\
342
+ void main()\n\
343
+ {\n\
344
+ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\
345
+ realPercent = clamp(realPercent, 0.0, 1.0);\n\
346
+ realPercent = sqrt(realPercent);\n\
347
+ \n\
348
+ /* SCALE */\n\
349
+ vec4 originalPosition = vec4(Position,0,1);\n\
350
+ vec4 center = vec4(Center, 0,1);\n\
351
+ vec3 scaleDirectionVec = vec3(originalPosition.xy-center.xy,0) * Scale * mix(0.1, 1.0, realPercent);\n\
352
+ \n\
353
+ /* ROTATE */\n\
354
+ mat3 rotMatrix = fastRotationMatrix(Rotation * realPercent);\n\
355
+ vec3 rotatedVec = rotMatrix * scaleDirectionVec;\n\
356
+ vec4 position = center + vec4(rotatedVec,0);\n\
357
+ \n\
358
+ float speedAdjust = realPercent;\n\
359
+ vec3 thisSpeed = Speed;\n\
360
+ thisSpeed.x *= sqrt(realPercent);\n\
361
+ thisSpeed.y *= realPercent*realPercent;\n\
362
+ position += vec4(thisSpeed, 0);\n\
363
+ \n\
364
+ float thisOpacity = Opacity;\n\
365
+ thisOpacity *= (1.0 - realPercent); /* fade out gradually */\n\
366
+ thisOpacity *= min(1.0, realPercent*20.0); /* fade in quickly */\n\
367
+ \n\
368
+ /* output */\n\
369
+ gl_Position = MVPMatrix * position;\n\
370
+ //v_Color = vec4(1.0, 1.0, 1.0, thisOpacity); //we applied a fix here, might not work everywhere\n\
371
+ v_Color = vec4(thisOpacity);\n\
372
+ v_TexCoord = ParticleTexCoord;\n\
373
+ }\n\
374
+ ",
375
+ fragment: "\
376
+ \n\
377
+ #ifdef GL_ES\n\
378
+ precision mediump float;\n\
379
+ #endif\n\
380
+ uniform sampler2D ParticleTexture;\n\
381
+ \n\
382
+ varying vec4 v_Color;\n\
383
+ varying vec2 v_TexCoord;\n\
384
+ \n\
385
+ void main()\n\
386
+ {\n\
387
+ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\
388
+ \n\
389
+ texColor *= v_Color;\n\
390
+ \n\
391
+ gl_FragColor = texColor;\n\
392
+ }\n\
393
+ "
394
+ };
395
+
396
+ KNWebGLShader.anvilspeck = {
397
+ attribNames: ["Speed", "Scale", "LifeSpan", "ParticleTexCoord", "Center", "Position"],
398
+ uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix"],
399
+ vertex: "\
400
+ \n\
401
+ uniform mat4 MVPMatrix;\n\
402
+ uniform float Percent;\n\
403
+ uniform float Opacity;\n\
404
+ \n\
405
+ attribute vec2 Position;\n\
406
+ attribute vec2 Center;\n\
407
+ attribute vec2 ParticleTexCoord;\n\
408
+ attribute vec3 Speed;\n\
409
+ attribute float Scale;\n\
410
+ attribute vec2 LifeSpan;\n\
411
+ \n\
412
+ varying vec4 v_Color;\n\
413
+ varying vec2 v_TexCoord;\n\
414
+ \n\
415
+ const float Pi = 3.1415926;\n\
416
+ const float Pi_2 = 1.5707963;\n\
417
+ const float TwoPi = 6.2831852;\n\
418
+ \n\
419
+ const float sineConstB = 1.2732396; /* = 4./Pi; */\n\
420
+ const float sineConstC = -0.40528476; /* = -4./(Pi*Pi); */\n\
421
+ \n\
422
+ vec3 fastSine(vec3 angle)\n\
423
+ {\n\
424
+ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\
425
+ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\
426
+ }\n\
427
+ \n\
428
+ void main()\n\
429
+ {\n\
430
+ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\
431
+ realPercent = clamp(realPercent, 0.0, 1.0);\n\
432
+ \n\
433
+ /* SCALE */\n\
434
+ vec4 originalPosition = vec4(Position,0,1);\n\
435
+ vec4 center = vec4(Center, 0,1);\n\
436
+ vec3 thisScale = Scale * vec3(1, Speed.z, 1) * mix(0.1, 1.0, realPercent);\n\
437
+ vec3 scaleDirectionVec = vec3(originalPosition.xy-center.xy,0) * thisScale;\n\
438
+ \n\
439
+ vec4 position = center + vec4(scaleDirectionVec,0);\n\
440
+ \n\
441
+ float speedAdjust = realPercent;\n\
442
+ vec3 thisPos = vec3(Speed.x * realPercent,\n\
443
+ Speed.y * fastSine(Pi*0.85*vec3(realPercent,0,0)).x, /* arc with gravity */\n\
444
+ 0);\n\
445
+ position += vec4(thisPos, 0);\n\
446
+ \n\
447
+ float thisOpacity = Opacity;\n\
448
+ thisOpacity *= (1.0 - realPercent); /* fade out gradually */\n\
449
+ thisOpacity *= min(1.0, realPercent*20.0); /* fade in quickly */\n\
450
+ \n\
451
+ /* output */\n\
452
+ gl_Position = MVPMatrix * position;\n\
453
+ v_Color = vec4(thisOpacity);\n\
454
+ v_TexCoord = ParticleTexCoord;\n\
455
+ }\
456
+ ",
457
+ fragment: "\
458
+ \n\
459
+ #ifdef GL_ES\n\
460
+ precision mediump float;\n\
461
+ #endif\n\
462
+ uniform sampler2D ParticleTexture;\n\
463
+ \n\
464
+ varying vec4 v_Color;\n\
465
+ varying vec2 v_TexCoord;\n\
466
+ \n\
467
+ void main()\n\
468
+ {\n\
469
+ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\
470
+ \n\
471
+ texColor *= v_Color;\n\
472
+ \n\
473
+ gl_FragColor = texColor;\n\
474
+ }\
475
+ "
476
+ };
477
+
478
+ KNWebGLShader.flame = {
479
+ attribNames: ["Rotation", "Speed", "LifeSpan", "ParticleTexCoord", "Center", "Position"],
480
+ uniformNames: ["Percent", "Duration", "Opacity", "RotationMax", "SpeedMax", "ParticleTexture", "MVPMatrix"],
481
+ vertex: "\
482
+ \n\
483
+ precision highp float;\n\
484
+ \n\
485
+ uniform mat4 MVPMatrix;\n\
486
+ uniform float Percent;\n\
487
+ uniform float Duration;\n\
488
+ \n\
489
+ attribute vec3 Rotation;\n\
490
+ attribute vec3 Speed;\n\
491
+ uniform float Opacity;\n\
492
+ attribute vec2 LifeSpan;\n\
493
+ attribute vec2 ParticleTexCoord;\n\
494
+ attribute vec2 Position;\n\
495
+ attribute vec2 Center;\n\
496
+ \n\
497
+ uniform mediump float RotationMax;\n\
498
+ uniform mediump float SpeedMax;\n\
499
+ \n\
500
+ varying vec4 v_Color;\n\
501
+ varying vec2 v_TexCoord;\n\
502
+ \n\
503
+ const float Pi = 3.1415926;\n\
504
+ const float Pi_2 = 1.5707963;\n\
505
+ const float TwoPi = 6.2831852;\n\
506
+ \n\
507
+ const float sineConstB = 1.2732396; /* = 4./Pi; */\n\
508
+ const float sineConstC = -0.40528476; /* = -4./(Pi*Pi); */\n\
509
+ \n\
510
+ float fastSine(float angle)\n\
511
+ {\n\
512
+ float theAngle = mod(angle + Pi, TwoPi) - Pi;\n\
513
+ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\
514
+ }\n\
515
+ \n\
516
+ const vec4 kStartColor = vec4( 1.0, 1.0, 1.0, 0.0 ); /* white */\n\
517
+ const vec4 kMidColor = vec4( 0.97, 1.0, 0.32, 0.0 ); /* yellow */\n\
518
+ const vec4 kEndColor = vec4( 0.9, 0.0, 0.0, 0.0 ); /* red */\n\
519
+ const float kColorMidPoint = 0.1;\n\
520
+ \n\
521
+ vec4 flameColor(float aPercent)\n\
522
+ {\n\
523
+ float thePercent = aPercent;\n\
524
+ /* CONSTANTS */\n\
525
+ float beginCutoff = 0.4/Duration; /* start slow (not bright white) */\n\
526
+ float smokeCutoff = 1.0 - (0.95/Duration); /* end with black, basically */\n\
527
+ float alphaCutoff = 1.0 - 0.5/Duration; /* fade out towards the end */\n\
528
+ \n\
529
+ float alpha = (thePercent < alphaCutoff) ? 1.0 : (1.0-(thePercent-alphaCutoff)/(1.0-alphaCutoff));\n\
530
+ vec4 theColor = vec4(0,0,0, alpha * 0.75);\n\
531
+ \n\
532
+ if (Percent < beginCutoff) {\n\
533
+ float colorCutoff = beginCutoff*3.0;\n\
534
+ thePercent += mix(colorCutoff, 0.0, Percent/beginCutoff);\n\
535
+ }\n\
536
+ \n\
537
+ if (thePercent < kColorMidPoint) {\n\
538
+ float newPercent = thePercent/kColorMidPoint;\n\
539
+ theColor += mix(kStartColor, kMidColor, newPercent);\n\
540
+ } else {\n\
541
+ float newPercent = (thePercent-kColorMidPoint)/(1.0-kColorMidPoint);\n\
542
+ theColor += mix(kMidColor, kEndColor, newPercent);\n\
543
+ }\n\
544
+ \n\
545
+ if (Percent > smokeCutoff) {\n\
546
+ /* smoke */\n\
547
+ float smokeAmount = (Percent - smokeCutoff)/(1.0 - smokeCutoff);\n\
548
+ smokeAmount = sqrt(smokeAmount);\n\
549
+ smokeAmount *= (0.25+thePercent*thePercent);\n\
550
+ theColor = vec4(theColor.rgb * max(0.0, 1.0-smokeAmount), theColor.a);\n\
551
+ }\n\
552
+ \n\
553
+ return theColor;\n\
554
+ }\n\
555
+ \n\
556
+ void main()\n\
557
+ {\n\
558
+ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\
559
+ bool shouldDiscard = realPercent < 0.0 || realPercent > 1.0;\n\
560
+ realPercent = clamp(realPercent, 0.0, 1.0);\n\
561
+ \n\
562
+ vec4 scaleDirectionVec = vec4(Position-Center,0,0);\n\
563
+ \n\
564
+ /* ROTATE */\n\
565
+ float halfPercent = realPercent/2.0;\n\
566
+ vec3 thisRotation = Rotation * RotationMax;\n\
567
+ float theRotation = thisRotation.x + thisRotation.z * (halfPercent * (halfPercent + 1.0));\n\
568
+ float sinRot = fastSine(theRotation);\n\
569
+ float cosRot = fastSine(Pi_2 - theRotation);\n\
570
+ mat3 rotMatrix = mat3(cosRot,-sinRot,0, sinRot,cosRot,0, 0,0,1);\n\
571
+ vec3 rotatedVec = rotMatrix * scaleDirectionVec.xyz;\n\
572
+ \n\
573
+ /* SCALE */\n\
574
+ float scaleAdjust = (0.1 + 1.0-(1.0-realPercent)*(1.0-realPercent));\n\
575
+ vec4 position = vec4(Center,0,1) + vec4(rotatedVec * scaleAdjust * (shouldDiscard ? 0.001 : 1.0), 0);\n\
576
+ \n\
577
+ /* POSITION */\n\
578
+ vec3 thisSpeed = Speed * SpeedMax;\n\
579
+ vec4 upVector = vec4(0.0, realPercent*realPercent * -thisSpeed.y, 0.0, 0.0);\n\
580
+ position += upVector;\n\
581
+ \n\
582
+ v_Color = flameColor(realPercent)*Opacity;\n\
583
+ gl_Position = MVPMatrix * position;\n\
584
+ v_TexCoord = ParticleTexCoord;\n\
585
+ }\
586
+ ",
587
+ fragment: "\
588
+ \n\
589
+ #ifdef GL_ES\n\
590
+ precision mediump float;\n\
591
+ #endif\n\
592
+ uniform sampler2D ParticleTexture;\n\
593
+ \n\
594
+ varying vec4 v_Color;\n\
595
+ varying vec2 v_TexCoord;\n\
596
+ \n\
597
+ void main()\n\
598
+ {\n\
599
+ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\
600
+ \n\
601
+ texColor *= v_Color;\n\
602
+ \n\
603
+ gl_FragColor = texColor;\n\
604
+ }\n\
605
+ "
606
+ };
607
+
608
+ KNWebGLShader.confetti = {
609
+ attribNames: ["Rotation", "Speed", "TexCoord", "Center", "Position"],
610
+ uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix"],
611
+ vertex: "\
612
+ \n\
613
+ precision highp float;\n\
614
+ uniform mat4 MVPMatrix;\n\
615
+ \n\
616
+ uniform float Percent;\n\
617
+ uniform mediump float Opacity;\n\
618
+ \n\
619
+ attribute vec2 Position;\n\
620
+ attribute vec2 Center;\n\
621
+ attribute vec2 TexCoord;\n\
622
+ attribute vec3 Rotation;\n\
623
+ attribute vec3 Speed;\n\
624
+ \n\
625
+ varying vec4 v_Color;\n\
626
+ varying vec2 v_TexCoord;\n\
627
+ \n\
628
+ const float Pi = 3.1415926;\n\
629
+ const float Pi_2 = 1.5707963;\n\
630
+ const float TwoPi = 6.2831852;\n\
631
+ \n\
632
+ const float sineConstB = 1.2732396;\n\
633
+ const float sineConstC = -0.40528476;\n\
634
+ \n\
635
+ vec3 fastSine(vec3 angle)\n\
636
+ {\n\
637
+ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\
638
+ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\
639
+ }\n\
640
+ \n\
641
+ mat3 fastRotationMatrix(vec3 theRotation)\n\
642
+ {\n\
643
+ vec3 sinXYZ = fastSine(theRotation);\n\
644
+ vec3 cosXYZ = fastSine(Pi_2 - theRotation);\n\
645
+ mat3 rotMatrix = mat3( cosXYZ.y*cosXYZ.z, sinXYZ.x*sinXYZ.y*cosXYZ.z+cosXYZ.x*sinXYZ.z, -cosXYZ.x*sinXYZ.y*cosXYZ.z+sinXYZ.x*sinXYZ.z,\n\
646
+ -cosXYZ.y*sinXYZ.z, -sinXYZ.x*sinXYZ.y*sinXYZ.z+cosXYZ.x*cosXYZ.z, cosXYZ.x*sinXYZ.y*sinXYZ.z+sinXYZ.x*cosXYZ.z,\n\
647
+ sinXYZ.y, -sinXYZ.x*cosXYZ.y, cosXYZ.x*cosXYZ.y);\n\
648
+ return rotMatrix;\n\
649
+ }\n\
650
+ \n\
651
+ void main()\n\
652
+ {\n\
653
+ /* SCALE */\n\
654
+ vec4 originalPosition = vec4(Position, 0, 1);\n\
655
+ vec3 scaleDirectionVec = vec3(Position-Center,0);\n\
656
+ \n\
657
+ /* ROTATE */\n\
658
+ mat3 rotMatrix = fastRotationMatrix(Rotation * Percent);\n\
659
+ vec3 rotatedVec = scaleDirectionVec * rotMatrix;\n\
660
+ vec4 position = vec4(Center,0,1) + vec4(rotatedVec,0);\n\
661
+ \n\
662
+ float colorAdjust = abs((rotMatrix * vec3(0,0,1)).z);\n\
663
+ \n\
664
+ float speedAdjust = Percent;\n\
665
+ position += vec4(Speed, 0) * speedAdjust;\n\
666
+ \n\
667
+ /* output */\n\
668
+ gl_Position = MVPMatrix * position;\n\
669
+ v_Color = vec4(vec3(colorAdjust), Opacity);\n\
670
+ v_TexCoord = TexCoord;\n\
671
+ }\
672
+ ",
673
+ fragment: "\
674
+ \n\
675
+ precision mediump float;\n\
676
+ \n\
677
+ uniform sampler2D ParticleTexture;\n\
678
+ //uniform float Opacity;\n\
679
+ \n\
680
+ varying vec4 v_Color;\n\
681
+ varying vec2 v_TexCoord;\n\
682
+ \n\
683
+ void main()\n\
684
+ {\n\
685
+ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\
686
+ \n\
687
+ texColor *= v_Color;\n\
688
+ //texColor.a = Opacity;\n\
689
+ \n\
690
+ gl_FragColor = texColor;\n\
691
+ }\
692
+ "
693
+ };
694
+
695
+ KNWebGLShader.diffuse = {
696
+ attribNames: ["Rotation", "Speed", "TexCoord", "Center", "Position", "LifeSpan"],
697
+ uniformNames: ["Percent", "Opacity", "ParticleTexture", "MVPMatrix", "RotationMax", "SpeedMax"],
698
+ vertex: "\
699
+ \n\
700
+ precision highp float;\n\
701
+ \n\
702
+ uniform mat4 MVPMatrix;\n\
703
+ \n\
704
+ uniform float Percent;\n\
705
+ uniform mediump float Opacity;\n\
706
+ \n\
707
+ attribute vec2 Position;\n\
708
+ attribute vec2 Center;\n\
709
+ attribute vec2 TexCoord;\n\
710
+ \n\
711
+ attribute mediump vec3 Rotation;\n\
712
+ uniform mediump float RotationMax;\n\
713
+ attribute mediump vec3 Speed;\n\
714
+ uniform mediump float SpeedMax;\n\
715
+ attribute mediump vec2 LifeSpan;\n\
716
+ \n\
717
+ varying vec4 v_Color;\n\
718
+ varying vec2 v_TexCoord;\n\
719
+ \n\
720
+ const float Pi = 3.1415926;\n\
721
+ const float Pi_2 = 1.5707963;\n\
722
+ const float TwoPi = 6.2831852;\n\
723
+ \n\
724
+ const float sineConstB = 1.2732396;\n\
725
+ const float sineConstC = -0.40528476;\n\
726
+ \n\
727
+ vec3 fastSine(vec3 angle)\n\
728
+ {\n\
729
+ vec3 theAngle = mod(angle + Pi, TwoPi) - Pi;\n\
730
+ return sineConstB * theAngle + sineConstC * theAngle * abs(theAngle);\n\
731
+ }\n\
732
+ \n\
733
+ mat3 fastRotationMatrix(vec3 theRotation)\n\
734
+ {\n\
735
+ vec3 sinXYZ = fastSine(theRotation);\n\
736
+ vec3 cosXYZ = fastSine(Pi_2 - theRotation);\n\
737
+ mat3 rotMatrix = mat3( cosXYZ.y*cosXYZ.z, sinXYZ.x*sinXYZ.y*cosXYZ.z+cosXYZ.x*sinXYZ.z, -cosXYZ.x*sinXYZ.y*cosXYZ.z+sinXYZ.x*sinXYZ.z,\n\
738
+ -cosXYZ.y*sinXYZ.z, -sinXYZ.x*sinXYZ.y*sinXYZ.z+cosXYZ.x*cosXYZ.z, cosXYZ.x*sinXYZ.y*sinXYZ.z+sinXYZ.x*cosXYZ.z,\n\
739
+ sinXYZ.y, -sinXYZ.x*cosXYZ.y, cosXYZ.x*cosXYZ.y);\n\
740
+ return rotMatrix;\n\
741
+ }\n\
742
+ \n\
743
+ void main()\n\
744
+ {\n\
745
+ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\
746
+ float doDiscard = (realPercent > 1.0) ? 0.0 : 1.0;\n\
747
+ realPercent = clamp(realPercent, 0.0,1.0);\n\
748
+ float revPercent = 1.0-realPercent;\n\
749
+ \n\
750
+ //SCALE\n\
751
+ vec4 originalPosition = vec4(Position, 0, 1);\n\
752
+ vec3 scaleDirectionVec = vec3(Position-Center,0);\n\
753
+ \n\
754
+ //ROTATE\n\
755
+ vec3 thisRotation = Rotation * RotationMax;\n\
756
+ mat3 rotMatrix = fastRotationMatrix(thisRotation * realPercent);\n\
757
+ vec3 rotatedVec = scaleDirectionVec * rotMatrix;\n\
758
+ vec4 position = vec4(Center,0,1) + vec4(rotatedVec,0) * doDiscard;\n\
759
+ \n\
760
+ vec3 thisSpeed = Speed * SpeedMax;\n\
761
+ float l2r = -thisSpeed.x/abs(thisSpeed.x);\n\
762
+ float reverseVector = l2r*(thisSpeed.x+abs(thisSpeed.y)) * realPercent/8.0;\n\
763
+ \n\
764
+ float speedMultiplier = 1.-pow(revPercent, 2.0);\n\
765
+ vec3 dist = thisSpeed * speedMultiplier;\n\
766
+ dist.x += reverseVector;\n\
767
+ position.xyz += dist;\n\
768
+ \n\
769
+ float colorAdjust = abs((rotMatrix * vec3(0,0,1)).z);\n\
770
+ \n\
771
+ //output\n\
772
+ gl_Position = MVPMatrix * position;\n\
773
+ v_Color = vec4(vec3(colorAdjust), 1) * (revPercent*Opacity);\n\
774
+ v_TexCoord = TexCoord;\n\
775
+ }\
776
+ ",
777
+ fragment: "\
778
+ \n\
779
+ precision mediump float;\n\
780
+ \n\
781
+ uniform sampler2D Texture;\n\
782
+ uniform float Opacity;\n\
783
+ \n\
784
+ varying vec4 v_Color;\n\
785
+ varying vec2 v_TexCoord;\n\
786
+ \n\
787
+ void main()\n\
788
+ {\n\
789
+ vec4 texColor = texture2D(Texture, v_TexCoord);\n\
790
+ \n\
791
+ texColor *= v_Color;\n\
792
+ \n\
793
+ gl_FragColor = texColor;\n\
794
+ }\
795
+ "
796
+ };
797
+
798
+ KNWebGLShader.fireworks = {
799
+ attribNames: ["Color", "Speed", "LifeSpan", "Scale", "ParticleTexCoord", "Center", "Position"],
800
+ uniformNames: ["Percent", "PreviousPercent", "Gravity", "StartScale", "ShouldSparkle", "SparklePeriod", "ParticleBurstTiming", "PreviousParticleBurstTiming", "SpeedMax", "ParticleTexture", "Opacity", "MVPMatrix"],
801
+ vertex: "\
802
+ \n\
803
+ precision highp float;\n\
804
+ \n\
805
+ uniform mat4 MVPMatrix;\n\
806
+ \n\
807
+ uniform float Percent;\n\
808
+ uniform float PreviousPercent;\n\
809
+ uniform float Gravity;\n\
810
+ uniform float StartScale;\n\
811
+ uniform float ShouldSparkle;\n\
812
+ uniform float SparklePeriod;\n\
813
+ uniform float ParticleBurstTiming;\n\
814
+ uniform float PreviousParticleBurstTiming;\n\
815
+ uniform float SpeedMax;\n\
816
+ \n\
817
+ attribute vec2 Position;\n\
818
+ attribute vec2 Center;\n\
819
+ attribute vec2 ParticleTexCoord;\n\
820
+ \n\
821
+ attribute vec4 Color;\n\
822
+ attribute vec3 Speed;\n\
823
+ attribute vec2 LifeSpan;\n\
824
+ attribute float Scale;\n\
825
+ \n\
826
+ varying vec4 v_Color;\n\
827
+ varying vec2 v_TexCoord;\n\
828
+ \n\
829
+ void main()\n\
830
+ {\n\
831
+ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\
832
+ realPercent = clamp(realPercent, 0.0, 1.0);\n\
833
+ \n\
834
+ float prevRealPercent = (PreviousPercent-LifeSpan.x)/LifeSpan.y;\n\
835
+ prevRealPercent = clamp(prevRealPercent, 0.0,1.0);\n\
836
+ \n\
837
+ vec4 center = vec4(Center,0,1);\n\
838
+ vec4 scaleDirectionVec = vec4(Position-Center,0,0);\n\
839
+ \n\
840
+ // TRANSLATE\n\
841
+ vec3 translation = Speed * (SpeedMax * ParticleBurstTiming); // (1.0-pow(1.0-realPercent, ExplosionPower));\n\
842
+ translation.y -= Gravity * (Percent - LifeSpan.x); // Gravity is in terms of global percent, not particle system percent\n\
843
+ \n\
844
+ vec3 prevTranslation = Speed * (SpeedMax * PreviousParticleBurstTiming);\n\
845
+ prevTranslation.y -= Gravity * (PreviousPercent - LifeSpan.x); // Gravity is in terms of global percent, not particle system percent\n\
846
+ \n\
847
+ vec3 blurOffset = translation - prevTranslation; // Blur in direction of velocity\n\
848
+ \n\
849
+ // project centerVec onto translationOffset to get direction\n\
850
+ blurOffset *= (dot(blurOffset, scaleDirectionVec.xyz) >= 0.0 ? 1.0 : -1.0);\n\
851
+ \n\
852
+ center.xyz += translation;\n\
853
+ \n\
854
+ // SCALE\n\
855
+ float scalePercent = (1.0-(1.0-realPercent)*(1.0-realPercent));\n\
856
+ float scaleAdjust = mix(StartScale, Scale, scalePercent);\n\
857
+ // scale down to zero, unless we're sparkling\n\
858
+ scaleAdjust *= (ShouldSparkle>0.5 ? 0.25 : 1.0-scalePercent);\n\
859
+ vec4 position = center + scaleDirectionVec * scaleAdjust;\n\
860
+ position += vec4(blurOffset,0);\n\
861
+ \n\
862
+ // SPARKLE\n\
863
+ float sparkleOpacity = fract(realPercent*realPercent * SparklePeriod);\n\
864
+ sparkleOpacity = smoothstep(0.0, 1.0, sparkleOpacity);\n\
865
+ \n\
866
+ // COLOR\n\
867
+ vec4 color = mix(vec4(1), Color, scalePercent * (ShouldSparkle<0.5 ? 1.0 : 0.5)); // white to color\n\
868
+ color *= (ShouldSparkle<0.5 ? 1.0 : sparkleOpacity); // apply sparkle opacity\n\
869
+ color *= (realPercent>=1.0 ? 0.0 : 1.0);\n\
870
+ v_Color = color;\n\
871
+ \n\
872
+ gl_Position = MVPMatrix * position;\n\
873
+ v_TexCoord = ParticleTexCoord;\n\
874
+ }\
875
+ ",
876
+ fragment: "\
877
+ \n\
878
+ precision mediump float;\n\
879
+ \n\
880
+ uniform sampler2D ParticleTexture;\n\
881
+ uniform float Opacity;\n\
882
+ \n\
883
+ varying vec4 v_Color;\n\
884
+ varying vec2 v_TexCoord;\n\
885
+ //varying float particleTexPercent;\n\
886
+ \n\
887
+ void main()\n\
888
+ {\n\
889
+ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\
890
+ \n\
891
+ texColor *= v_Color * Opacity;\n\
892
+ //texColor.a *= Opacity;\n\
893
+ \n\
894
+ //texColor = vec4(v_TexCoord, 0, 1);\n\
895
+ \n\
896
+ gl_FragColor = texColor;\n\
897
+ }\
898
+ "
899
+ };
900
+
901
+ KNWebGLShader.fireworkstrails = {
902
+ attribNames: [ "Position", "TexCoord"],
903
+ uniformNames: ["Texture", "Opacity", "NoiseAmount", "NoiseSeed", "NoiseMax", "MVPMatrix"],
904
+ vertex: "\
905
+ \n\
906
+ precision highp float;\n\
907
+ \n\
908
+ uniform mat4 MVPMatrix;\n\
909
+ \n\
910
+ attribute vec2 Position;\n\
911
+ attribute vec2 TexCoord;\n\
912
+ \n\
913
+ varying vec2 v_TexCoord;\n\
914
+ \n\
915
+ void main()\n\
916
+ {\n\
917
+ gl_Position = MVPMatrix * vec4(Position, 0,1);\n\
918
+ v_TexCoord = TexCoord;\n\
919
+ }\
920
+ ",
921
+ fragment: "\
922
+ precision mediump float;\n\
923
+ \n\
924
+ uniform sampler2D Texture;\n\
925
+ uniform float Opacity;\n\
926
+ uniform float NoiseAmount;\n\
927
+ uniform vec2 NoiseSeed;\n\
928
+ uniform float NoiseMax;\n\
929
+ \n\
930
+ //varying vec4 v_Color;\n\
931
+ varying vec2 v_TexCoord;\n\
932
+ //varying float particleTexPercent;\n\
933
+ \n\
934
+ float rand(vec2 co){\n\
935
+ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n\
936
+ }\n\
937
+ \n\
938
+ float inverseSquare(float a) {\n\
939
+ return 1.0-(1.0-a)*(1.0-a);\n\
940
+ }\n\
941
+ \n\
942
+ void main()\n\
943
+ {\n\
944
+ vec4 texColor = texture2D(Texture, v_TexCoord);\n\
945
+ \n\
946
+ //texColor = bloom(texColor);\n\
947
+ \n\
948
+ // Dither transparency to add noise\n\
949
+ float randomNoise = NoiseMax*rand(v_TexCoord*NoiseSeed);\n\
950
+ float randomAmount = NoiseAmount * 1.5*max(0.0, texColor.a-0.3333);\n\
951
+ \n\
952
+ float thisOpacity = Opacity * mix(1.0, randomNoise, randomAmount);\n\
953
+ texColor *= thisOpacity;\n\
954
+ \n\
955
+ //texColor = vec4(v_TexCoord, 0, 1);\n\
956
+ \n\
957
+ gl_FragColor = texColor;\n\
958
+ }\
959
+ "
960
+ };
961
+
962
+ KNWebGLShader.horizontalGaussianBlur = {
963
+ attribNames: [ "Position"],
964
+ uniformNames: ["Texture", "TextureSize", "MVPMatrix"],
965
+ vertex: "\
966
+ \n\
967
+ precision highp float;\n\
968
+ \n\
969
+ uniform mat4 MVPMatrix;\n\
970
+ \n\
971
+ attribute vec2 Position;\n\
972
+ \n\
973
+ void main()\n\
974
+ {\n\
975
+ gl_Position = MVPMatrix * vec4(Position, 0, 1);\n\
976
+ }\
977
+ ",
978
+ fragment: "\
979
+ precision highp float;\n\
980
+ \n\
981
+ uniform sampler2D Texture;\n\
982
+ uniform vec2 TextureSize;\n\
983
+ \n\
984
+ const vec2 offset1 = vec2(1.3846153846, 0);\n\
985
+ const vec2 offset2 = vec2(3.2307692308, 0);\n\
986
+ const float weight0 = 0.2270270270;\n\
987
+ const float weight1 = 0.3162162162;\n\
988
+ const float weight2 = 0.0702702703;\n\
989
+ \n\
990
+ void main()\n\
991
+ {\n\
992
+ vec4 color = texture2D(Texture, gl_FragCoord.xy*TextureSize) * weight0;\n\
993
+ \n\
994
+ color += texture2D(Texture, (gl_FragCoord.xy + offset1)*TextureSize) * weight1;\n\
995
+ color += texture2D(Texture, (gl_FragCoord.xy - offset1)*TextureSize) * weight1;\n\
996
+ \n\
997
+ color += texture2D(Texture, (gl_FragCoord.xy + offset2)*TextureSize) * weight2;\n\
998
+ color += texture2D(Texture, (gl_FragCoord.xy - offset2)*TextureSize) * weight2;\n\
999
+ \n\
1000
+ gl_FragColor = color;\n\
1001
+ }\
1002
+ "
1003
+ };
1004
+
1005
+ KNWebGLShader.verticalGaussianBlur = {
1006
+ attribNames: [ "Position"],
1007
+ uniformNames: ["Texture", "TextureSize", "MVPMatrix"],
1008
+ vertex: "\
1009
+ \n\
1010
+ precision highp float;\n\
1011
+ \n\
1012
+ uniform mat4 MVPMatrix;\n\
1013
+ \n\
1014
+ attribute vec2 Position;\n\
1015
+ \n\
1016
+ void main()\n\
1017
+ {\n\
1018
+ gl_Position = MVPMatrix * vec4(Position, 0, 1);\n\
1019
+ }\
1020
+ ",
1021
+ fragment: "\
1022
+ precision highp float;\n\
1023
+ \n\
1024
+ uniform sampler2D Texture;\n\
1025
+ uniform vec2 TextureSize;\n\
1026
+ \n\
1027
+ const vec2 offset1 = vec2(0, 1.3846153846);\n\
1028
+ const vec2 offset2 = vec2(0, 3.2307692308);\n\
1029
+ const float weight0 = 0.2270270270;\n\
1030
+ const float weight1 = 0.3162162162;\n\
1031
+ const float weight2 = 0.0702702703;\n\
1032
+ \n\
1033
+ void main()\n\
1034
+ {\n\
1035
+ vec4 color = texture2D(Texture, gl_FragCoord.xy*TextureSize) * weight0;\n\
1036
+ \n\
1037
+ color += texture2D(Texture, (gl_FragCoord.xy + offset1)*TextureSize) * weight1;\n\
1038
+ color += texture2D(Texture, (gl_FragCoord.xy - offset1)*TextureSize) * weight1;\n\
1039
+ \n\
1040
+ color += texture2D(Texture, (gl_FragCoord.xy + offset2)*TextureSize) * weight2;\n\
1041
+ color += texture2D(Texture, (gl_FragCoord.xy - offset2)*TextureSize) * weight2;\n\
1042
+ \n\
1043
+ gl_FragColor = color;\n\
1044
+ }\
1045
+ "
1046
+ };
1047
+
1048
+ KNWebGLShader.bloom = {
1049
+ attribNames: [ "Position", "TexCoord"],
1050
+ uniformNames: ["Texture", "BlurTexture", "BloomAmount", "MVPMatrix"],
1051
+ vertex: "\
1052
+ \n\
1053
+ precision highp float;\n\
1054
+ \n\
1055
+ uniform mat4 MVPMatrix;\n\
1056
+ \n\
1057
+ attribute vec2 Position;\n\
1058
+ attribute vec2 TexCoord;\n\
1059
+ \n\
1060
+ varying vec2 v_TexCoord;\n\
1061
+ \n\
1062
+ void main()\n\
1063
+ {\n\
1064
+ v_TexCoord = TexCoord;\n\
1065
+ gl_Position = MVPMatrix * vec4(Position, 0, 1);\n\
1066
+ }\
1067
+ ",
1068
+ fragment: "\
1069
+ precision mediump float;\n\
1070
+ \n\
1071
+ uniform sampler2D Texture;\n\
1072
+ uniform sampler2D BlurTexture;\n\
1073
+ uniform float BloomAmount;\n\
1074
+ \n\
1075
+ varying vec2 v_TexCoord;\n\
1076
+ \n\
1077
+ void main()\n\
1078
+ {\n\
1079
+ vec4 color = texture2D(Texture, v_TexCoord);\n\
1080
+ vec4 blurColor = texture2D(BlurTexture, v_TexCoord);\n\
1081
+ \n\
1082
+ color += (blurColor + color) * BloomAmount;\n\
1083
+ gl_FragColor = color;\n\
1084
+ }\
1085
+ "
1086
+ };
1087
+
1088
+ KNWebGLShader.shimmerObject = {
1089
+ attribNames: [ "Position", "Center", "TexCoord", "Color", "Speed"],
1090
+ uniformNames: ["Percent", "Opacity", "RotationMatrix", "SpeedMax", "Texture", "MVPMatrix"],
1091
+ vertex: "\
1092
+ \n\
1093
+ precision highp float;\n\
1094
+ \n\
1095
+ uniform mat4 MVPMatrix;\n\
1096
+ uniform float Percent;\n\
1097
+ uniform float Opacity;\n\
1098
+ \n\
1099
+ uniform mat3 RotationMatrix;\n\
1100
+ \n\
1101
+ attribute vec2 Position;\n\
1102
+ attribute vec2 Center;\n\
1103
+ attribute vec2 TexCoord;\n\
1104
+ attribute vec4 Color;\n\
1105
+ \n\
1106
+ attribute vec3 Speed;\n\
1107
+ uniform float SpeedMax;\n\
1108
+ \n\
1109
+ varying vec4 v_Color;\n\
1110
+ varying vec2 v_TexCoord;\n\
1111
+ \n\
1112
+ void main()\n\
1113
+ {\n\
1114
+ float thisPercent = Percent;\n\
1115
+ float invPercent = 1.0-thisPercent;\n\
1116
+ float thisPercent2 = thisPercent*thisPercent;\n\
1117
+ \n\
1118
+ /* CENTER */\n\
1119
+ vec3 scaleDirectionVec = vec3((Position.x-Center.x),(Position.y-Center.y),0);\n\
1120
+ \n\
1121
+ /* ROTATE */\n\
1122
+ vec3 rotatedVec = RotationMatrix * scaleDirectionVec.xyz;\n\
1123
+ \n\
1124
+ /* SCALE */\n\
1125
+ float scale = invPercent;\n\
1126
+ vec4 position = vec4(Center.xy,0,1) + vec4(rotatedVec,0) * scale;\n\
1127
+ \n\
1128
+ vec3 thisSpeed = Speed * SpeedMax;\n\
1129
+ position.xyz += thisSpeed * thisPercent*(3.0 + mix(thisPercent2*thisPercent, 1.0-invPercent*invPercent, thisPercent2));\n\
1130
+ \n\
1131
+ vec4 outColor = Color;\n\
1132
+ outColor = vec4(Opacity);\n\
1133
+ \n\
1134
+ /* output */\n\
1135
+ gl_Position = MVPMatrix * position;\n\
1136
+ v_Color = outColor;\n\
1137
+ v_TexCoord = TexCoord;\n\
1138
+ }\n\
1139
+ ",
1140
+ fragment: "\
1141
+ precision mediump float;\n\
1142
+ \n\
1143
+ uniform sampler2D Texture;\n\
1144
+ \n\
1145
+ varying vec4 v_Color;\n\
1146
+ varying vec2 v_TexCoord;\n\
1147
+ \n\
1148
+ void main()\n\
1149
+ {\n\
1150
+ vec4 color = texture2D(Texture, v_TexCoord);\n\
1151
+ \n\
1152
+ color *= v_Color;\n\
1153
+ \n\
1154
+ gl_FragColor = color;\n\
1155
+ }\
1156
+ "
1157
+ };
1158
+
1159
+ KNWebGLShader.shimmerParticle = {
1160
+ attribNames: [ "Position", "Center", "ParticleTexCoord", "Color", "LifeSpan", "Speed", "Scale"],
1161
+ uniformNames: ["Percent", "Opacity", "ParticleScalePercent", "RotationMatrix", "SpeedMax", "ParticleTexture", "MVPMatrix"],
1162
+ vertex: "\
1163
+ \n\
1164
+ precision highp float;\n\
1165
+ \n\
1166
+ uniform mat4 MVPMatrix;\n\
1167
+ uniform float Percent;\n\
1168
+ uniform float Opacity;\n\
1169
+ \n\
1170
+ uniform float ParticleScalePercent;\n\
1171
+ uniform mat3 RotationMatrix;\n\
1172
+ \n\
1173
+ attribute vec2 Position;\n\
1174
+ attribute vec2 Center;\n\
1175
+ attribute vec2 ParticleTexCoord;\n\
1176
+ attribute vec4 Color;\n\
1177
+ attribute vec2 LifeSpan;\n\
1178
+ \n\
1179
+ attribute vec3 Speed;\n\
1180
+ uniform float SpeedMax;\n\
1181
+ attribute float Scale;\n\
1182
+ \n\
1183
+ varying vec4 v_Color;\n\
1184
+ varying vec2 v_TexCoord;\n\
1185
+ \n\
1186
+ float scaleUpDown(float x) {\n\
1187
+ float result = 1.0 - abs(2.0*(x-0.5));\n\
1188
+ result *= result;\n\
1189
+ return result;\n\
1190
+ }\n\
1191
+ \n\
1192
+ void main()\n\
1193
+ {\n\
1194
+ /* LIFESPAN */\n\
1195
+ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\
1196
+ float doDiscard = (realPercent > 1.0 || realPercent < 0.0) ? 0.0 : 1.0;\n\
1197
+ realPercent = clamp(realPercent, 0.0,1.0);\n\
1198
+ float realPercent2 = realPercent*realPercent;\n\
1199
+ float invPercent2 = 1.0-realPercent;\n\
1200
+ invPercent2 *= invPercent2;\n\
1201
+ \n\
1202
+ vec3 scaleDirectionVec = vec3((Position.x-Center.x),(Position.y-Center.y),0);\n\
1203
+ \n\
1204
+ /* ROTATE */\n\
1205
+ vec3 rotatedVec = RotationMatrix * scaleDirectionVec.xyz;\n\
1206
+ \n\
1207
+ /* SCALE */\n\
1208
+ float scalePercent = (LifeSpan.x <= 0.001 ? ParticleScalePercent : scaleUpDown(realPercent));\n\
1209
+ float scale = scalePercent * Scale * doDiscard;\n\
1210
+ vec4 position = vec4(Center,0,1) + vec4(rotatedVec,0) * scale;\n\
1211
+ \n\
1212
+ vec3 thisSpeed = Speed * SpeedMax;\n\
1213
+ position.xyz += thisSpeed * realPercent*(3.0 + mix(realPercent*realPercent2, 1.0-invPercent2, realPercent2));\n\
1214
+ \n\
1215
+ // Only adjust opacity on particles that last the duration of the animation\n\
1216
+ float thisOpacity = (LifeSpan.x <= 0.001 ? Opacity : 1.0);\n\
1217
+ vec4 color = vec4(Color.rgb, 1) * thisOpacity;\n\
1218
+ \n\
1219
+ v_Color = color;\n\
1220
+ v_TexCoord = ParticleTexCoord;\n\
1221
+ gl_Position = MVPMatrix * position;\n\
1222
+ }\n\
1223
+ ",
1224
+ fragment: "\
1225
+ precision mediump float;\n\
1226
+ \n\
1227
+ uniform sampler2D ParticleTexture;\n\
1228
+ \n\
1229
+ varying vec4 v_Color;\n\
1230
+ varying vec2 v_TexCoord;\n\
1231
+ \n\
1232
+ void main()\n\
1233
+ {\n\
1234
+ vec4 color = texture2D(ParticleTexture, v_TexCoord);\n\
1235
+ \n\
1236
+ color *= v_Color;\n\
1237
+ \n\
1238
+ gl_FragColor = color;\n\
1239
+ }\
1240
+ "
1241
+ };
1242
+
1243
+ KNWebGLShader.sparkle = {
1244
+ attribNames: ["Scale", "LifeSpan", "Speed", "ParticleTexCoord", "Center", "Position"],
1245
+ uniformNames: ["Percent", "Opacity", "Color", "SpeedMax", "ParticleTexture", "MVPMatrix"],
1246
+ vertex: "\
1247
+ \n\
1248
+ precision highp float;\n\
1249
+ \n\
1250
+ uniform mat4 MVPMatrix;\n\
1251
+ uniform float Percent;\n\
1252
+ \n\
1253
+ attribute vec2 Position;\n\
1254
+ attribute vec2 Center;\n\
1255
+ uniform float Opacity;\n\
1256
+ attribute vec2 ParticleTexCoord;\n\
1257
+ uniform vec4 Color;\n\
1258
+ \n\
1259
+ attribute mediump vec3 Speed;\n\
1260
+ uniform mediump float SpeedMax;\n\
1261
+ attribute mediump float Scale;\n\
1262
+ attribute mediump vec2 LifeSpan;\n\
1263
+ \n\
1264
+ varying vec4 v_Color;\n\
1265
+ varying vec2 v_TexCoord;\n\
1266
+ \n\
1267
+ float ReverseSquareOfFloat(float f) {\n\
1268
+ return 1.0 - (1.0-f)*(1.0-f);\n\
1269
+ }\n\
1270
+ \n\
1271
+ void main()\n\
1272
+ {\n\
1273
+ float doDiscard = 0.0;\n\
1274
+ float realPercent = (Percent-LifeSpan.x)/LifeSpan.y;\n\
1275
+ if (realPercent < 0.0 || realPercent > 1.0) {\n\
1276
+ doDiscard = 1.0;\n\
1277
+ realPercent = 1.0;\n\
1278
+ }\n\
1279
+ \n\
1280
+ vec4 position;\n\
1281
+ vec4 scaleDirectionVec = vec4((Position.x-Center.x),(Position.y-Center.y),0,0);\n\
1282
+ \n\
1283
+ // SCALE\n\
1284
+ float scaleAdjust = realPercent;\n\
1285
+ if (scaleAdjust < 0.1) {\n\
1286
+ scaleAdjust /= 0.1;\n\
1287
+ scaleAdjust = sqrt(scaleAdjust);\n\
1288
+ } else {\n\
1289
+ scaleAdjust = 1.0-(scaleAdjust-0.1)/0.9;\n\
1290
+ scaleAdjust = scaleAdjust*scaleAdjust*scaleAdjust;\n\
1291
+ }\n\
1292
+ scaleAdjust *= (doDiscard==0.0 ? 1.0 : 0.0);\n\
1293
+ position = vec4(Center,0,1) + scaleDirectionVec * scaleAdjust * Scale;\n\
1294
+ \n\
1295
+ // POSITION\n\
1296
+ vec3 thisSpeed = Speed * SpeedMax;\n\
1297
+ position += vec4(thisSpeed, 0) * realPercent;\n\
1298
+ \n\
1299
+ float invPercent = 1.0 - realPercent;\n\
1300
+ vec3 rgbColor = mix(Color.rgb, vec3(1,1,1), invPercent*invPercent*invPercent);\n\
1301
+ \n\
1302
+ /* output */\n\
1303
+ gl_Position = MVPMatrix * position;\n\
1304
+ v_Color = vec4(rgbColor, (1.0-realPercent*realPercent)*Opacity);\n\
1305
+ v_TexCoord = ParticleTexCoord;\n\
1306
+ }\
1307
+ ",
1308
+ fragment: "\
1309
+ \n\
1310
+ precision mediump float;\n\
1311
+ \n\
1312
+ uniform sampler2D ParticleTexture;\n\
1313
+ \n\
1314
+ varying vec4 v_Color;\n\
1315
+ varying vec2 v_TexCoord;\n\
1316
+ \n\
1317
+ void main()\n\
1318
+ {\n\
1319
+ vec4 texColor = texture2D(ParticleTexture, v_TexCoord);\n\
1320
+ \n\
1321
+ texColor *= v_Color;\n\
1322
+ \n\
1323
+ gl_FragColor = texColor;\n\
1324
+ }\
1325
+ "
1326
+ };
assets/player/gl/KNWebGLUtil.js CHANGED
@@ -1,3 +1,1145 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:b563c00690b3d7ac19464b5cc6bc01bad1784a739c4e7bf885e95aaec9c0dc24
3
- size 31880
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * KNWebGLUtil.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2016-2018 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var KNWebGLUtil = {};
10
+
11
+ KNWebGLUtil.setupProgram = function(gl, programName) {
12
+ var shader = KNWebGLShader[programName];
13
+ var vertexShader = this.loadShader(gl, gl.VERTEX_SHADER, shader.vertex);
14
+ var fragmentShader = this.loadShader(gl, gl.FRAGMENT_SHADER, shader.fragment);
15
+ var shaderProgram = this.createShaderProgram(gl, vertexShader, fragmentShader);
16
+
17
+ // creates uniforms and attribs but does not enable attribs.
18
+ var attribs = {};
19
+ var uniforms = {};
20
+
21
+ for (var i = 0, length = shader.uniformNames.length; i < length; i++) {
22
+ var uniformName = shader.uniformNames[i];
23
+ uniforms[uniformName] = gl.getUniformLocation(shaderProgram, uniformName);
24
+ }
25
+
26
+ for (var i = 0, length = shader.attribNames.length; i < length; i++) {
27
+ var attribName = shader.attribNames[i];
28
+ attribs[attribName] = gl.getAttribLocation(shaderProgram, attribName);
29
+ }
30
+
31
+ // create a program object
32
+ var program = {
33
+ shaderProgram: shaderProgram,
34
+ uniforms: uniforms,
35
+ attribs: attribs
36
+ };
37
+
38
+ // use this program for rendering
39
+ gl.useProgram(shaderProgram);
40
+
41
+ return program;
42
+ };
43
+
44
+ KNWebGLUtil.loadShader = function(gl, type, shaderSource) {
45
+ var shader = gl.createShader(type);
46
+ gl.shaderSource(shader, shaderSource);
47
+ gl.compileShader(shader);
48
+
49
+ // Check the compile status
50
+ var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
51
+ if (!compiled) {
52
+ // error during compilation
53
+ var error = gl.getShaderInfoLog(shader);
54
+ console.log("*** Error compiling shader '" + shader + "':" + error);
55
+ gl.deleteShader(shader);
56
+ return null;
57
+ }
58
+
59
+ return shader;
60
+ };
61
+
62
+ KNWebGLUtil.createShaderProgram = function(gl, vertexShader, fragmentShader) {
63
+ // create shader program
64
+ var shaderProgram = gl.createProgram();
65
+
66
+ // Attach the shaders to the program
67
+ gl.attachShader(shaderProgram, vertexShader);
68
+ gl.attachShader(shaderProgram, fragmentShader);
69
+
70
+ // Link the program
71
+ gl.linkProgram(shaderProgram);
72
+
73
+ var linked = gl.getProgramParameter(shaderProgram, gl.LINK_STATUS);
74
+ if (!linked) {
75
+ var error = gl.getProgramInfoLog(shaderProgram);
76
+ console.log("Error in program linking:" + error);
77
+ gl.deleteProgram(shaderProgram);
78
+ }
79
+
80
+ return shaderProgram;
81
+ };
82
+
83
+ KNWebGLUtil.createTexture = function(gl, image) {
84
+ var texture = gl.createTexture();
85
+
86
+ // bind WebGLTexture object to gl.TEXTURE_2D target
87
+ gl.bindTexture(gl.TEXTURE_2D, texture);
88
+
89
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
90
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
91
+
92
+ // upload texture data to GPU
93
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
94
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
95
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
96
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
97
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
98
+ gl.bindTexture(gl.TEXTURE_2D, null);
99
+
100
+ return texture;
101
+ };
102
+
103
+ KNWebGLUtil.bindTextureWithImage = function(gl, image) {
104
+ var texture = gl.createTexture();
105
+
106
+ // bind WebGLTexture object to gl.TEXTURE_2D target
107
+ gl.bindTexture(gl.TEXTURE_2D, texture);
108
+
109
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
110
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
111
+
112
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
113
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
114
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
115
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
116
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
117
+ gl.bindTexture(gl.TEXTURE_2D, null);
118
+
119
+ return texture;
120
+ };
121
+
122
+ KNWebGLUtil.bindDynamicBufferWithData = function(gl, attribLoc, buffer, data, size) {
123
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
124
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.DYNAMIC_DRAW);
125
+
126
+ // we need to enable attrib loc to work with data buffer
127
+ gl.enableVertexAttribArray(attribLoc);
128
+ gl.vertexAttribPointer(attribLoc, size, gl.FLOAT, false, 0, 0);
129
+ };
130
+
131
+ KNWebGLUtil.bindBufferWithData = function(gl, attribLoc, buffer, data, size, bufferUsage) {
132
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
133
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), bufferUsage);
134
+
135
+ // we need to enable attrib loc to work with data buffer
136
+ gl.enableVertexAttribArray(attribLoc);
137
+ gl.vertexAttribPointer(attribLoc, size, gl.FLOAT, false, 0, 0);
138
+ };
139
+
140
+ //attribute buffer insertion
141
+ KNWebGLUtil.setPoint2DAtIndexForAttribute = function(point, index, attribute) {
142
+ //attribute cannot become an object. we need to create an object where we can place this. BUMMER
143
+ attribute[index*2] = point.x;
144
+ attribute[index*2+1] = point.y;
145
+ attribute.size = 2;
146
+ };
147
+
148
+ KNWebGLUtil.setPoint3DAtIndexForAttribute = function(point, index, attribute) {
149
+ attribute[index*3] = point.x;
150
+ attribute[index*3+1] = point.y;
151
+ attribute[index*3+2] = point.z;
152
+ attribute.size = 3;
153
+ };
154
+
155
+ KNWebGLUtil.setPoint4DAtIndexForAttribute = function(point, index, attribute) {
156
+ attribute[index*4] = point.x;
157
+ attribute[index*4+1] = point.y;
158
+ attribute[index*4+2] = point.z;
159
+ attribute[index*4+3] = point.w;
160
+ attribute.size = 4;
161
+ };
162
+
163
+ KNWebGLUtil.setFloatAtIndexForAttribute = function(f, index, attribute) {
164
+ attribute[index] = f;
165
+ };
166
+
167
+ KNWebGLUtil.getPoint2DForArrayAtIndex = function(attrib, index) {
168
+ var point = {};
169
+ point.x = attrib[index*2];
170
+ point.y = attrib[index*2 + 1];
171
+ return point;
172
+ };
173
+
174
+ KNWebGLUtil.getPoint3DForArrayAtIndex = function(attrib, index) {
175
+ var point = {};
176
+ point.x = attrib[index*3];
177
+ point.y = attrib[index*3 + 1];
178
+ point.z = attrib[index*3 + 2];
179
+ return point;
180
+ };
181
+
182
+ KNWebGLUtil.getPoint4DForArrayAtIndex = function(attrib, index) {
183
+ var point = {};
184
+ point.x = attrib[index*4];
185
+ point.y = attrib[index*4 + 1];
186
+ point.z = attrib[index*4 + 2];
187
+ point.w = attrib[index*4 + 3];
188
+ return point;
189
+ };
190
+
191
+ KNWebGLUtil.bindAllAvailableAttributesToBuffers = function(gl, attribs, bufferdata, size, buffer, bufferUsage) {
192
+ for (var obj in attribs) {
193
+ var attribute = attribs[obj];
194
+ if (buffer[obj] == undefined) {
195
+ buffer[obj] = gl.createBuffer();
196
+ }
197
+
198
+ KNWebGLUtil.bindBufferWithData(gl, attribute, buffer[obj], bufferdata[obj], size[obj], bufferUsage);
199
+ }
200
+ };
201
+
202
+ // We need to enable attribs before binding.
203
+ // This also sets the program to the given program.
204
+ // This never needs to be called in single program animations
205
+ KNWebGLUtil.enableAttribs = function(gl, program) {
206
+ var attribs = program.attribs;
207
+ gl.useProgram(program.shaderProgram);
208
+ for (var obj in attribs) {
209
+ gl.enableVertexAttribArray(attribs[obj]);
210
+ }
211
+ };
212
+
213
+ /*
214
+ * WebGraphics is not a container for any data. It should only computer and return values.
215
+ *
216
+ * makePoint(x, y): returns a object with .x and .y properties attached
217
+ *
218
+ * randomBetween(a, b): returns a random number between a (lower bound) and b (upper bound)
219
+ *
220
+ * mix(x, y, a): returns a linear intern between x and y using a as a weight between them
221
+ *
222
+ * clamp(x, minVal, maxVal) : clamps x between a min and max value
223
+ */
224
+ var WebGraphics = {};
225
+
226
+ WebGraphics.makePoint = function(x, y) {
227
+ var obj = {};
228
+ obj.x = x;
229
+ obj.y = y;
230
+ return obj;
231
+ };
232
+
233
+ WebGraphics.makePoint3D = function(x, y, z) {
234
+ var obj = {};
235
+ obj.x = x;
236
+ obj.y = y;
237
+ obj.z = z;
238
+ return obj;
239
+ };
240
+
241
+ WebGraphics.makePoint4D = function(x, y, z, w) {
242
+ var obj = {};
243
+ obj.x = x;
244
+ obj.y = y;
245
+ obj.z = z;
246
+ obj.w = w;
247
+ return obj;
248
+ };
249
+
250
+ WebGraphics.makeRect = function(x,y, width, height) {
251
+ var obj = {};
252
+ obj.x = x;
253
+ obj.y = y;
254
+ obj.width = width;
255
+ obj.height = height;
256
+ return obj;
257
+ };
258
+
259
+ WebGraphics.makeSize = function(width, height) {
260
+ var obj = {};
261
+ obj.width = width;
262
+ obj.height = height;
263
+ return obj;
264
+ };
265
+
266
+ WebGraphics.setOrigin = function(obj, point) {
267
+ obj.x = point.x;
268
+ obj.y = point.y;
269
+ return obj;
270
+ };
271
+
272
+ WebGraphics.multiplyPoint3DByScalar = function(point, scalar) {
273
+ var obj = {};
274
+ obj.x = point.x * scalar;
275
+ obj.y = point.y * scalar;
276
+ obj.z = point.z * scalar;
277
+ return obj;
278
+ };
279
+
280
+ WebGraphics.multiplyPoint4DByScalar = function(point, scalar) {
281
+ var obj = {};
282
+ obj.x = point.x * scalar;
283
+ obj.y = point.y * scalar;
284
+ obj.z = point.z * scalar;
285
+ obj.w = point.w * scalar;
286
+ return obj;
287
+ };
288
+
289
+ WebGraphics.addPoint3DToPoint3D = function(a, b) {
290
+ var obj = {};
291
+ obj.x = a.x + b.x;
292
+ obj.y = a.y + b.y;
293
+ obj.z = a.z + b.z;
294
+ return obj;
295
+ };
296
+
297
+ WebGraphics.point3DNormalize = function(pt3d) {
298
+ var length = Math.sqrt(pt3d.x * pt3d.x + pt3d.y * pt3d.y + pt3d.z * pt3d.z);
299
+ var obj = {};
300
+ obj.z = pt3d.z / length;
301
+ obj.y = pt3d.y / length;
302
+ obj.x = pt3d.x / length;
303
+ return obj;
304
+ };
305
+
306
+ WebGraphics.randomBetween = function(min, max) {
307
+ var x = Math.random();
308
+ x *= (max - min);
309
+ x += min;
310
+ return x;
311
+ };
312
+
313
+ WebGraphics.doubleBetween = function(randMin, randMax) {
314
+ var result = 0;
315
+
316
+ var bottom, top;
317
+ if (randMin < randMax) {
318
+ bottom = randMin;
319
+ top = randMax;
320
+ } else {
321
+ bottom = randMax;
322
+ top = randMin;
323
+ }
324
+
325
+ // rnd: random in range [0.0 -> 1.0)
326
+ // RandBetween(bottom, top) = ((top - bottom) * rnd) + bottom
327
+
328
+ // To avoid overflows, distribute the multiplication:
329
+ // = top*rand - bottom*rand + bottom
330
+
331
+ var rnd = Math.random();
332
+ var topMult = top * rnd;
333
+ var bottomMult = bottom * rnd;
334
+
335
+ if ((bottom >= 0.0) == (top >= 0.0)) {
336
+ // Both are the same sign, do the subtraction first to avoid overflow.
337
+ result = topMult - bottomMult;
338
+ result = result + bottom;
339
+ } else {
340
+ // The signs differ, add bottom in first to avoid overflow.
341
+ result = topMult + bottom;
342
+ result = result - bottomMult;
343
+ }
344
+
345
+ return result;
346
+ }
347
+
348
+ WebGraphics.mix = function(x, y, a) {
349
+ return x * (1 - a) + (y * a);
350
+ };
351
+
352
+ WebGraphics.clamp = function(x, minVal, maxVal) {
353
+ return Math.min(Math.max(x, minVal), maxVal);
354
+ };
355
+
356
+ WebGraphics.sineMap = function(x) {
357
+ return (Math.sin(x * Math.PI - (Math.PI / 2)) + 1) * 0.5;
358
+ };
359
+
360
+ WebGraphics.createMatrix4 = function() {
361
+ //creates and identity matrix, column-major matrix library, it is not necessary to use this to get an ortho matrix
362
+ var obj = new Float32Array(16);
363
+ obj[0] = 1;
364
+ obj[1] = 0;
365
+ obj[2] = 0;
366
+ obj[3] = 0;
367
+ obj[4] = 0;
368
+ obj[5] = 1;
369
+ obj[6] = 0;
370
+ obj[7] = 0;
371
+ obj[8] = 0;
372
+ obj[9] = 0;
373
+ obj[10] = 1;
374
+ obj[11] = 0;
375
+ obj[12] = 0;
376
+ obj[13] = 0;
377
+ obj[14] = 0;
378
+ obj[15] = 1;
379
+ return obj;
380
+ };
381
+
382
+ WebGraphics.makeIdentityMatrix4 = function() {
383
+ return WebGraphics.createMatrix4();
384
+ };
385
+
386
+ WebGraphics.makeOrthoMatrix4 = function(left, right, bottom, top, near, far) {
387
+ var matrix = new Float32Array(16);
388
+ var rl = right - left;
389
+ var tb = top - bottom;
390
+ var fn = far - near;
391
+ matrix[0] = 2 / rl;
392
+ matrix[1] = 0;
393
+ matrix[2] = 0;
394
+ matrix[3] = 0;
395
+ matrix[4] = 0;
396
+ matrix[5] = 2 / tb;
397
+ matrix[6] = 0;
398
+ matrix[7] = 0;
399
+ matrix[8] = 0;
400
+ matrix[9] = 0;
401
+ matrix[10] = -2 /fn;
402
+ matrix[11] = 0;
403
+ matrix[12] = -(right + left) / rl;
404
+ matrix[13] = -(top - bottom) / tb;
405
+ matrix[14] = -(far + near) / fn;
406
+ matrix[15] = 1;
407
+ return matrix;
408
+ };
409
+
410
+ WebGraphics.makeFrustumMatrix4 = function(left, right, bottom, top, near, far) {
411
+ var rl = right - left;
412
+ var tb = top - bottom;
413
+ var fn = far - near;
414
+ var m = new Float32Array(16);
415
+ m[0] = (near * 2) / rl; //11
416
+ m[1] = 0; //21
417
+ m[2] = 0; //31
418
+ m[3] = 0; //41
419
+ m[4] = 0; //12
420
+ m[5] = (near * 2) / tb; //22
421
+ m[6] = 0; //32
422
+ m[7] = 0; //42
423
+ m[8] = (right + left) / rl;
424
+ m[9] = (top + bottom) / tb;
425
+ m[10] = -(far + near) / fn;
426
+ m[11] = -1;
427
+ m[12] = 0;
428
+ m[13] = 0;
429
+ m[14] = (-2 * far * near) / fn;
430
+ m[15] = 0;
431
+ return m;
432
+ };
433
+
434
+ WebGraphics.makePerspectiveMatrix4 = function(fovy, aspect, near, far) {
435
+ var top = near * Math.tan(fovy * Math.PI / 360.0);
436
+ var right = top * aspect;
437
+ return WebGraphics.makeFrustumMatrix4(-right, right, -top, top, near, far);
438
+ };
439
+
440
+ WebGraphics.multiplyMatrix4 = function(a, b) {
441
+ //a*b
442
+ var m = new Float32Array(16);
443
+ var a11 = a[0], a12 = a[4], a13 = a[8], a14 = a[12], a21 = a[1], a22 = a[5], a23 = a[9], a24 = a[13],
444
+ a31 = a[2], a32 = a[6], a33 = a[10], a34 = a[14], a41 = a[3], a42 = a[7], a43 = a[11], a44 = a[15];
445
+ var b11 = b[0], b12 = b[4], b13 = b[8], b14 = b[12], b21 = b[1], b22 = b[5], b23 = b[9], b24 = b[13],
446
+ b31 = b[2], b32 = b[6], b33 = b[10], b34 = b[14], b41 = b[3], b42 = b[7], b43 = b[11], b44 = b[15];
447
+ m[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
448
+ m[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
449
+ m[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
450
+ m[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
451
+ m[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
452
+ m[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
453
+ m[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
454
+ m[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
455
+ m[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
456
+ m[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
457
+ m[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
458
+ m[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
459
+ m[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
460
+ m[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
461
+ m[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
462
+ m[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
463
+ return m;
464
+ };
465
+ WebGraphics.scaleMatrix4 = function(m4, sx, sy, sz) {
466
+ var m = WebGraphics.createMatrix4();
467
+ m[0] = sx;
468
+ m[5] = sy;
469
+ m[10] = sz;
470
+ return WebGraphics.multiplyMatrix4(m4, m);
471
+ };
472
+
473
+ WebGraphics.translateMatrix4 = function(m4, tx, ty, tz) {
474
+ var m = WebGraphics.createMatrix4();
475
+ m[12] = tx;
476
+ m[13] = ty;
477
+ m[14] = tz;
478
+ return WebGraphics.multiplyMatrix4(m4, m);
479
+ };
480
+
481
+ WebGraphics.rotateMatrix4AboutXYZ = function(m4, theta, x, y, z) {
482
+ var point3d = WebGraphics.makePoint3D(x, y, z);
483
+ point3d = WebGraphics.point3DNormalize(point3d);
484
+ var ux = point3d.x;
485
+ var uy = point3d.y;
486
+ var uz = point3d.z;
487
+ var cos = Math.cos(theta);
488
+ var oneMinusCos = 1 - cos;
489
+ var sin = Math.sin(theta);
490
+ var m = WebGraphics.createMatrix4();
491
+ m[0] = cos + (ux * ux) * oneMinusCos;
492
+ m[1] = ux * uy * oneMinusCos + (uz * sin);
493
+ m[2] = uz * ux * oneMinusCos - uy * sin;
494
+ m[4] = ux * uy * oneMinusCos - uz * sin;
495
+ m[5] = cos + (uy * uy) * oneMinusCos;
496
+ m[6] = uz * uy * oneMinusCos + ux * sin;
497
+ m[8] = ux * uy * oneMinusCos + uy * sin;
498
+ m[9] = uy * uz * oneMinusCos - ux * sin;
499
+ m[10] = cos + (uz * uz) * oneMinusCos;
500
+ return WebGraphics.multiplyMatrix4(m4, m);
501
+ };
502
+
503
+ WebGraphics.colorWithHSBA = function(hue, saturation, brightness, alpha) {
504
+ var hueTimesSix, frac, p1, p2, p3, red, blue, green;
505
+ var obj = {"hue": hue, "saturation": saturation, "brightness": brightness, "alpha": alpha};
506
+ if (hue == 1.0) {
507
+ hue = 0.0;
508
+ }
509
+ hueTimesSix = hue * 6.0;
510
+ frac = hueTimesSix - Math.floor(hueTimesSix);
511
+ p1 = brightness * (1-saturation);
512
+ p2 = brightness * (1.0 - (saturation * frac));
513
+ p3 = brightness * (1.0 - (saturation * (1.0 - frac)));
514
+ switch (parseInt(hueTimesSix)) {
515
+ case 0:
516
+ red = brightness;
517
+ green = p3;
518
+ blue = p1;
519
+ break;
520
+ case 1:
521
+ red = p2;
522
+ green = brightness;
523
+ blue = p1;
524
+ break;
525
+ case 2:
526
+ red = p1;
527
+ green = brightness;
528
+ blue = p3;
529
+ break;
530
+ case 3:
531
+ red = p1;
532
+ green = p2;
533
+ blue = brightness;
534
+ break;
535
+ case 4:
536
+ red = p3;
537
+ green = p1;
538
+ blue = brightness;
539
+ break;
540
+ case 5:
541
+ red = brightness;
542
+ green = p1;
543
+ blue = p2;
544
+ break;
545
+ }
546
+ obj.red = red;
547
+ obj.blue = blue;
548
+ obj.green = green;
549
+ return obj;
550
+ };
551
+
552
+ WebGraphics.makeMat3WithAffineTransform = function(affineTransform) {
553
+ var obj = new Float32Array(9);
554
+ obj[0] = affineTransform[0];
555
+ obj[1] = affineTransform[1];
556
+ obj[2] = 0;
557
+ obj[3] = affineTransform[2];
558
+ obj[4] = affineTransform[3];
559
+ obj[5] = 0;
560
+ obj[6] = affineTransform[4];
561
+ obj[7] = affineTransform[5];
562
+ obj[8] = 1;
563
+ return obj;
564
+ };
565
+
566
+ /*
567
+ * High performance vector container for math
568
+ * Copyright (c) 2011 Apple, Inc
569
+ */
570
+ vector3 = function(vec) {
571
+ this.create(vec);
572
+ };
573
+
574
+ vector3.prototype = {
575
+ create: function(vec) {
576
+ var m = this.$matrix = {};
577
+ if (!vec) {
578
+ m.m11 = 0;
579
+ m.m12 = 0;
580
+ m.m13 = 0;
581
+ } else {
582
+ m.m11 = vec[0];
583
+ m.m12 = vec[1];
584
+ m.m13 = vec[2];
585
+ }
586
+ },
587
+
588
+ subtract: function(vec) {
589
+ var m = this.$matrix;
590
+ var mm = vec.$matrix;
591
+ m.m11 -= mm.m11;
592
+ m.m12 -= mm.m12;
593
+ m.m13 -= mm.m13;
594
+ },
595
+
596
+ add: function(vec) {
597
+ var m = this.$matrix;
598
+ var mm = vec.$matrix;
599
+ m.m11 += mm.m11;
600
+ m.m12 += mm.m12;
601
+ m.m13 += mm.m13;
602
+ },
603
+
604
+ normalize: function() {
605
+ var m = this.$matrix;
606
+ var length = Math.sqrt((m.m11 * m.m11) + (m.m12 * m.m12) + (m.m13 * m.m13));
607
+ if (length > 0) {
608
+ m.m11 /= length;
609
+ m.m12 /= length;
610
+ m.m13 /= length;
611
+ }
612
+ },
613
+
614
+ scale: function(scalar) {
615
+ var m = this.$matrix;
616
+ m.m11 *= scalar;
617
+ m.m12 *= scalar;
618
+ m.m13 *= scalar;
619
+ },
620
+
621
+ cross: function(vec) {
622
+ var m = this.$matrix;
623
+ var mm = vec.$matrix;
624
+ var a1 = mm.m11, a2 = mm.m12, a3 = mm.m13;
625
+ var m1 = m.m11, m2 = m.m12, m3 = m.m13;
626
+ m.m11 = m2 * a3 - m3 * a2;
627
+ m.m12 = m3 * a1 - m1 * a3;
628
+ m.m13 = m1 * a2 - m2 * a1;
629
+ },
630
+
631
+ getArray: function() {
632
+ var m = this.$matrix;
633
+
634
+ return [m.m11, m.m12, m.m13];
635
+ }
636
+ };
637
+
638
+ // Matrix3, 3x3 Matrix Class
639
+ // Matrix3 stores row-major order, simply transverse to get a webGL acceptable array
640
+ Matrix3 = function() {
641
+ this.identity();
642
+ };
643
+
644
+ Matrix3.prototype = {
645
+ identity: function() {
646
+ this.$matrix = {
647
+ m11: 1, m12: 0, m13: 0,
648
+ m21: 0, m22: 1, m23: 0,
649
+ m31: 0, m32: 0, m33: 1
650
+ };
651
+ },
652
+
653
+ affineScale: function(sx, sy) {
654
+ var m = this.$matrix;
655
+ m.m11 = sx;
656
+ m.m22 = sy;
657
+ },
658
+
659
+ affineTranslate: function(tx, ty) {
660
+ var m = this.$matrix;
661
+ m.m13 = tx;
662
+ m.m23 = ty;
663
+ },
664
+
665
+ transformTranslate: function(tx, ty) {
666
+ var matrix = new Matrix3();
667
+ matrix.affineTranslate(tx, ty);
668
+ this.multiply(matrix.getArray());
669
+ },
670
+
671
+ multiply: function(mat) {
672
+ var m = this.$matrix;
673
+ var m0 = m.m11, m1 = m.m12, m2 = m.m13, m3 = m.m21, m4 = m.m22, m5 = m.m23, m6 = m.m31, m7 = m.m32, m8 = m.m33;
674
+ m.m11 = m0 * mat[0] + m1 * mat[3] + m2 * mat[6];
675
+ m.m12 = m0 * mat[1] + m1 * mat[4] + m2 * mat[7];
676
+ m.m13 = m0 * mat[2] + m1 * mat[5] + m2 * mat[8];
677
+ m.m21 = m3 * mat[0] + m4 * mat[3] + m5 * mat[6];
678
+ m.m22 = m3 * mat[1] + m4 * mat[4] + m5 * mat[7];
679
+ m.m23 = m3 * mat[2] + m4 * mat[5] + m5 * mat[8];
680
+ m.m31 = m6 * mat[0] + m7 * mat[3] + m8 * mat[6];
681
+ m.m32 = m6 * mat[1] + m7 * mat[4] + m8 * mat[7];
682
+ m.m33 = m6 * mat[2] + m7 * mat[5] + m8 * mat[8];
683
+ },
684
+
685
+ getArray: function() {
686
+ // this is row major order, for WebGL you'll need to transverse this
687
+ var m = this.$matrix;
688
+
689
+ return [m.m11, m.m12, m.m13, m.m21, m.m22, m.m23, m.m31, m.m32, m.m33];
690
+ },
691
+
692
+ getFloat32Array: function() {
693
+ return new Float32Array(this.getArray());
694
+ },
695
+
696
+ getColumnMajorArray: function() {
697
+ // this is row major order, for WebGL you'll need to transverse this
698
+ var m = this.$matrix;
699
+
700
+ return [m.m11, m.m21, m.m31, m.m12, m.m22, m.m32, m.m13, m.m23, m.m33 ];
701
+ },
702
+
703
+ getColumnMajorFloat32Array: function() {
704
+ return new Float32Array(this.getColumnMajorArray());
705
+ }
706
+
707
+ };
708
+
709
+ Matrix4 = function() {
710
+ this.identity();
711
+ };
712
+
713
+ Matrix4.prototype = {
714
+ identity: function() {
715
+ this.$matrix = {
716
+ m11: 1, m12: 0, m13: 0, m14: 0,
717
+ m21: 0, m22: 1, m23: 0, m24: 0,
718
+ m31: 0, m32: 0, m33: 1, m34: 0,
719
+ m41: 0, m42: 0, m43: 0, m44: 1
720
+ };
721
+ },
722
+
723
+ translate: function(x, y, z) {
724
+ var matrix = new Matrix4();
725
+ var m = matrix.$matrix;
726
+ m.m14 = x;
727
+ m.m24 = y;
728
+ m.m34 = z;
729
+ this.multiply(matrix);
730
+ /*
731
+ * this.$matrix.m41 = this.$matrix.m11*x + this.$matrix.m21*y +
732
+ * this.$matrix.m31*z + this.$matrix.m41; this.$matrix.m42 =
733
+ * this.$matrix.m12*x + this.$matrix.m22*y + this.$matrix.m32*z +
734
+ * this.$matrix.m42; this.$matrix.m43 = this.$matrix.m13*x +
735
+ * this.$matrix.m23*y + this.$matrix.m33*z + this.$matrix.m43;
736
+ * this.$matrix.m44 = this.$matrix.m14*x + this.$matrix.m24*y +
737
+ * this.$matrix.m34*z + this.$matrix.m44;
738
+ */
739
+ },
740
+
741
+ scale: function(x, y, z) {
742
+ var matrix = new Matrix4();
743
+ var m = matrix.$matrix;
744
+ m.m11 = x;
745
+ m.m22 = y;
746
+ m.m33 = z;
747
+ this.multiply(matrix);
748
+ },
749
+
750
+ multiply: function(mat) {
751
+ var m = this.$matrix;
752
+ var mm = mat.$matrix;
753
+ var m11 = (mm.m11 * m.m11 + mm.m21 * m.m12 + mm.m31 * m.m13 + mm.m41 * m.m14);
754
+ var m12 = (mm.m12 * m.m11 + mm.m22 * m.m12 + mm.m32 * m.m13 + mm.m42 * m.m14);
755
+ var m13 = (mm.m13 * m.m11 + mm.m23 * m.m12 + mm.m33 * m.m13 + mm.m43 * m.m14);
756
+ var m14 = (mm.m14 * m.m11 + mm.m24 * m.m12 + mm.m34 * m.m13 + mm.m44 * m.m14);
757
+
758
+ var m21 = (mm.m11 * m.m21 + mm.m21 * m.m22 + mm.m31 * m.m23 + mm.m41 * m.m24);
759
+ var m22 = (mm.m12 * m.m21 + mm.m22 * m.m22 + mm.m32 * m.m23 + mm.m42 * m.m24);
760
+ var m23 = (mm.m13 * m.m21 + mm.m23 * m.m22 + mm.m33 * m.m23 + mm.m43 * m.m24);
761
+ var m24 = (mm.m14 * m.m21 + mm.m24 * m.m22 + mm.m34 * m.m23 + mm.m44 * m.m24);
762
+
763
+ var m31 = (mm.m11 * m.m31 + mm.m21 * m.m32 + mm.m31 * m.m33 + mm.m41 * m.m34);
764
+ var m32 = (mm.m12 * m.m31 + mm.m22 * m.m32 + mm.m32 * m.m33 + mm.m42 * m.m34);
765
+ var m33 = (mm.m13 * m.m31 + mm.m23 * m.m32 + mm.m33 * m.m33 + mm.m43 * m.m34);
766
+ var m34 = (mm.m14 * m.m31 + mm.m24 * m.m32 + mm.m34 * m.m33 + mm.m44 * m.m34);
767
+
768
+ var m41 = (mm.m11 * m.m41 + mm.m21 * m.m42 + mm.m31 * m.m43 + mm.m41 * m.m44);
769
+ var m42 = (mm.m12 * m.m41 + mm.m22 * m.m42 + mm.m32 * m.m43 + mm.m42 * m.m44);
770
+ var m43 = (mm.m13 * m.m41 + mm.m23 * m.m42 + mm.m33 * m.m43 + mm.m43 * m.m44);
771
+ var m44 = (mm.m14 * m.m41 + mm.m24 * m.m42 + mm.m34 * m.m43 + mm.m44 * m.m44);
772
+
773
+ m.m11 = m11;
774
+ m.m12 = m12;
775
+ m.m13 = m13;
776
+ m.m14 = m14;
777
+
778
+ m.m21 = m21;
779
+ m.m22 = m22;
780
+ m.m23 = m23;
781
+ m.m24 = m24;
782
+
783
+ m.m31 = m31;
784
+ m.m32 = m32;
785
+ m.m33 = m33;
786
+ m.m34 = m34;
787
+
788
+ m.m41 = m41;
789
+ m.m42 = m42;
790
+ m.m43 = m43;
791
+ m.m44 = m44;
792
+ },
793
+
794
+ perspective: function(fovy, aspect, near, far) {
795
+ var top = near * Math.tan(fovy * Math.PI / 360.0);
796
+ var right = top * aspect;
797
+ return this.frustum(-right, right, -top, top, near, far);
798
+ },
799
+
800
+ ortho: function(left, right, bottom, top, near, far) {
801
+ var rl = right - left;
802
+ var tb = top - bottom;
803
+ var fn = far - near;
804
+ var m = this.$matrix;
805
+ m.m11 = 2 / rl;
806
+ m.m12 = 0;
807
+ m.m13 = 0;
808
+ m.m14 = -(right + left) / rl;
809
+ m.m21 = 0;
810
+ m.m22 = 2 / tb;
811
+ m.m23 = 0;
812
+ m.m24 = -(top + bottom) / tb;
813
+ m.m31 = 0;
814
+ m.m32 = 0;
815
+ m.m33 = -2 / fn;
816
+ m.m34 = -(far + near) / fn;
817
+ m.m41 = 0;
818
+ m.m42 = 0;
819
+ m.m43 = 0;
820
+ m.m44 = 1;
821
+ },
822
+
823
+ frustum: function(left, right, bottom, top, near, far) {
824
+ var rl = right - left;
825
+ var tb = top - bottom;
826
+ var fn = far - near;
827
+ var m = this.$matrix;
828
+ m.m11 = (near * 2) / rl;
829
+ m.m12 = 0;
830
+ m.m13 = (right + left) / rl;
831
+ m.m14 = 0;
832
+ m.m21 = 0;
833
+ m.m22 = (near * 2) / tb;
834
+ m.m23 = (top + bottom) / tb;
835
+ m.m24 = 0;
836
+ m.m31 = 0;
837
+ m.m32 = 0;
838
+ m.m33 = -(far + near) / fn;
839
+ m.m34 = (-2 * far * near) / fn;
840
+ m.m41 = 0;
841
+ m.m42 = 0;
842
+ m.m43 = -1;
843
+ m.m44 = 0;
844
+ },
845
+
846
+ getArray: function() {
847
+ // this is row major order, for WebGL you'll need to transverse this
848
+ var m = this.$matrix;
849
+
850
+ return [m.m11, m.m12, m.m13, m.m14,
851
+ m.m21, m.m22, m.m23, m.m24,
852
+ m.m31, m.m32, m.m33, m.m34,
853
+ m.m41, m.m42, m.m43, m.m44];
854
+ },
855
+
856
+ getFloat32Array: function() {
857
+ return new Float32Array(this.getArray());
858
+ },
859
+
860
+ getColumnMajorArray: function() {
861
+ // this is row major order, for WebGL you'll need to transverse this
862
+ var m = this.$matrix;
863
+
864
+ return [m.m11, m.m21, m.m31, m.m41,
865
+ m.m12, m.m22, m.m32, m.m42,
866
+ m.m13, m.m23, m.m33, m.m43,
867
+ m.m14, m.m24, m.m34, m.m44];
868
+ },
869
+
870
+ getColumnMajorFloat32Array: function() {
871
+ return new Float32Array(this.getColumnMajorArray());
872
+ }
873
+ };
874
+
875
+ function TSUMix(a, b, x) {
876
+ return a + (b - a) * x;
877
+ }
878
+
879
+ //sinusoidal timing function
880
+ function TSUSineMap(x) {
881
+ return (Math.sin(x * Math.PI - (Math.PI / 2)) + 1) * 0.5;
882
+ }
883
+
884
+ //function for Twist sizing
885
+ function TwistFX(location, percent) {
886
+ var twist = 4.0 / 10.25;
887
+ var x = (1 + twist) * percent - twist * location;
888
+ if (x < 0) {
889
+ return 0;
890
+ }
891
+ else if (x > 1) {
892
+ return 1;
893
+ }
894
+ else {
895
+ return TSUSineMap(x);
896
+ }
897
+ }
898
+
899
+ //CGAffineTransformMakeRotation
900
+ function CGAffineTransformMakeRotation(angle) {
901
+ var sine, consine;
902
+
903
+ sine = Math.sin(angle);
904
+ cosine = Math.cos(angle);
905
+
906
+ return [cosine, sine, -sine, cosine, 0, 0];
907
+ }
908
+
909
+ //CGAffineTransformEqualToTransform
910
+ function CGAffineTransformEqualToTransform(t1, t2) {
911
+ return t1.a === t2.a && t1.b === t2.b && t1.c === t2.c && t1.d === t2.d && t1.tx === t2.tx && t1.ty === t2.ty;
912
+ }
913
+
914
+ //CATransform3DEqualToTransform
915
+ function CATransform3DEqualToTransform(a, b) {
916
+ var result = a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
917
+
918
+ return result;
919
+ }
920
+
921
+ //CGPointMake
922
+ function CGPointMake(x, y) {
923
+ var p = {
924
+ x: x,
925
+ y: y
926
+ };
927
+
928
+ return p;
929
+ }
930
+
931
+ //CGRectIntersection
932
+ function CGRectIntersection(r1, r2) {
933
+ var r = {
934
+ "origin": {
935
+ "x": 0,
936
+ "y": 0
937
+ },
938
+ "size": {
939
+ "width": 0,
940
+ "height": 0
941
+ }
942
+ };
943
+
944
+ var x1, x2, y1, y2;
945
+
946
+ x1 = Math.max(r1.origin.x, r2.origin.x);
947
+ x2 = Math.min(r1.origin.x + r1.size.width, r2.origin.x + r2.size.width);
948
+
949
+ if (x1 > x2) {
950
+ return r;
951
+ }
952
+
953
+ y1 = Math.max(r1.origin.y, r2.origin.y);
954
+ y2 = Math.min(r1.origin.y + r1.size.height, r2.origin.y + r2.size.height);
955
+
956
+ if (y1 > y2) {
957
+ return r;
958
+ }
959
+
960
+ r.origin.x = x1;
961
+ r.size.width = x2 - x1;
962
+ r.origin.y = y1;
963
+ r.size.height = y2 - y1;
964
+
965
+ return r;
966
+ }
967
+
968
+ // CGRectIntegral
969
+ function CGRectIntegral(rect) {
970
+ var r = {
971
+ "origin": {
972
+ "x": 0,
973
+ "y": 0
974
+ },
975
+ "size": {
976
+ "width": 0,
977
+ "height": 0
978
+ }
979
+ };
980
+
981
+ r.origin.x = Math.floor(rect.origin.x);
982
+ r.origin.y = Math.floor(rect.origin.y);
983
+ r.size.width = Math.ceil(rect.origin.x + rect.size.width) - r.origin.x;
984
+ r.size.height = Math.ceil(rect.origin.y + rect.size.height) - r.origin.y;
985
+ return r;
986
+ }
987
+
988
+ // CGRectGetMinX
989
+ function CGRectGetMinX(rect) {
990
+ return rect.origin.x;
991
+ }
992
+
993
+ // CGRectGetMinY
994
+ function CGRectGetMinY(rect) {
995
+ return rect.origin.y;
996
+ }
997
+
998
+ // CGRectGetMidX
999
+ function CGRectGetMidX(rect) {
1000
+ return rect.origin.x + rect.size.width / 2;
1001
+ }
1002
+
1003
+ // CGRectGetMidY
1004
+ function CGRectGetMidY(rect) {
1005
+ return rect.origin.y + rect.size.height / 2;
1006
+ }
1007
+
1008
+ // CGRectGetMaxX
1009
+ function CGRectGetMaxX(rect) {
1010
+ return rect.origin.x + rect.size.width;
1011
+ }
1012
+
1013
+ // CGRectGetMaxY
1014
+ function CGRectGetMaxY(rect) {
1015
+ return rect.origin.y + rect.size.height;
1016
+ }
1017
+
1018
+ // CGRectEqualToRect
1019
+ function CGRectEqualToRect(rect1, rect2) {
1020
+ return (rect1.origin.x == rect2.origin.x) && (rect1.origin.y == rect2.origin.y) && (rect1.size.width == rect2.size.width) && (rect1.size.height == rect2.size.height);
1021
+ }
1022
+
1023
+ // CGRectMake
1024
+ function CGRectMake(x, y, width, height) {
1025
+ var r = {
1026
+ "origin": {
1027
+ "x": x,
1028
+ "y": y
1029
+ },
1030
+ "size": {
1031
+ "width": width,
1032
+ "height": height
1033
+ }
1034
+ };
1035
+
1036
+ return r;
1037
+ }
1038
+
1039
+ // CGSizeMake
1040
+ function CGSizeMake(width, height) {
1041
+ var sizeOut = {};
1042
+ sizeOut.width = width;
1043
+ sizeOut.height = height;
1044
+
1045
+ return sizeOut;
1046
+ }
1047
+
1048
+ // CGSizeEqualToSize
1049
+ function CGSizeEqualToSize (size1, size2) {
1050
+ return size1.width === size2.width && size1.height === size2.height;
1051
+ }
1052
+
1053
+ // CGSizeZero
1054
+ var CGSizeZero = {
1055
+ "width": 0,
1056
+ "height": 0
1057
+ };
1058
+
1059
+ // CGRectZero
1060
+ var CGRectZero = {
1061
+ "origin": {
1062
+ "x": 0,
1063
+ "y": 0
1064
+ },
1065
+ "size": {
1066
+ "width": 0,
1067
+ "height": 0
1068
+ }
1069
+ };
1070
+
1071
+ // TSDRectUnit
1072
+ var TSDRectUnit = {
1073
+ "origin": {
1074
+ "x": 0,
1075
+ "y": 0
1076
+ },
1077
+ "size": {
1078
+ "width": 1,
1079
+ "height": 1
1080
+ }
1081
+ };
1082
+
1083
+ //TSDMixFloats
1084
+ function TSDMixFloats(a, b, fraction) {
1085
+ return a * (1.0 - fraction) + b * fraction;
1086
+ }
1087
+
1088
+ // TSDCenterOfRect
1089
+ function TSDCenterOfRect(rect) {
1090
+ return WebGraphics.makePoint(CGRectGetMidX(rect), CGRectGetMidY(rect));
1091
+ }
1092
+
1093
+ // TSDPointFromNormalizedRect
1094
+ function TSDPointFromNormalizedRect(pt, rect) {
1095
+ return WebGraphics.makePoint(rect.origin.x + pt.x * rect.size.width, rect.origin.y + pt.y * rect.size.height);
1096
+ }
1097
+
1098
+ // TSDRectWithPoints
1099
+ function TSDRectWithPoints(a, b) {
1100
+ // smallest rect enclosing two points
1101
+ var minX = Math.min(a.x, b.x);
1102
+ var maxX = Math.max(a.x, b.x);
1103
+ var minY = Math.min(a.y, b.y);
1104
+ var maxY = Math.max(a.y, b.y);
1105
+
1106
+ return CGRectMake(minX, minY, maxX - minX, maxY - minY);
1107
+ }
1108
+
1109
+ function TSDGLColor(r, g, b, a) {
1110
+ var color = {
1111
+ r: r,
1112
+ g: g,
1113
+ b: b,
1114
+ a: a
1115
+ };
1116
+
1117
+ return color;
1118
+ }
1119
+
1120
+ var TSD8bitColorDenominator = 0.003906402593851;
1121
+
1122
+ /// Creates a TSDGLColor4f from a 32-bit BGRA-encoded unsigned int
1123
+ function TSDGLColor4fMakeWithUInt(anInt) {
1124
+ var color = WebGraphics.makePoint4D(
1125
+ ((anInt & 0x00ff0000) >> 16) * TSD8bitColorDenominator,
1126
+ ((anInt & 0x0000ff00) >> 8) * TSD8bitColorDenominator,
1127
+ ((anInt & 0x000000ff)) * TSD8bitColorDenominator,
1128
+ ((anInt & 0xff000000) >> 24) * TSD8bitColorDenominator
1129
+ );
1130
+
1131
+ return color;
1132
+ }
1133
+
1134
+ // TSUReverseSquare
1135
+ function TSUReverseSquare(x) {
1136
+ var reverse = 1.0 - x;
1137
+ return 1.0 - reverse * reverse;
1138
+ }
1139
+
1140
+ window.requestAnimFrame = (function() {
1141
+ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame
1142
+ || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) {
1143
+ window.setTimeout(callback, 1000 / 60);
1144
+ };
1145
+ })();
assets/player/gl/ParameterGroup.js CHANGED
@@ -1,3 +1,153 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:650870f0913c488aa958682f77399948ccc9cfa242ada934a531680b15de2111
3
- size 4014
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * ParameterGroup.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var KNAnimParameterGroup = Class.create({
10
+ initialize: function(name) {
11
+ this.parameterGroup = ParameterGroup[name];
12
+
13
+ this.animationCurves = {};
14
+ },
15
+
16
+ doubleForKey: function(key) {
17
+ var result = this.parameterGroup[key].dblValue;
18
+
19
+ if (!result) {
20
+ result = this.parameterGroup[key];
21
+ }
22
+
23
+ return result;
24
+ },
25
+
26
+ boolForKey: function(key) {
27
+ var result = this.parameterGroup[key].dblValue;
28
+
29
+ if (!result) {
30
+ result = this.parameterGroup[key];
31
+ }
32
+
33
+ return result > 0;
34
+ },
35
+
36
+ doubleForAnimationCurve: function(key, percent) {
37
+ var path = this.pathForAnimationCurve(key);
38
+ var result = path.yValueFromXValue(percent);
39
+
40
+ return result;
41
+ },
42
+
43
+ pathForAnimationCurve: function(key) {
44
+ var bezierCurve = this.animationCurves[key];
45
+
46
+ if (!bezierCurve) {
47
+ var parameter = this.parameterGroup[key];
48
+ bezierCurve = new CubicBezierPath(parameter.controlPoints[0], parameter.controlPoints[1]);
49
+
50
+ this.animationCurves[key] = bezierCurve;
51
+ }
52
+
53
+ return bezierCurve;
54
+ }
55
+ });
56
+
57
+ // Bezier Curve with Newton's method for solving
58
+ var CubicBezierPath = Class.create({
59
+ initialize: function(p1, p2) {
60
+ var cx = this.cx = 3 * p1.x;
61
+ var bx = this.bx = 3 * (p2.x - p1.x) - cx;
62
+ var ax = this.ax = 1 - cx - bx;
63
+
64
+ var cy = this.cy = 3 * p1.y;
65
+ var by = this.by = 3 * (p2.y - p1.y) - cy;
66
+ var ay = this.ay = 1 - cy - by;
67
+
68
+ // loop 5 times maximum
69
+ this.iteration = 5;
70
+
71
+ // the tolerance accepted
72
+ this.epsilon = 1e-4;
73
+ },
74
+
75
+ bezierCurveX: function(t) {
76
+ return t * (this.cx + t * (this.bx + t * this.ax));
77
+ },
78
+
79
+ bezierCurveY: function(t) {
80
+ return t * (this.cy + t * (this.by + t * this.ay));
81
+ },
82
+
83
+ bezierCurveDerivativeX: function(t) {
84
+ return this.cx + t * (2 * this.bx + 3 * this.ax * t);
85
+ },
86
+
87
+ solveXForT: function(t) {
88
+ var epsilon = this.epsilon;
89
+ var x0 = t;
90
+ var x1;
91
+
92
+ for (var i = 0, length = this.iteration; i < length; i++) {
93
+ x1 = this.bezierCurveX(x0) - t;
94
+
95
+ if (Math.abs(x1) < epsilon) {
96
+ break;
97
+ }
98
+
99
+ x0 = x0 - (x1 / this.bezierCurveDerivativeX(x0));
100
+ }
101
+
102
+ return x0;
103
+ },
104
+
105
+ yValueFromXValue: function(xValue) {
106
+ return this.bezierCurveY(this.solveXForT(xValue));
107
+ }
108
+
109
+ });
110
+
111
+ var ParameterGroup = {
112
+ "Fireworks": {
113
+ "FireworkSizeMax": 0.3,
114
+ "FireworkDurationMax": 2,
115
+ "ParticleTrailsDitherMax": 2,
116
+ "SparkleStartTime": 0.5,
117
+ "TextOpacityEndTime": 0.6,
118
+ "ParticleTransparency": {
119
+ "dblValue": 0,
120
+ "controlPoints": [{"x": 1, "y": 0}, {"x": 0.718446, "y": 1}]
121
+ },
122
+ "TextOpacityTiming": {
123
+ "dblValue": 0,
124
+ "controlPoints": [{"x": 1, "y": 0}, {"x": 0.825627, "y": 1}]
125
+ },
126
+ "BloomBlurScale":4,
127
+ "Gravity": 20,
128
+ "ParticleBurstTiming": {
129
+ "dblValue": 0,
130
+ "controlPoints": [{"x": 0, "y": 1}, {"x": 0.551894, "y": 0.993738}]
131
+ },
132
+ "ParticleSizeStart": 0.5,
133
+ "ParticleTrailsDitherAmount": 0.5,
134
+ "CenterBurstOpacity": 1,
135
+ "BloomPower": 3,
136
+ "ParticleSizeMax": 0.5,
137
+ "ParticleSizeMin": 3,
138
+ "CenterBurstScaleMin": 0.15,
139
+ "TrailsFadeOutMax": 0.1,
140
+ "CenterBurstScaleMax": 0.3,
141
+ "TrailsFadeOutMin": 0.03,
142
+ "TextOpacityBeginTime": 0.1,
143
+ "ParticleCount": 200,
144
+ "SparklePeriod": 13,
145
+ "ParticleColorRandomness": 0.09,
146
+ "FireworkSpeedMax": 1,
147
+ "FireworkDurationMin": 1,
148
+ "FireworkSizeMin": 0.15,
149
+ "ParticleLifeSpanMinDuration": 0.5,
150
+ "FireworkSpeedMin": 0.8,
151
+ "FireworksCount": 2
152
+ }
153
+ };
assets/player/gl/TSDGLBloomEffect.js CHANGED
@@ -1,3 +1,170 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:ea5fc578fe5d6b58736f3b69bb2176600a5249d6390ec23cefc4b654fa5e9e93
3
- size 6726
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TSDGLBloomEffect.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var kShaderUniformBloomAmount = "BloomAmount";
10
+ var kShaderUniformBlurTexture = "BlurTexture";
11
+
12
+ var TSDGLBloomEffect = Class.create({
13
+ initialize: function(gl) {
14
+ this.gl = gl;
15
+ },
16
+
17
+ initWithEffectSize: function(effectSize, blurScale) {
18
+ this._effectSize = effectSize;
19
+
20
+ // blurScale must be >= 1.0
21
+ this._blurBufferSize = CGSizeMake(Math.max(16, Math.ceil(effectSize.width / blurScale)), Math.max(16, Math.ceil(effectSize.height / blurScale)));;
22
+
23
+ this.p_setupShaders();
24
+ this.p_setupBuffers();
25
+ },
26
+
27
+ p_setupShaders: function() {
28
+ var gl = this.gl;
29
+ var _blurBufferSize = this._blurBufferSize;
30
+
31
+ var blurTextureSize = WebGraphics.makePoint(1.0 / _blurBufferSize.width, 1.0 / _blurBufferSize.height);
32
+ var blurTransform = WebGraphics.makeOrthoMatrix4(0, _blurBufferSize.width, 0, _blurBufferSize.height, -1, +1);
33
+
34
+ // shader 1: horizontal blur shader
35
+ var _blurHorizontalShader = this._blurHorizontalShader = new TSDGLShader(gl);
36
+ _blurHorizontalShader.initWithDefaultHorizontalBlurShader();
37
+ _blurHorizontalShader.setMat4WithTransform3D(blurTransform, kTSDGLShaderUniformMVPMatrix);
38
+ _blurHorizontalShader.setPoint2D(blurTextureSize, kTSDGLShaderUniformTextureSize);
39
+
40
+ // shader 2: vertical blur shader
41
+ var _blurVerticalShader = this._blurVerticalShader = new TSDGLShader(gl);
42
+ _blurVerticalShader.initWithDefaultVerticalBlurShader();
43
+ _blurVerticalShader.setMat4WithTransform3D(blurTransform, kTSDGLShaderUniformMVPMatrix);
44
+ _blurVerticalShader.setPoint2D(blurTextureSize, kTSDGLShaderUniformTextureSize);
45
+
46
+ // shader 3: transfer shader
47
+ var _fboTransferShader = this._fboTransferShader = new TSDGLShader(gl);
48
+ _fboTransferShader.initWithDefaultTextureShader();
49
+ _fboTransferShader.setMat4WithTransform3D(blurTransform, kTSDGLShaderUniformMVPMatrix);
50
+
51
+ // shader 4: bloom effect shader
52
+ var _bloomShader = this._bloomShader = new TSDGLShader(gl);
53
+ _bloomShader.initWithShaderFileNames("bloom", "bloom");
54
+ _bloomShader.setGLint(0, kTSDGLShaderUniformTexture);
55
+ _bloomShader.setGLint(1, kShaderUniformBlurTexture);
56
+ },
57
+
58
+ p_setupBuffers: function() {
59
+ var gl = this.gl;
60
+ var _effectSize = this._effectSize;
61
+ var _blurBufferSize = this._blurBufferSize;
62
+ var meshSize = CGSizeMake(2, 2);
63
+ var effectRect = CGRectMake(0, 0, _effectSize.width, _effectSize.height);
64
+ var blurBufferRect = CGRectMake(0, 0, _blurBufferSize.width, _blurBufferSize.height);
65
+
66
+ // buffer 1: bloom effect
67
+ var _dataBuffer = this._dataBuffer = new TSDGLDataBuffer(gl);
68
+ _dataBuffer.initWithVertexRect(effectRect, TSDRectUnit, meshSize, false, false);
69
+
70
+ // buffer 2: blur buffer
71
+ var _blurDataBuffer = this._blurDataBuffer = new TSDGLDataBuffer(gl);
72
+ _blurDataBuffer.initWithVertexRect(blurBufferRect, CGRectZero, meshSize, true, false);
73
+
74
+ // buffer 3: transfer buffer
75
+ var _blurTransferDataBuffer = this._blurTransferDataBuffer = new TSDGLDataBuffer(gl);
76
+ _blurTransferDataBuffer.initWithVertexRect(blurBufferRect, TSDRectUnit, meshSize, false, false);
77
+
78
+ // initialize color framebuffer with one texture for storing incoming rendering
79
+ this._colorFramebuffer = new TSDGLFrameBuffer(gl, _effectSize, 1);
80
+
81
+ // initialize blur framebuffer with two textures for blurring operations
82
+ this._blurFramebuffer = new TSDGLFrameBuffer(gl, _blurBufferSize, 2);
83
+ },
84
+
85
+ bindFramebuffer: function() {
86
+ this._colorFramebuffer.bindFramebuffer();
87
+ },
88
+
89
+ unbindFramebufferAndBindGLFramebuffer: function(previousFramebuffer) {
90
+ this._colorFramebuffer.unbindFramebufferAndBindGLFramebuffer(previousFramebuffer);
91
+ },
92
+
93
+ p_blurColorBufferWithPreviousFramebuffer: function(previousFramebuffer) {
94
+ var gl = this.gl;
95
+ var _blurFramebuffer = this._blurFramebuffer;
96
+ var _blurBufferSize = this._blurBufferSize;
97
+
98
+ _blurFramebuffer.bindFramebuffer();
99
+
100
+ gl.clear(gl.COLOR_BUFFER_BIT);
101
+
102
+ gl.viewport(0, 0, _blurBufferSize.width, _blurBufferSize.height);
103
+
104
+ // Step 1: Transfer color to blur buffer
105
+
106
+ gl.bindTexture(gl.TEXTURE_2D, this._colorFramebuffer.currentGLTexture());
107
+
108
+ this._blurTransferDataBuffer.drawWithShader(this._fboTransferShader, true);
109
+
110
+ // Step 2: Blur horizontally
111
+
112
+ var blurTexture = _blurFramebuffer.currentGLTexture();
113
+ _blurFramebuffer.setCurrentTextureToNext();
114
+
115
+ gl.clear(gl.COLOR_BUFFER_BIT);
116
+
117
+ gl.bindTexture(gl.TEXTURE_2D, blurTexture);
118
+
119
+ this._blurDataBuffer.drawWithShader(this._blurHorizontalShader, true);
120
+
121
+ // Step 3: Blur Vertically
122
+
123
+ gl.bindTexture(gl.TEXTURE_2D, null);
124
+
125
+ blurTexture = _blurFramebuffer.currentGLTexture();
126
+ _blurFramebuffer.setCurrentTextureToNext();
127
+
128
+ gl.clear(gl.COLOR_BUFFER_BIT);
129
+
130
+ gl.bindTexture(gl.TEXTURE_2D, blurTexture);
131
+
132
+ this._blurDataBuffer.drawWithShader(this._blurVerticalShader, true);
133
+
134
+ _blurFramebuffer.unbindFramebufferAndBindGLFramebuffer(previousFramebuffer);
135
+
136
+ gl.bindTexture(gl.TEXTURE_2D, null);
137
+ },
138
+
139
+ drawBloomEffectWithMVPMatrix: function(MVPMatrix, bloomAmount, currentGLFramebuffer) {
140
+ var gl = this.gl;
141
+ var _effectSize = this._effectSize;
142
+ var oldViewportRect = gl.getParameter(gl.VIEWPORT);
143
+
144
+ // Blur color buffer into blur FBO
145
+ this.p_blurColorBufferWithPreviousFramebuffer(currentGLFramebuffer);
146
+
147
+ // change viewport back to effect size
148
+ gl.viewport(0, 0, _effectSize.width, _effectSize.height);
149
+
150
+ // Draw Bloom
151
+ gl.activeTexture(gl.TEXTURE1);
152
+ gl.bindTexture(gl.TEXTURE_2D, this._blurFramebuffer.currentGLTexture());
153
+ gl.activeTexture(gl.TEXTURE0);
154
+ gl.bindTexture(gl.TEXTURE_2D, this._colorFramebuffer.currentGLTexture());
155
+
156
+ var _bloomShader = this._bloomShader;
157
+ _bloomShader.setMat4WithTransform3D(MVPMatrix, kTSDGLShaderUniformMVPMatrix);
158
+ _bloomShader.setGLFloat(bloomAmount, kShaderUniformBloomAmount);
159
+
160
+ this._dataBuffer.drawWithShader(_bloomShader, true);
161
+
162
+ gl.activeTexture(gl.TEXTURE1);
163
+ gl.bindTexture(gl.TEXTURE_2D, null);
164
+ gl.activeTexture(gl.TEXTURE0);
165
+ gl.bindTexture(gl.TEXTURE_2D, null);
166
+
167
+ // change viewport back to original size
168
+ gl.viewport(oldViewportRect[0], oldViewportRect[1], oldViewportRect[2], oldViewportRect[3]);
169
+ }
170
+ });
assets/player/gl/TSDGLDataBuffer.js CHANGED
@@ -1,3 +1,823 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:ed75ed02475d747fc5d8bf38d62998ac7ff9794c95ea2a0ed30e489c1de2dec4
3
- size 26073
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TSDGLDataBuffer.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var CHAR_MAX = 127;
10
+ var UCHAR_MAX = 255;
11
+ var SHRT_MAX = 32767;
12
+ var USHRT_MAX = 65535;
13
+
14
+ /* Boolean */
15
+ var GL_FALSE = 0;
16
+ var GL_TRUE = 1;
17
+
18
+ /* BeginMode */
19
+ var GL_POINTS = 0x0000;
20
+ var GL_LINES = 0x0001;
21
+ var GL_LINE_LOOP = 0x0002;
22
+ var GL_LINE_STRIP = 0x0003;
23
+ var GL_TRIANGLES = 0x0004;
24
+ var GL_TRIANGLE_STRIP = 0x0005;
25
+ var GL_TRIANGLE_FAN = 0x0006;
26
+
27
+ /* DataType */
28
+ var GL_BYTE = 0x1400;
29
+ var GL_UNSIGNED_BYTE = 0x1401;
30
+ var GL_SHORT = 0x1402;
31
+ var GL_UNSIGNED_SHORT = 0x1403;
32
+ var GL_INT = 0x1404;
33
+ var GL_UNSIGNED_INT = 0x1405;
34
+ var GL_FLOAT = 0x1406;
35
+ var GL_DOUBLE = 0x140A;
36
+
37
+ var GL_STREAM_DRAW = 0x88E0;
38
+ var GL_STATIC_DRAW = 0x88E4;
39
+ var GL_DYNAMIC_DRAW = 0x88E8;
40
+
41
+ var GL_FLOAT_VEC2 = 0x8B50;
42
+ var GL_FLOAT_VEC3 = 0x8B51;
43
+ var GL_FLOAT_VEC4 = 0x8B52;
44
+ var GL_INT_VEC2 = 0x8B53;
45
+ var GL_INT_VEC3 = 0x8B54;
46
+ var GL_INT_VEC4 = 0x8B55;
47
+ var GL_BOOL = 0x8B56;
48
+ var GL_BOOL_VEC2 = 0x8B57;
49
+ var GL_BOOL_VEC3 = 0x8B58;
50
+ var GL_BOOL_VEC4 = 0x8B59;
51
+ var GL_FLOAT_MAT2 = 0x8B5A;
52
+ var GL_FLOAT_MAT3 = 0x8B5B;
53
+ var GL_FLOAT_MAT4 = 0x8B5C;
54
+ var GL_SAMPLER_1D = 0x8B5D;
55
+ var GL_SAMPLER_2D = 0x8B5E;
56
+ var GL_SAMPLER_3D = 0x8B5F;
57
+ var GL_SAMPLER_CUBE = 0x8B60;
58
+
59
+ var TSDGLDataBufferDataTypeUnknown = 0;
60
+ var TSDGLDataBufferDataTypeByte = GL_BYTE;
61
+ var TSDGLDataBufferDataTypeUnsignedByte = GL_UNSIGNED_BYTE;
62
+ var TSDGLDataBufferDataTypeShort = GL_SHORT;
63
+ var TSDGLDataBufferDataTypeUnsignedShort = GL_UNSIGNED_SHORT;
64
+ var TSDGLDataBufferDataTypeFloat = GL_FLOAT;
65
+
66
+ function TSDGLDataBufferDataTypeAsGLEnum(dataType) {
67
+ var result = 0;
68
+ switch (dataType) {
69
+ case TSDGLDataBufferDataTypeByte:
70
+ result = GL_BYTE;
71
+ break;
72
+ case TSDGLDataBufferDataTypeUnsignedByte:
73
+ result = GL_UNSIGNED_BYTE;
74
+ break;
75
+ case TSDGLDataBufferDataTypeUnsignedShort:
76
+ result = GL_UNSIGNED_SHORT;
77
+ break;
78
+ case TSDGLDataBufferDataTypeShort:
79
+ result = GL_SHORT;
80
+ break;
81
+ case TSDGLDataBufferDataTypeFloat:
82
+ result = GL_FLOAT;
83
+ break;
84
+ case TSDGLDataBufferDataTypeUnknown:
85
+ console.log("Unknown TSDGLdataBufferDataType!");
86
+ break;
87
+ }
88
+
89
+ return result;
90
+ }
91
+
92
+ function TSDGLDataBufferDataTypeSize(dataType) {
93
+ var result = 0;
94
+ switch (dataType) {
95
+ case GL_BYTE:
96
+ result = 1;
97
+ break;
98
+ case GL_UNSIGNED_BYTE:
99
+ result = 1;
100
+ break;
101
+ case GL_SHORT:
102
+ result = 2;
103
+ break;
104
+ case GL_UNSIGNED_SHORT:
105
+ result = 2;
106
+ break;
107
+ case GL_FLOAT:
108
+ result = 4;
109
+ break;
110
+ default:
111
+ break;
112
+ }
113
+
114
+ return result;
115
+ }
116
+
117
+ function TSDGLPoint2DByteFromPoint2D(aPoint, isNormalized) {
118
+ var x = TSDGLbyteFromFloat(aPoint.x, isNormalized);
119
+ var y = TSDGLbyteFromFloat(aPoint.y, isNormalized);
120
+
121
+ var p = new Int8Array(2);
122
+ p.set([x, y], 0);
123
+
124
+ return p;
125
+ }
126
+
127
+ function TSDGLbyteFromFloat(aFloat, isNormalized) {
128
+ if (isNormalized) {
129
+ aFloat *= CHAR_MAX;
130
+ }
131
+
132
+ return aFloat;
133
+ }
134
+
135
+ function TSDGLPoint2DUnsignedByteFromPoint2D(aPoint, isNormalized) {
136
+ var x = TSDGLubyteFromFloat(aPoint.x, isNormalized);
137
+ var y = TSDGLubyteFromFloat(aPoint.y, isNormalized);
138
+
139
+ var p = new Uint8Array(2);
140
+
141
+ p.set([x, y], 0);
142
+
143
+ return p;
144
+ }
145
+
146
+ function TSDGLubyteFromFloat(aFloat, isNormalized) {
147
+ if (isNormalized) {
148
+ aFloat *= UCHAR_MAX;
149
+ }
150
+
151
+ return aFloat;
152
+ }
153
+
154
+ function TSDGLPoint2DShortFromPoint2D(aPoint, isNormalized) {
155
+ var x = TSDGLshortFromFloat(aPoint.x, isNormalized);
156
+ var y = TSDGLshortFromFloat(aPoint.y, isNormalized);
157
+
158
+ var p = new Int16Array(4);
159
+ p.set([x, y], 0);
160
+
161
+ return p;
162
+ }
163
+
164
+ function TSDGLshortFromFloat(aFloat, isNormalized) {
165
+ if (isNormalized) {
166
+ aFloat *= SHRT_MAX;
167
+ }
168
+
169
+ return aFloat;
170
+ }
171
+
172
+ function TSDGLPoint2DUnsignedShortFromPoint2D(aPoint, isNormalized) {
173
+ var x = TSDGLushortFromFloat(aPoint.x, isNormalized);
174
+ var y = TSDGLushortFromFloat(aPoint.y, isNormalized);
175
+
176
+ var p = new Uint16Array(4);
177
+ p.set([x, y], 0);
178
+
179
+ return p;
180
+ }
181
+
182
+ function TSDGLushortFromFloat(aFloat, isNormalized) {
183
+ if (isNormalized) {
184
+ aFloat *= USHRT_MAX;
185
+ }
186
+ return aFloat;
187
+ }
188
+
189
+ function TSDGLDataBufferSetGLPoint2DWithDataType(mGLData, bufferOffset, dataType, isNormalized, aPoint2D) {
190
+ switch (dataType) {
191
+ case TSDGLDataBufferDataTypeByte:
192
+ var value = TSDGLPoint2DByteFromPoint2D(aPoint2D, isNormalized);
193
+ var typedArray = new Int8Array(mGLData);
194
+ typedArray.set(value, bufferOffset);
195
+
196
+ break;
197
+
198
+ case TSDGLDataBufferDataTypeUnsignedByte:
199
+ var value = TSDGLPoint2DUnsignedByteFromPoint2D(aPoint2D, isNormalized);
200
+ var typedArray = new Uint8Array(mGLData);
201
+ typedArray.set(value, bufferOffset);
202
+
203
+ break;
204
+
205
+ case TSDGLDataBufferDataTypeShort:
206
+ var value = TSDGLPoint2DShortFromPoint2D(aPoint2D, isNormalized);
207
+ var typedArray = new Int16Array(mGLData);
208
+ typedArray.set(value, bufferOffset/2);
209
+
210
+ break;
211
+
212
+ case TSDGLDataBufferDataTypeUnsignedShort:
213
+ var value = TSDGLPoint2DUnsignedShortFromPoint2D(aPoint2D, isNormalized);
214
+ var typedArray = new Uint16Array(mGLData);
215
+ typedArray.set(value, bufferOffset/2);
216
+
217
+ break;
218
+
219
+ case TSDGLDataBufferDataTypeFloat:
220
+ var typedArray = new Float32Array(mGLData);
221
+ typedArray.set([aPoint2D.x, aPoint2D.y], bufferOffset/4);
222
+
223
+ break;
224
+ case TSDGLDataBufferDataTypeUnknown:
225
+ console.log("Unknown data type!");
226
+ break;
227
+ }
228
+ }
229
+
230
+ var TSDGLDataBufferAttribute = Class.create({
231
+ initialize: function(name, bufferUsage, dataType, normalized, componentCount) {
232
+ this.locationInShader = -1;
233
+ this.bufferOffset = null;
234
+ this.dataArrayBuffer = null;
235
+ this.dataBuffer = null;
236
+
237
+ this.initWithName(name, bufferUsage, dataType, normalized, componentCount);
238
+ },
239
+
240
+ initWithName: function(attributeName, bufferUsage, dataType, isNormalized, componentCount) {
241
+ this.name = attributeName;
242
+ this.bufferUsage = bufferUsage;
243
+ this.dataType = dataType;
244
+
245
+ if (this.dataType === GL_SHORT) {
246
+ this.dataType = GL_FLOAT;
247
+ }
248
+
249
+ this.componentCount = componentCount;
250
+ this.isNormalized = isNormalized;
251
+
252
+ this.locationInShader = -1;
253
+ }
254
+ });
255
+
256
+ var TSDGLDataArrayBuffer = Class.create({
257
+ initialize: function(gl) {
258
+ this.gl = gl;
259
+
260
+ this._vertexAttributes = null;
261
+ this.mVertexCount = 0;
262
+
263
+ // data type size in bytes
264
+ this._dataTypeSizeInBytes = 0;
265
+
266
+ // GL_STATIC_DRAW, GL_STREAM_DRAW, etc
267
+ this._bufferUsage = 0;
268
+
269
+ this.mNeedsUpdateFirstIndex = [];
270
+ this.mNeedsUpdateLastIndex = [];
271
+
272
+ this.mGLData = null;
273
+
274
+ // GL vertex data buffer
275
+ this.mGLDataBufferHasBeenSetup = false;
276
+
277
+ this.mGLDataBuffers = [];
278
+
279
+ this.mAttributeOffsetsDictionary = null;
280
+
281
+ this.GLDataBufferEntrySize = 0;
282
+
283
+ // for double-buffering
284
+ this.bufferCount = 1;
285
+ this.currentBufferIndex = 0;
286
+ },
287
+
288
+ initWithVertexAttributes: function(attributes, vertexCount, bufferCount) {
289
+ this._vertexAttributes = attributes.slice();
290
+ this.mVertexCount = vertexCount;
291
+ this.mAttributeOffsetsDictionary = {};
292
+
293
+ // Sort the attributes into buffers by buffer usage type
294
+ var bufferSizeIfFloats = 0;
295
+
296
+ var bufferOffset = 0;
297
+
298
+ for (var i = 0, length = this._vertexAttributes.length; i < length; i++) {
299
+ var attribute = this._vertexAttributes[i];
300
+
301
+ // Assign data array buffer to attribute
302
+ attribute.dataArrayBuffer = this;
303
+
304
+ var dataTypeSizeInBytes = TSDGLDataBufferDataTypeSize(attribute.dataType);
305
+
306
+ if (this._bufferUsage === 0) {
307
+ this._bufferUsage = attribute.bufferUsage;
308
+ }
309
+
310
+ // Assign buffer offset
311
+ attribute.bufferOffset = bufferOffset;
312
+
313
+ var paddedSize = attribute.componentCount * dataTypeSizeInBytes;
314
+
315
+ paddedSize = (paddedSize + 3) & ~3;
316
+
317
+ bufferOffset += paddedSize;
318
+
319
+ bufferSizeIfFloats += attribute.componentCount * 4;
320
+ }
321
+
322
+ // Create the buffer data (if necessary)
323
+ this.GLDataBufferEntrySize = bufferOffset;
324
+
325
+ // We need to give the arraybuffer a size
326
+ if (this.GLDataBufferEntrySize > 0) {
327
+ this.mGLData = new ArrayBuffer(this.mVertexCount * this.GLDataBufferEntrySize);
328
+ }
329
+
330
+ this.bufferCount = bufferCount;
331
+
332
+ this.mNeedsUpdateFirstIndex = [];
333
+ this.mNeedsUpdateLastIndex = [];
334
+
335
+ for (var i = 0; i < bufferCount; i++) {
336
+ this.mNeedsUpdateFirstIndex[i] = -1;
337
+ this.mNeedsUpdateLastIndex[i] = -1;
338
+ }
339
+ },
340
+
341
+ p_setupGLDataBufferIfNecessary: function() {
342
+ var gl = this.gl;
343
+
344
+ // Sets up GL buffers
345
+ if (this.mGLDataBufferHasBeenSetup) {
346
+ return;
347
+ }
348
+
349
+ for (var i = 0; i < this.bufferCount; i++) {
350
+ this.mGLDataBuffers[i] = gl.createBuffer();
351
+
352
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.mGLDataBuffers[i]);
353
+
354
+ gl.bufferData(gl.ARRAY_BUFFER, this.mGLData, this._bufferUsage);
355
+
356
+ this.mNeedsUpdateFirstIndex[i] = -1;
357
+ this.mNeedsUpdateLastIndex[i] = -1;
358
+ }
359
+
360
+ this.mGLDataBufferHasBeenSetup = true;
361
+ },
362
+
363
+ updateDataBufferIfNecessary: function() {
364
+ this.p_setupGLDataBufferIfNecessary();
365
+
366
+ if (!this.hasUpdatedData()) {
367
+ // Nothing needs to be updated!
368
+ return;
369
+ }
370
+
371
+ if (this._bufferUsage == GL_STATIC_DRAW) {
372
+ console.log("We're GL_STATIC_DRAW but trying (and FAILING) to update the array after initial setup!");
373
+ return;
374
+ }
375
+
376
+ var gl = this.gl;
377
+ // Combine all buffer's updated ranges, in case they're not the same...
378
+ var firstIndex = Number.MAX_SAFE_INTEGER;
379
+ var lastIndex = -1;
380
+
381
+ for (var i = 0; i < this.bufferCount; i++) {
382
+ var thisFirstIndex = this.mNeedsUpdateFirstIndex[i];
383
+ if (thisFirstIndex !== -1) {
384
+ firstIndex = Math.min(firstIndex, thisFirstIndex);
385
+ }
386
+ var thisLastIndex = this.mNeedsUpdateLastIndex[i];
387
+ if (thisLastIndex !== -1) {
388
+ lastIndex = Math.max(lastIndex, this.mNeedsUpdateLastIndex[i]);
389
+ }
390
+ }
391
+
392
+ var offset = firstIndex;
393
+ var size = lastIndex + 1 - firstIndex;
394
+ offset *= this.GLDataBufferEntrySize;
395
+ size *= this.GLDataBufferEntrySize;
396
+
397
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.mGLDataBuffers[this.currentBufferIndex]);
398
+ gl.bufferSubData(gl.ARRAY_BUFFER, offset, this.mGLData);
399
+
400
+ this.mNeedsUpdateFirstIndex[this.currentBufferIndex] = -1;
401
+ this.mNeedsUpdateLastIndex[this.currentBufferIndex] = -1;
402
+ },
403
+
404
+ p_bufferOffsetOfAttribute: function(attribute, index, component) {
405
+ var bufferOffset = index * this.GLDataBufferEntrySize;
406
+
407
+ bufferOffset += attribute.bufferOffset;
408
+
409
+ if (component !== 0) {
410
+ bufferOffset += TSDGLDataBufferDataTypeSize(attribute.dataType) * component;
411
+ }
412
+
413
+ return bufferOffset;
414
+ },
415
+
416
+ setGLPoint2D: function(aPoint2D, attribute, index) {
417
+ var bufferOffset = this.p_bufferOffsetOfAttribute(attribute, index, 0);
418
+ TSDGLDataBufferSetGLPoint2DWithDataType(this.mGLData, bufferOffset, attribute.dataType, attribute.isNormalized, aPoint2D);
419
+
420
+ this.addIndexNeedsUpdate(index);
421
+ },
422
+
423
+ enableVertexAttributeArrayBuffersWithShader: function(shader) {
424
+ var gl = this.gl;
425
+
426
+ this.updateDataBufferIfNecessary();
427
+
428
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.mGLDataBuffers[this.currentBufferIndex]);
429
+
430
+ for (var i = 0, length = this._vertexAttributes.length; i < length; i++) {
431
+ var attribute = this._vertexAttributes[i];
432
+ var locationInShader = attribute.locationInShader;
433
+
434
+ if (locationInShader === -1) {
435
+ locationInShader = shader.locationForAttribute(attribute.name);
436
+
437
+ if (locationInShader === -1) {
438
+ console.log("Could not find attribute " + attribute.name + "in shader!");
439
+ }
440
+
441
+ attribute.locationInShader = locationInShader;
442
+ }
443
+
444
+ var stride = 0;
445
+
446
+ if (this._vertexAttributes.length > 1) {
447
+ // we're not tight-packed, so need to specify how many elements to skip when iterating
448
+ stride = this.GLDataBufferEntrySize;
449
+ }
450
+
451
+ var dataType = TSDGLDataBufferDataTypeAsGLEnum(attribute.dataType);
452
+
453
+ gl.enableVertexAttribArray(locationInShader);
454
+ gl.vertexAttribPointer(locationInShader, attribute.componentCount, dataType, attribute.isNormalized ? GL_TRUE : GL_FALSE, stride, attribute.bufferOffset);
455
+ }
456
+ },
457
+
458
+ disableVertexAttributeArrayBuffersWithShader: function(shader) {
459
+ var gl = this.gl;
460
+
461
+ for (var i = 0, length = this._vertexAttributes.length; i < length; i++) {
462
+ var attribute = this._vertexAttributes[i];
463
+ gl.disableVertexAttribArray(attribute.locationInShader);
464
+ }
465
+
466
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
467
+ },
468
+
469
+ hasUpdatedData: function() {
470
+ for (var i = 0; i < this.bufferCount; i++) {
471
+ if (this.mNeedsUpdateFirstIndex[i] !== -1) {
472
+ return true;
473
+ }
474
+ }
475
+ return false;
476
+ },
477
+
478
+ addIndexNeedsUpdate: function(index) {
479
+ var currentBufferIndex = this.currentBufferIndex;
480
+ var mNeedsUpdateFirstIndex = this.mNeedsUpdateFirstIndex;
481
+ var mNeedsUpdateLastIndex = this.mNeedsUpdateLastIndex;
482
+
483
+ mNeedsUpdateFirstIndex[currentBufferIndex] = (mNeedsUpdateFirstIndex[currentBufferIndex] == -1) ? index : Math.min(mNeedsUpdateFirstIndex[currentBufferIndex], index);
484
+ mNeedsUpdateLastIndex[currentBufferIndex] = (mNeedsUpdateLastIndex[currentBufferIndex] == -1) ? index : Math.max(mNeedsUpdateLastIndex[currentBufferIndex], index);
485
+ }
486
+
487
+ });
488
+
489
+ var TSDGLDataBuffer = Class.create({
490
+ initialize: function(gl) {
491
+ this.gl = gl;
492
+
493
+ this.mCurrentBufferIndex = 0;
494
+ this.mArrayBuffers = [];
495
+ this.mAttributeToArrayBuffersDictionary = {};
496
+
497
+ // Element array buffer
498
+ this.mElementArrayCount = 0;
499
+ this.mGLElementData = null;
500
+ this.mGLElementDataBufferWasSetup = false;
501
+ this.mGLElementDataBuffer = null;
502
+
503
+ this.mGLElementMeshSize = {
504
+ width: 0,
505
+ height: 0
506
+ }
507
+
508
+ this.mGLElementQuadParticleCount = 0;
509
+ },
510
+
511
+ p_setupGLElementArrayBufferIfNecessary: function() {
512
+ var gl = this.gl;
513
+
514
+ if (this.mGLElementDataBufferWasSetup) {
515
+ return;
516
+ }
517
+
518
+ if (!this.mGLElementData) {
519
+ this.mGLElementDataBufferWasSetup = true;
520
+ return;
521
+ }
522
+
523
+ var useIndexCounter = false;
524
+ var indexCounter = 0;
525
+
526
+ if (!CGSizeEqualToSize(this.mGLElementMeshSize, CGSizeZero)) {
527
+ useIndexCounter = true;
528
+
529
+ // set up grid-based element array data
530
+ for (var y = 0; y < this.mGLElementMeshSize.height - 1; ++y) {
531
+ for (var x = 0; x < this.mGLElementMeshSize.width; ++x) {
532
+ this.setGLushort((y + 0) * this.mGLElementMeshSize.width + x, indexCounter++);
533
+ this.setGLushort((y + 1) * this.mGLElementMeshSize.width + x, indexCounter++);
534
+ }
535
+ }
536
+ } else if (this.mGLElementQuadParticleCount != 0) {
537
+ useIndexCounter = true;
538
+ this.drawMode = GL_TRIANGLES;
539
+
540
+ // set up quad particle-based element array data
541
+ for (var i = 0; i < this.mGLElementQuadParticleCount; ++i) {
542
+ // First triangle
543
+ this.setGLushort((4 * i + 0), indexCounter++);
544
+ this.setGLushort((4 * i + 1), indexCounter++);
545
+ this.setGLushort((4 * i + 2), indexCounter++);
546
+
547
+ // Second triangle
548
+ this.setGLushort((4 * i + 0), indexCounter++);
549
+ this.setGLushort((4 * i + 2), indexCounter++);
550
+ this.setGLushort((4 * i + 3), indexCounter++);
551
+ }
552
+ }
553
+
554
+ this.mGLElementDataBuffer = gl.createBuffer();
555
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mGLElementDataBuffer);
556
+
557
+ this.mGLElementDataBufferWasSetup = true;
558
+ },
559
+
560
+ newDataBufferWithVertexAttributes: function(attributes, meshSize, isDoubleBuffered) {
561
+ var vertexCount = meshSize.width * meshSize.height;
562
+ var indexCount = meshSize.width * 2 * (meshSize.height - 1);
563
+
564
+ this.initWithVertexAttributesDesignated(attributes, vertexCount, indexCount, isDoubleBuffered);
565
+
566
+ this.mGLElementMeshSize = meshSize;
567
+ },
568
+
569
+ initWithVertexAttributes: function(attributes, meshSize) {
570
+ var vertexCount = meshSize.width * meshSize.height;
571
+ var indexCount = meshSize.width * 2 * (meshSize.height - 1);
572
+
573
+ this.initWithVertexAttributesDesignated(attributes, vertexCount, indexCount, false);
574
+
575
+ this.mGLElementMeshSize = meshSize;
576
+ },
577
+
578
+ initWithVertexAttributesDesignated: function(attributes, vertexCount, indexElementCount, isDoubleBuffered) {
579
+ this._doubleBuffered = isDoubleBuffered;
580
+ this.drawMode = GL_TRIANGLE_STRIP;
581
+ this._vertexAttributes = attributes;
582
+ this._vertexCount = vertexCount;
583
+
584
+ this.mArrayBuffers = [];
585
+ this.mAttributeToArrayBuffersDictionary = {};
586
+
587
+ var attributesToArrange = attributes.slice();
588
+
589
+ while (attributesToArrange.length > 0) {
590
+ var thisAttribute = attributesToArrange[0];
591
+ var currentAttributes = [];
592
+
593
+ for (var i = 0, length = attributesToArrange.length; i < length; i++) {
594
+ var attribute = attributesToArrange[i];
595
+
596
+ if (attribute.bufferUsage == thisAttribute.bufferUsage) {
597
+ currentAttributes.push(attribute);
598
+ }
599
+ }
600
+
601
+ var bufferCount = ((isDoubleBuffered && thisAttribute.bufferUsage !== GL_STATIC_DRAW) ? 2 : 1);
602
+
603
+ var arrayBuffer = new TSDGLDataArrayBuffer(this.gl);
604
+
605
+ arrayBuffer.initWithVertexAttributes(currentAttributes, vertexCount, bufferCount);
606
+
607
+ for (var i = 0, length = currentAttributes.length; i < length; i++) {
608
+ var attribute = currentAttributes[i];
609
+
610
+ // this will cause circular reference
611
+ attribute.dataBuffer = this;
612
+ this.mAttributeToArrayBuffersDictionary[attribute.name] = arrayBuffer;
613
+ }
614
+
615
+ this.mArrayBuffers.push(arrayBuffer);
616
+
617
+ for (var i = 0, length = currentAttributes.length; i < length; i++) {
618
+ var element = currentAttributes[i];
619
+ attributesToArrange.splice(attributesToArrange.indexOf(element), 1);
620
+ }
621
+ }
622
+
623
+ if (indexElementCount > 0) {
624
+ this.mElementArrayCount = indexElementCount;
625
+
626
+ this.mGLElementData = new ArrayBuffer(this.mElementArrayCount * 2);
627
+ }
628
+
629
+
630
+ },
631
+
632
+ initWithVertexRect: function(vertexRect, textureRect, meshSize, isTextureFlipped, includeCenterAttribute) {
633
+ var gl = this.gl;
634
+
635
+ var shouldSetupTexCoords = !CGRectEqualToRect(textureRect, CGRectZero);
636
+
637
+ var quadAttributes = [];
638
+ var positionAttribute = new TSDGLDataBufferAttribute("Position", GL_STATIC_DRAW, GL_FLOAT, false, 2);
639
+
640
+ quadAttributes.push(positionAttribute);
641
+
642
+ var texCoordAttribute;
643
+ if (shouldSetupTexCoords) {
644
+ var dataType = GL_SHORT;
645
+
646
+ if (CGRectEqualToRect(textureRect, CGRectMake(0, 0, 1, 1)) && CGSizeEqualToSize(meshSize, CGSizeMake(2, 2))) {
647
+ // If we're just passing in the unit rectangle, we can use lower precision texcoords!
648
+ dataType = GL_UNSIGNED_BYTE;
649
+ }
650
+
651
+ texCoordAttribute = new TSDGLDataBufferAttribute("TexCoord", GL_STATIC_DRAW, dataType, true, 2);
652
+
653
+ quadAttributes.push(texCoordAttribute);
654
+ }
655
+
656
+ var centerAttribute;
657
+ if (includeCenterAttribute) {
658
+ centerAttribute = new TSDGLDataBufferAttribute("Center", GL_STATIC_DRAW, GL_FLOAT, false, 2);
659
+
660
+ quadAttributes.push(centerAttribute);
661
+ }
662
+
663
+ this.initWithVertexAttributes(quadAttributes, meshSize);
664
+
665
+ var index = 0;
666
+
667
+ // This is TSDGLPoint2D in native which is a struct of float type
668
+ var center = TSDCenterOfRect(vertexRect);
669
+
670
+ var verticesWide = parseInt(meshSize.width - 1);
671
+ var verticesHigh = parseInt(meshSize.height - 1);
672
+
673
+ for (var row = 0; row <= verticesHigh; ++row) {
674
+ for (var col = 0; col <= verticesWide; ++col) {
675
+ var point = WebGraphics.makePoint(col / verticesWide, row / verticesHigh);
676
+
677
+ // This is TSDGLPoint2D in native which is a struct of float type
678
+ var vertex = TSDPointFromNormalizedRect(point, vertexRect);
679
+
680
+ this.setGLPoint2D(vertex, positionAttribute, index);
681
+
682
+ if (shouldSetupTexCoords) {
683
+ var texCoord = TSDPointFromNormalizedRect(point, textureRect);
684
+ if (isTextureFlipped) {
685
+ texCoord = WebGraphics.makePoint(texCoord.x, 1.0 - texCoord.y);
686
+ }
687
+ this.setGLPoint2D(texCoord, texCoordAttribute, index);
688
+ }
689
+ if (includeCenterAttribute) {
690
+ this.setGLPoint2D(center, centerAttribute, index);
691
+ }
692
+
693
+ index++;
694
+ }
695
+ }
696
+
697
+ },
698
+
699
+ setGLPoint2D: function(aPoint2D, attribute, index) {
700
+ attribute.dataArrayBuffer.setGLPoint2D(aPoint2D, attribute, index);
701
+ },
702
+
703
+ setGLushort: function(aShort, index) {
704
+ var bufferOffset = index;
705
+ var typedArray = new Uint16Array(this.mGLElementData);
706
+
707
+ typedArray.set([aShort], bufferOffset);
708
+ },
709
+
710
+ enableElementArrayBuffer: function() {
711
+ var gl = this.gl;
712
+
713
+ this.p_setupGLElementArrayBufferIfNecessary();
714
+
715
+ if (this.mGLElementDataBufferWasSetup) {
716
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mGLElementDataBuffer);
717
+ }
718
+ },
719
+
720
+ disableElementArrayBuffer: function() {
721
+ var gl = this.gl;
722
+
723
+ if (this.mGLElementDataBufferWasSetup) {
724
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
725
+ }
726
+ },
727
+
728
+ enableDataBufferWithShader: function(shader) {
729
+ // Vertex Array Object is an expension in WebGL and currently not implemented in Safari
730
+ if (!shader.isActive) {
731
+ shader.activate();
732
+ }
733
+
734
+ for (var i = 0, length = this.mArrayBuffers.length; i < length; i++) {
735
+ var buffer = this.mArrayBuffers[i];
736
+ buffer.enableVertexAttributeArrayBuffersWithShader(shader);
737
+ }
738
+
739
+ this.enableElementArrayBuffer();
740
+
741
+ this._enabledShader = shader;
742
+ this._isEnabled = true;
743
+ },
744
+
745
+ disableDataBufferWithShader: function(shader) {
746
+ if (!this._isEnabled) {
747
+ return;
748
+ }
749
+
750
+ this.disableElementArrayBuffer();
751
+
752
+ for (var i = 0, length = this.mArrayBuffers.length; i < length; i++) {
753
+ var buffer = this.mArrayBuffers[i];
754
+ buffer.disableVertexAttributeArrayBuffersWithShader(shader);
755
+ }
756
+
757
+ this._enabledShader = null;
758
+ this._isEnabled = false;
759
+
760
+ },
761
+
762
+ drawWithShader: function(shader, shouldDeactivateShader) {
763
+ var gl = this.gl;
764
+ var range = {
765
+ location: 0,
766
+ length: this.mElementArrayCount > 0 ? this.mElementArrayCount : this._vertexCount
767
+ };
768
+
769
+ this.enableDataBufferWithShader(shader);
770
+
771
+ if (this.mGLElementDataBufferWasSetup && this.mElementArrayCount > 0) {
772
+ // we need to send element data to element array buffer, e.g. [0, 2, 1, 3]
773
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.mGLElementData, gl.STATIC_DRAW);
774
+
775
+ if (!CGSizeEqualToSize(this.mGLElementMeshSize, CGSizeZero)) {
776
+ // Draw mesh by rows
777
+ var width = this.mGLElementMeshSize.width;
778
+
779
+ for (var y = 0; y < this.mGLElementMeshSize.height - 1; ++y) {
780
+ // location is vertex location, so need to multiply by two to get index location
781
+ gl.drawElements(this.drawMode, width * 2, gl.UNSIGNED_SHORT, 2 * y * width * 2);
782
+ }
783
+ } else {
784
+ // just draw everything
785
+ gl.drawElements(this.drawMode, range.length, gl.UNSIGNED_SHORT, 2 * range.location);
786
+ }
787
+ } else {
788
+ // No element data; just pass vertices straight down
789
+ gl.drawArrays(this.drawMode, range.location, range.length);
790
+ }
791
+
792
+ this.disableDataBufferWithShader(shader);
793
+
794
+ // Swap buffers
795
+ if (this.isDoubleBuffered) {
796
+ this.mCurrentBufferIndex = (this.mCurrentBufferIndex + 1) % 2;
797
+
798
+ for (var i = 0, length = this.mArrayBuffers.length; i < length; i++) {
799
+ var buffer = this.mArrayBuffers[i];
800
+
801
+ if (buffer.bufferCount != 1) {
802
+ buffer.currentBufferIndex = this.mCurrentBufferIndex;
803
+ }
804
+ }
805
+ }
806
+
807
+ if (shouldDeactivateShader) {
808
+ shader.deactivate();
809
+ }
810
+ },
811
+
812
+ vertexAttributeNamed: function(attributeName) {
813
+ for (var attrib in this._vertexAttributes) {
814
+ var attribute = this._vertexAttributes[attrib];
815
+
816
+ if (attribute.name === attributeName) {
817
+ return attribute;
818
+ }
819
+ }
820
+
821
+ return null;
822
+ }
823
+ });
assets/player/gl/TSDGLFrameBuffer.js CHANGED
@@ -1,3 +1,116 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:acf866fde829c8c3c9b847cb8e0d8f36201d10ab157b707edd9491b41ad5654f
3
- size 3660
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TSDGLFrameBuffer.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ var TSDGLFrameBuffer = Class.create({
10
+ initialize: function(gl, size, textureCount) {
11
+ this.gl = gl;
12
+
13
+ // framebuffer size
14
+ this.size = size;
15
+
16
+ // number of framebuffer-attachable texture images
17
+ this.textureCount = textureCount;
18
+
19
+ // current texture index
20
+ this.currentTextureIndex = 0;
21
+
22
+ // create framebuffer-attachable texture images
23
+ this.setupFramebuffer(gl, size, textureCount);
24
+ },
25
+
26
+ setupFramebuffer: function(gl, size, textureCount) {
27
+ // create and bind frame buffer object
28
+ var buffer = this.buffer = gl.createFramebuffer();
29
+
30
+ gl.bindFramebuffer(gl.FRAMEBUFFER, buffer);
31
+
32
+ var textures = this.textures = [];
33
+
34
+ // set up framebuffer texture(s)
35
+ for (var i = 0; i < textureCount; i++) {
36
+ var texture = gl.createTexture();
37
+
38
+ // bind texture
39
+ gl.bindTexture(gl.TEXTURE_2D, texture);
40
+
41
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
42
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
43
+
44
+ // setup texture parameters
45
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
46
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
47
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
48
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
49
+
50
+ // specify the texture size for memory allocation
51
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size.width, size.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
52
+
53
+ // unbind texture
54
+ gl.bindTexture(gl.TEXTURE_2D, null);
55
+
56
+ textures.push(texture);
57
+ }
58
+
59
+ // bind current texture to the framebuffer
60
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[this.currentTextureIndex], 0);
61
+
62
+ // unbind framebuffer
63
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
64
+ },
65
+
66
+ currentGLTexture: function() {
67
+ var texture = this.textures[this.currentTextureIndex];
68
+
69
+ return texture;
70
+ },
71
+
72
+ setCurrentTextureToNext: function() {
73
+ var textureCount = this.textureCount;
74
+
75
+ if (this.textureCount > 0) {
76
+ var currentTextureIndex = this.currentTextureIndex;
77
+ var nextTextureIndex = (currentTextureIndex + 1) % textureCount;
78
+
79
+ this.currentTextureIndex = nextTextureIndex;
80
+
81
+ // bind the framebuffer to the next texture
82
+ this.bindFramebuffer();
83
+ }
84
+ },
85
+
86
+ bindFramebuffer: function() {
87
+ var gl = this.gl;
88
+
89
+ //bind framebuffer
90
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this.buffer);
91
+
92
+ // bind current texture
93
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.textures[this.currentTextureIndex], 0);
94
+ },
95
+
96
+ currentGLFramebuffer: function() {
97
+ var gl = this.gl;
98
+ var framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
99
+
100
+ return framebuffer;
101
+ },
102
+
103
+ unbindFramebufferAndBindGLFramebuffer: function(currentGLFramebuffer) {
104
+ var gl = this.gl;
105
+ gl.bindFramebuffer(gl.FRAMEBUFFER, currentGLFramebuffer);
106
+ }
107
+
108
+ });
109
+
110
+ TSDGLFrameBuffer.currentGLFramebuffer = function(gl) {
111
+ // use getParameter in WebGL as there is no getIntegerv implementation
112
+ var framebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
113
+
114
+ // this will return null if drawing buffer is the display default
115
+ return framebuffer;
116
+ };
assets/player/gl/TSDGLShader.js CHANGED
@@ -1,3 +1,520 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:86412f8c4bd4b24540f8c0cd2e3ed97f914db6da890d0e20af823aa3643fe8c1
3
- size 17763
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TSDGLShader.js
3
+ * Keynote HTML Player
4
+ *
5
+ * Created by Tungwei Cheng
6
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
7
+ */
8
+
9
+ // Uniforms
10
+ var kTSDGLShaderUniformColor = "Color";
11
+ var kTSDGLShaderUniformDuration = "Duration";
12
+ var kTSDGLShaderUniformMotionBlurVector = "MotionBlurVector";
13
+ var kTSDGLShaderUniformMVPMatrix = "MVPMatrix";
14
+ var kTSDGLShaderUniformOpacity = "Opacity";
15
+ var kTSDGLShaderUniformParticleTexture = "ParticleTexture";
16
+ var kTSDGLShaderUniformPercent = "Percent";
17
+ var kTSDGLShaderUniformPreviousMVPMatrix = "PreviousMVPMatrix";
18
+ var kTSDGLShaderUniformTexture = "Texture";
19
+ var kTSDGLShaderUniformTextureMatrix = "TextureMatrix";
20
+ var kTSDGLShaderUniformTextureSize = "TextureSize";
21
+ var kTSDGLShaderUniformTexture2 = "Texture2";
22
+ var kTSDGLShaderUniformTexture2Matrix = "Texture2Matrix";
23
+ var kTSDGLShaderUniformTexture2Size = "Texture2Size";
24
+ var kTSDGLShaderUniformVelocityScale = "VelocityScale";
25
+ var kTSDGLShaderUniformVelocityTexture = "VelocityTexture";
26
+
27
+ // Attributes
28
+ var kTSDGLShaderAttributeCenter = "Center"; // center point of this particle
29
+ var kTSDGLShaderAttributeColor = "Color";
30
+ var kTSDGLShaderAttributeLifeSpan = "LifeSpan";
31
+ var kTSDGLShaderAttributeNormal = "Normal";
32
+ var kTSDGLShaderAttributeParticleTexCoord = "ParticleTexCoord";
33
+ var kTSDGLShaderAttributePosition = "Position";
34
+ var kTSDGLShaderAttributePreviousPosition = "PreviousPosition";
35
+ var kTSDGLShaderAttributeRotation = "Rotation";
36
+ var kTSDGLShaderAttributeScale = "Scale";
37
+ var kTSDGLShaderAttributeSpeed = "Speed";
38
+ var kTSDGLShaderAttributeTexCoord = "TexCoord";
39
+ var kTSDGLShaderUniformRotationMax = "RotationMax";
40
+ var kTSDGLShaderUniformSpeedMax = "SpeedMax";
41
+
42
+ var TSDGLShaderQualifierType = {
43
+ Unknown: 0, ///< ERROR
44
+ Int: 1, // < GLSL type "int"
45
+ Float: 2, // < GLSL type "float"
46
+ Vec2: 3, // < GLSL type "vec2"
47
+ Vec3: 4, // < GLSL type "vec3"
48
+ Vec4: 5, // < GLSL type "vec4"
49
+ Mat3: 6, // < GLSL type "mat3"
50
+ Mat4: 7 // < GLSL type "mat4"
51
+ };
52
+
53
+ function TSDGLShaderQualifierTypeFromGLenum(type) {
54
+ var result = TSDGLShaderQualifierType.Unknown;
55
+
56
+ switch (type) {
57
+ case GL_FLOAT:
58
+ result = TSDGLShaderQualifierType.Float;
59
+ break;
60
+ case GL_FLOAT_VEC2:
61
+ result = TSDGLShaderQualifierType.Vec2;
62
+ break;
63
+ case GL_FLOAT_VEC3:
64
+ result = TSDGLShaderQualifierType.Vec3;
65
+ break;
66
+ case GL_FLOAT_VEC4:
67
+ result = TSDGLShaderQualifierType.Vec4;
68
+ break;
69
+ case GL_BOOL:
70
+ case GL_SAMPLER_2D:
71
+ case GL_INT:
72
+ result = TSDGLShaderQualifierType.Int;
73
+ break;
74
+ case GL_FLOAT_MAT3:
75
+ result = TSDGLShaderQualifierType.Mat3;
76
+ break;
77
+ case GL_FLOAT_MAT4:
78
+ result = TSDGLShaderQualifierType.Mat4;
79
+ break;
80
+
81
+ case GL_INT_VEC2:
82
+ case GL_INT_VEC3:
83
+ case GL_INT_VEC4:
84
+ case GL_BOOL_VEC2:
85
+ case GL_BOOL_VEC3:
86
+ case GL_BOOL_VEC4:
87
+ case GL_FLOAT_MAT2:
88
+ case GL_SAMPLER_CUBE:
89
+ default:
90
+ console.log("Unimplemented GLenum type " + type);
91
+ break;
92
+ }
93
+
94
+ return result;
95
+ }
96
+
97
+ var TSDGLShader = Class.create({
98
+ initialize: function(gl) {
99
+ this.gl = gl;
100
+
101
+ this._uniforms = {};
102
+ this.name = "";
103
+ this.programObject = null;
104
+ this.isActive = false;
105
+
106
+ this._uniformsNeedingUpdate = [];
107
+ },
108
+
109
+ initWithDefaultTextureShader: function() {
110
+ this.initWithShaderFileNames("defaultTexture", "defaultTexture");
111
+ this.setGLint(0, kTSDGLShaderUniformTexture);
112
+ },
113
+
114
+ initWithDefaultTextureAndOpacityShader: function() {
115
+ this.initWithShaderFileNames("defaultTexture", "defaultTextureAndOpacity");
116
+ },
117
+
118
+ initWithDefaultHorizontalBlurShader: function() {
119
+ this.initWithShaderFileNames("horizontalGaussianBlur", "horizontalGaussianBlur");
120
+ this.setGLint(0, kTSDGLShaderUniformTexture);
121
+ },
122
+
123
+ initWithDefaultVerticalBlurShader: function() {
124
+ this.initWithShaderFileNames("verticalGaussianBlur", "verticalGaussianBlur");
125
+ this.setGLint(0, kTSDGLShaderUniformTexture);
126
+ },
127
+
128
+ initWithContentsShader: function() {
129
+ this.initWithShaderFileNames("contents", "contents");
130
+ },
131
+
132
+ initWithShaderFileNames: function(vertexShaderFileName, fragmentShaderFileName) {
133
+ var vertexString = KNWebGLShader[vertexShaderFileName].vertex;
134
+ var fragmentString = KNWebGLShader[fragmentShaderFileName].fragment;
135
+
136
+ this.initWithShaders(vertexString, fragmentString);
137
+ },
138
+
139
+ initWithShaders: function(vertexString, fragmentString) {
140
+ var gl = this.gl;
141
+
142
+ var vertexShader = KNWebGLUtil.loadShader(gl, gl.VERTEX_SHADER, vertexString);
143
+ var fragmentShader = KNWebGLUtil.loadShader(gl, gl.FRAGMENT_SHADER, fragmentString);
144
+
145
+ this.programObject = KNWebGLUtil.createShaderProgram(gl, vertexShader, fragmentShader);
146
+
147
+ this.p_updateUniformsAndAttributesFromShader();
148
+ },
149
+
150
+ p_updateUniformsAndAttributesFromShader: function() {
151
+ var gl = this.gl;
152
+ var programObject = this.programObject;
153
+ var uniformsCount = -1;
154
+
155
+ uniformsCount = gl.getProgramParameter(programObject, gl.ACTIVE_UNIFORMS);
156
+
157
+ for (var i = 0; i < uniformsCount; i++) {
158
+ var activeInfo = gl.getActiveUniform(programObject, i);
159
+ var name = activeInfo.name;
160
+ var type = activeInfo.type;
161
+ var size = activeInfo.size;
162
+
163
+ // Add uniform to cache
164
+ var qualifierType = TSDGLShaderQualifierTypeFromGLenum(type);
165
+ this.shaderQualifierForUniform(name, qualifierType);
166
+ }
167
+
168
+ // Update attributes
169
+ var attributesCount = -1;
170
+
171
+ attributesCount = gl.getProgramParameter(programObject, gl.ACTIVE_ATTRIBUTES);
172
+
173
+ for (var i = 0; i < attributesCount; i++) {
174
+ var activeInfo = gl.getActiveAttrib(programObject, i);
175
+ var name = activeInfo.name;
176
+ var type = activeInfo.type;
177
+ var size = activeInfo.size;
178
+
179
+ // Add attribute location to cache
180
+ this.locationForAttribute(name);
181
+ }
182
+ },
183
+
184
+ shaderQualifierForUniform: function(uniform, qualifierType) {
185
+ var gl = this.gl;
186
+ var qualifier = this._uniforms[uniform];
187
+
188
+ if (!qualifier) {
189
+ switch (qualifierType) {
190
+ case TSDGLShaderQualifierType.Unknown:
191
+ console.log("Unknown Shader Qualifier Type!");
192
+ break;
193
+ case TSDGLShaderQualifierType.Int:
194
+ qualifier = new TSDGLShaderQualifierInt(gl, uniform);
195
+ break;
196
+ case TSDGLShaderQualifierType.Float:
197
+ qualifier = new TSDGLShaderQualifierFloat(gl, uniform);
198
+ break;
199
+ case TSDGLShaderQualifierType.Vec2:
200
+ qualifier = new TSDGLShaderQualifierPoint2D(gl, uniform);
201
+ break;
202
+ case TSDGLShaderQualifierType.Vec3:
203
+ qualifier = new TSDGLShaderQualifierPoint3D(gl, uniform);
204
+ break;
205
+ case TSDGLShaderQualifierType.Vec4:
206
+ qualifier = new TSDGLShaderQualifierPoint4D(gl, uniform);
207
+ break;
208
+ case TSDGLShaderQualifierType.Mat3:
209
+ qualifier = new TSDGLShaderQualifierMat3(gl, uniform);
210
+ break;
211
+ case TSDGLShaderQualifierType.Mat4:
212
+ qualifier = new TSDGLShaderQualifierMat4(gl, uniform);
213
+ break;
214
+ }
215
+
216
+ qualifier.updateUniformLocationWithShaderProgramObject(this.programObject);
217
+ this._uniforms[uniform] = qualifier;
218
+ }
219
+
220
+ return qualifier;
221
+ },
222
+
223
+ setGLint: function(newInt, uniform) {
224
+ var qualifier = this.shaderQualifierForUniform(uniform, TSDGLShaderQualifierType.Int);
225
+
226
+ qualifier.setProposedGLintValue(newInt);
227
+
228
+ if (qualifier._needsUpdate) {
229
+ this._uniformsNeedingUpdate.push(qualifier);
230
+ }
231
+
232
+ this.p_setQualifiersIfNecessary();
233
+ },
234
+
235
+ setGLFloat: function(newFloat, uniform) {
236
+ var qualifier = this.shaderQualifierForUniform(uniform, TSDGLShaderQualifierType.Float);
237
+
238
+ qualifier.setProposedGLfloatValue(newFloat);
239
+
240
+ if (qualifier._needsUpdate) {
241
+ this._uniformsNeedingUpdate.push(qualifier);
242
+ }
243
+
244
+ this.p_setQualifiersIfNecessary();
245
+ },
246
+
247
+ setPoint2D: function(newPoint2D, uniform) {
248
+ var qualifier = this.shaderQualifierForUniform(uniform, TSDGLShaderQualifierType.Vec2);
249
+
250
+ qualifier.setProposedGLPoint2DValue(newPoint2D);
251
+
252
+ if (qualifier._needsUpdate) {
253
+ this._uniformsNeedingUpdate.push(qualifier);
254
+ }
255
+
256
+ this.p_setQualifiersIfNecessary();
257
+ },
258
+
259
+ setMat4WithTransform3D: function(aTransform3D, uniform) {
260
+ var qualifier = this.shaderQualifierForUniform(uniform, TSDGLShaderQualifierType.Mat4);
261
+
262
+ qualifier.setProposedTransform3D(aTransform3D);
263
+
264
+ if (qualifier._needsUpdate) {
265
+ this._uniformsNeedingUpdate.push(qualifier);
266
+ }
267
+
268
+ this.p_setQualifiersIfNecessary();
269
+ },
270
+
271
+ locationForUniform: function(uniform) {
272
+ var location;
273
+ var shaderQualifier = this._uniforms[uniform];
274
+
275
+ if (shaderQualifier) {
276
+ location = shaderQualifier._uniformLocation;
277
+ }
278
+
279
+ if (!location) {
280
+ location = this.gl.getUniformLocation(this.programObject, uniform);
281
+ }
282
+
283
+ return location;
284
+ },
285
+
286
+ locationForAttribute: function(attribute) {
287
+ if (!this._attributeLocations) {
288
+ this._attributeLocations = {};
289
+ }
290
+
291
+ var location = this._attributeLocations[attribute];
292
+
293
+ if (location === undefined) {
294
+ location = -1;
295
+ }
296
+
297
+ if (location < 0) {
298
+ location = this.gl.getAttribLocation(this.programObject, attribute);
299
+ this._attributeLocations[attribute] = location;
300
+ }
301
+
302
+ return location;
303
+ },
304
+
305
+ p_setQualifiersIfNecessary: function() {
306
+ if (!this.isActive) {
307
+ return;
308
+ }
309
+ if (this._uniformsNeedingUpdate.length === 0) {
310
+ return;
311
+ }
312
+
313
+ // Look through all the newly-set qualifiers
314
+ for (var i = 0, length = this._uniformsNeedingUpdate.length; i < length; i++) {
315
+ var proposedQualifier = this._uniformsNeedingUpdate[i];
316
+
317
+ if (proposedQualifier._uniformLocation === -1) {
318
+ proposedQualifier.updateUniformLocationWithShaderProgramObject(this.programObject);
319
+ }
320
+
321
+ proposedQualifier.setGLUniformWithShader(this.gl, this);
322
+ }
323
+
324
+ this._uniformsNeedingUpdate = [];
325
+ },
326
+
327
+ activate: function() {
328
+ var gl = this.gl;
329
+
330
+ if (!this.isActive) {
331
+ gl.useProgram(this.programObject);
332
+ this.isActive = true;
333
+ }
334
+
335
+ this.p_setQualifiersIfNecessary();
336
+ },
337
+
338
+ deactivate: function() {
339
+ if (this.isActive) {
340
+ //gl.useProgram(0);
341
+ this.isActive = false;
342
+ }
343
+ }
344
+
345
+ });
346
+
347
+ var TSDGLShaderQualifier = Class.create({
348
+ initialize: function(gl, qualifierName) {
349
+ this.gl = gl;
350
+ this._uniformLocation = -1;
351
+ this._needsUpdate = true;
352
+ this._name = qualifierName;
353
+ },
354
+
355
+ updateUniformLocationWithShaderProgramObject: function(shaderProgramObject) {
356
+ if (this._uniformLocation === -1) {
357
+ this._uniformLocation = this.gl.getUniformLocation(shaderProgramObject, this._name);
358
+ }
359
+ }
360
+ });
361
+
362
+ var TSDGLShaderQualifierInt = Class.create(TSDGLShaderQualifier, {
363
+ initialize: function($super, gl, qualifierName) {
364
+ this._GLintValue = 0;
365
+ this._proposedGLintValue = 0;
366
+
367
+ $super(gl, qualifierName);
368
+ },
369
+
370
+ setProposedGLintValue: function(proposedGLintValue) {
371
+ if (this._proposedGLintValue !== proposedGLintValue) {
372
+ this._proposedGLintValue = proposedGLintValue;
373
+ this._needsUpdate = true;
374
+ }
375
+ },
376
+
377
+ setGLUniformWithShader: function(gl, shader) {
378
+ gl.uniform1i(this._uniformLocation, this._proposedGLintValue);
379
+ this._GLintValue = this._proposedGLintValue;
380
+ this._needsUpdate = false;
381
+ }
382
+ });
383
+
384
+ var TSDGLShaderQualifierFloat = Class.create(TSDGLShaderQualifier, {
385
+ initialize: function($super, gl, qualifierName) {
386
+ this._GLfloatValue = 0;
387
+ this._proposedGLfloatValue = 0;
388
+
389
+ $super(gl, qualifierName);
390
+ },
391
+
392
+ setProposedGLfloatValue: function(proposedGLfloatValue) {
393
+ if (this._proposedGLfloatValue !== proposedGLfloatValue) {
394
+ this._proposedGLfloatValue = proposedGLfloatValue;
395
+ this._needsUpdate = true;
396
+ }
397
+ },
398
+
399
+ setGLUniformWithShader: function(gl, shader) {
400
+ gl.uniform1f(this._uniformLocation, this._proposedGLfloatValue);
401
+ this._GLfloatValue = this._proposedGLfloatValue;
402
+ this._needsUpdate = false;
403
+ }
404
+ });
405
+
406
+ var TSDGLShaderQualifierPoint2D = Class.create(TSDGLShaderQualifier, {
407
+ initialize: function($super, gl, qualifierName) {
408
+ this._GLPoint2DValue = {};
409
+ this._proposedGLPoint2DValue = {};
410
+
411
+ $super(gl, qualifierName);
412
+ },
413
+
414
+ setProposedGLPoint2DValue: function(proposedGLPoint2DValue) {
415
+ if (!(this._proposedGLPoint2DValue.x === proposedGLPoint2DValue.x && this._proposedGLPoint2DValue.y === proposedGLPoint2DValue.y)) {
416
+ this._proposedGLPoint2DValue = proposedGLPoint2DValue;
417
+ this._needsUpdate = true;
418
+ }
419
+ },
420
+
421
+ setGLUniformWithShader: function(gl, shader) {
422
+ gl.uniform2fv(this._uniformLocation, [this._proposedGLPoint2DValue.x, this._proposedGLPoint2DValue.y]);
423
+ this._GLPoint2DValue = this._proposedGLPoint2DValue;
424
+ this._needsUpdate = false;
425
+ }
426
+ });
427
+
428
+ var TSDGLShaderQualifierPoint3D = Class.create(TSDGLShaderQualifier, {
429
+ initialize: function($super, gl, qualifierName) {
430
+ this._GLPoint3DValue = {};
431
+ this._proposedGLPoint3DValue = {};
432
+
433
+ $super(gl, qualifierName);
434
+ },
435
+
436
+ setProposedGLPoint3DValue: function(proposedGLPoint3DValue) {
437
+ if (!(this._proposedGLPoint3DValue.x === proposedGLPoint3DValue.x && this._proposedGLPoint3DValue.y === proposedGLPoint3DValue.y && this._proposedGLPoint3DValue.z === proposedGLPoint3DValue.z)) {
438
+ this._proposedGLPoint3DValue = proposedGLPoint3DValue;
439
+ this._needsUpdate = true;
440
+ }
441
+ },
442
+
443
+ setGLUniformWithShader: function(gl, shader) {
444
+ gl.uniform3fv(this._uniformLocation, [this._proposedGLPoint3DValue.x, this._proposedGLPoint3DValue.y, this._proposedGLPoint3DValue.z]);
445
+ this._GLPoint3DValue = this._proposedGLPoint3DValue;
446
+ this._needsUpdate = false;
447
+ }
448
+ });
449
+
450
+ var TSDGLShaderQualifierPoint4D = Class.create(TSDGLShaderQualifier, {
451
+ initialize: function($super, gl, qualifierName) {
452
+ this._GLPoint4DValue = {};
453
+ this._proposedGLPoint4DValue = {};
454
+
455
+ $super(gl, qualifierName);
456
+ },
457
+
458
+ setProposedGLPoint4DValue: function(proposedGLPoint4DValue) {
459
+ if (!(this._proposedGLPoint4DValue.x === proposedGLPoint4DValue.x && this._proposedGLPoint4DValue.y === proposedGLPoint4DValue.y && this._proposedGLPoint4DValue.z === proposedGLPoint4DValue.z && this._proposedGLPoint4DValue.w === proposedGLPoint4DValue.w)) {
460
+ this._proposedGLPoint4DValue = proposedGLPoint4DValue;
461
+ this._needsUpdate = true;
462
+ }
463
+ },
464
+
465
+ setGLUniformWithShader: function(gl, shader) {
466
+ gl.uniform4fv(this._uniformLocation, [this._proposedGLPoint4DValue.x, this._proposedGLPoint4DValue.y, this._proposedGLPoint4DValue.z, this._proposedGLPoint4DValue.w]);
467
+ this._GLPoint4DValue = this._proposedGLPoint4DValue;
468
+ this._needsUpdate = false;
469
+ }
470
+ });
471
+
472
+ var TSDGLShaderQualifierMat3 = Class.create(TSDGLShaderQualifier, {
473
+ initialize: function($super, gl, qualifierName) {
474
+ this._affineTransform = new Float32Array(9) ;
475
+ this._proposedAffineTransform = new Float32Array(9);
476
+
477
+ $super(gl, qualifierName);
478
+ },
479
+
480
+ setProposedAffineTransform: function(proposedAffineTransform) {
481
+ if (!CGAffineTransformEqualToTransform(this._proposedAffineTransform, proposedAffineTransform)) {
482
+ this._proposedAffineTransform = proposedAffineTransform;
483
+ this._needsUpdate = true;
484
+ }
485
+ },
486
+
487
+ setGLUniformWithShader: function(gl, shader) {
488
+ var mat = [
489
+ this._proposedAffineTransform.a, this._proposedAffineTransform.b, 0,
490
+ this._proposedAffineTransform.c, this._proposedAffineTransform.d, 0,
491
+ this._proposedAffineTransform.tx, this._proposedAffineTransform.ty, 1
492
+ ];
493
+
494
+ gl.uniformMatrix3fv(this._uniformLocation, false, mat);
495
+ this._affineTransform = this._proposedAffineTransform;
496
+ this._needsUpdate = false;
497
+ }
498
+ });
499
+
500
+ var TSDGLShaderQualifierMat4 = Class.create(TSDGLShaderQualifier, {
501
+ initialize: function($super, gl, qualifierName) {
502
+ this._transform3D = new Float32Array(16);
503
+ this._proposedTransform3D = new Float32Array(16);
504
+
505
+ $super(gl, qualifierName);
506
+ },
507
+
508
+ setProposedTransform3D: function(proposedTransform3D) {
509
+ if (!CATransform3DEqualToTransform(this._proposedTransform3D, proposedTransform3D)) {
510
+ this._proposedTransform3D = proposedTransform3D;
511
+ this._needsUpdate = true;
512
+ }
513
+ },
514
+
515
+ setGLUniformWithShader: function(gl, shader) {
516
+ gl.uniformMatrix4fv(this._uniformLocation, false, this._proposedTransform3D);
517
+ this._transform3D = this._proposedTransform3D;
518
+ this._needsUpdate = false;
519
+ }
520
+ });
assets/player/pdfjs/bcmaps.js CHANGED
The diff for this file is too large to render. See raw diff
 
assets/player/pdfjs/pdf.js CHANGED
The diff for this file is too large to render. See raw diff
 
assets/player/pdfjs/pdf_worker.js CHANGED
The diff for this file is too large to render. See raw diff
 
assets/player/pdfjs/web/compatibility.js CHANGED
@@ -1,3 +1,593 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:1d7d093f5c6b57112514617194614018942d80ab6e0566acc70ab6b53d1c7721
3
- size 18126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Copyright 2012 Mozilla Foundation
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+ /* globals VBArray, PDFJS */
16
+
17
+ 'use strict';
18
+
19
+ // Initializing PDFJS global object here, it case if we need to change/disable
20
+ // some PDF.js features, e.g. range requests
21
+ if (typeof PDFJS === 'undefined') {
22
+ (typeof window !== 'undefined' ? window : this).PDFJS = {};
23
+ }
24
+
25
+ // Checking if the typed arrays are supported
26
+ // Support: iOS<6.0 (subarray), IE<10, Android<4.0
27
+ (function checkTypedArrayCompatibility() {
28
+ if (typeof Uint8Array !== 'undefined') {
29
+ // Support: iOS<6.0
30
+ if (typeof Uint8Array.prototype.subarray === 'undefined') {
31
+ Uint8Array.prototype.subarray = function subarray(start, end) {
32
+ return new Uint8Array(this.slice(start, end));
33
+ };
34
+ Float32Array.prototype.subarray = function subarray(start, end) {
35
+ return new Float32Array(this.slice(start, end));
36
+ };
37
+ }
38
+
39
+ // Support: Android<4.1
40
+ if (typeof Float64Array === 'undefined') {
41
+ window.Float64Array = Float32Array;
42
+ }
43
+ return;
44
+ }
45
+
46
+ function subarray(start, end) {
47
+ return new TypedArray(this.slice(start, end));
48
+ }
49
+
50
+ function setArrayOffset(array, offset) {
51
+ if (arguments.length < 2) {
52
+ offset = 0;
53
+ }
54
+ for (var i = 0, n = array.length; i < n; ++i, ++offset) {
55
+ this[offset] = array[i] & 0xFF;
56
+ }
57
+ }
58
+
59
+ function TypedArray(arg1) {
60
+ var result, i, n;
61
+ if (typeof arg1 === 'number') {
62
+ result = [];
63
+ for (i = 0; i < arg1; ++i) {
64
+ result[i] = 0;
65
+ }
66
+ } else if ('slice' in arg1) {
67
+ result = arg1.slice(0);
68
+ } else {
69
+ result = [];
70
+ for (i = 0, n = arg1.length; i < n; ++i) {
71
+ result[i] = arg1[i];
72
+ }
73
+ }
74
+
75
+ result.subarray = subarray;
76
+ result.buffer = result;
77
+ result.byteLength = result.length;
78
+ result.set = setArrayOffset;
79
+
80
+ if (typeof arg1 === 'object' && arg1.buffer) {
81
+ result.buffer = arg1.buffer;
82
+ }
83
+ return result;
84
+ }
85
+
86
+ window.Uint8Array = TypedArray;
87
+ window.Int8Array = TypedArray;
88
+
89
+ // we don't need support for set, byteLength for 32-bit array
90
+ // so we can use the TypedArray as well
91
+ window.Uint32Array = TypedArray;
92
+ window.Int32Array = TypedArray;
93
+ window.Uint16Array = TypedArray;
94
+ window.Float32Array = TypedArray;
95
+ window.Float64Array = TypedArray;
96
+ })();
97
+
98
+ // URL = URL || webkitURL
99
+ // Support: Safari<7, Android 4.2+
100
+ (function normalizeURLObject() {
101
+ if (!window.URL) {
102
+ window.URL = window.webkitURL;
103
+ }
104
+ })();
105
+
106
+ // Object.defineProperty()?
107
+ // Support: Android<4.0, Safari<5.1
108
+ (function checkObjectDefinePropertyCompatibility() {
109
+ if (typeof Object.defineProperty !== 'undefined') {
110
+ var definePropertyPossible = true;
111
+ try {
112
+ // some browsers (e.g. safari) cannot use defineProperty() on DOM objects
113
+ // and thus the native version is not sufficient
114
+ Object.defineProperty(new Image(), 'id', { value: 'test' });
115
+ // ... another test for android gb browser for non-DOM objects
116
+ var Test = function Test() {};
117
+ Test.prototype = { get id() { } };
118
+ Object.defineProperty(new Test(), 'id',
119
+ { value: '', configurable: true, enumerable: true, writable: false });
120
+ } catch (e) {
121
+ definePropertyPossible = false;
122
+ }
123
+ if (definePropertyPossible) {
124
+ return;
125
+ }
126
+ }
127
+
128
+ Object.defineProperty = function objectDefineProperty(obj, name, def) {
129
+ delete obj[name];
130
+ if ('get' in def) {
131
+ obj.__defineGetter__(name, def['get']);
132
+ }
133
+ if ('set' in def) {
134
+ obj.__defineSetter__(name, def['set']);
135
+ }
136
+ if ('value' in def) {
137
+ obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
138
+ this.__defineGetter__(name, function objectDefinePropertyGetter() {
139
+ return value;
140
+ });
141
+ return value;
142
+ });
143
+ obj[name] = def.value;
144
+ }
145
+ };
146
+ })();
147
+
148
+
149
+ // No XMLHttpRequest#response?
150
+ // Support: IE<11, Android <4.0
151
+ (function checkXMLHttpRequestResponseCompatibility() {
152
+ var xhrPrototype = XMLHttpRequest.prototype;
153
+ var xhr = new XMLHttpRequest();
154
+ if (!('overrideMimeType' in xhr)) {
155
+ // IE10 might have response, but not overrideMimeType
156
+ // Support: IE10
157
+ Object.defineProperty(xhrPrototype, 'overrideMimeType', {
158
+ value: function xmlHttpRequestOverrideMimeType(mimeType) {}
159
+ });
160
+ }
161
+ if ('responseType' in xhr) {
162
+ return;
163
+ }
164
+
165
+ // The worker will be using XHR, so we can save time and disable worker.
166
+ PDFJS.disableWorker = true;
167
+
168
+ Object.defineProperty(xhrPrototype, 'responseType', {
169
+ get: function xmlHttpRequestGetResponseType() {
170
+ return this._responseType || 'text';
171
+ },
172
+ set: function xmlHttpRequestSetResponseType(value) {
173
+ if (value === 'text' || value === 'arraybuffer') {
174
+ this._responseType = value;
175
+ if (value === 'arraybuffer' &&
176
+ typeof this.overrideMimeType === 'function') {
177
+ this.overrideMimeType('text/plain; charset=x-user-defined');
178
+ }
179
+ }
180
+ }
181
+ });
182
+
183
+ // Support: IE9
184
+ if (typeof VBArray !== 'undefined') {
185
+ Object.defineProperty(xhrPrototype, 'response', {
186
+ get: function xmlHttpRequestResponseGet() {
187
+ if (this.responseType === 'arraybuffer') {
188
+ return new Uint8Array(new VBArray(this.responseBody).toArray());
189
+ } else {
190
+ return this.responseText;
191
+ }
192
+ }
193
+ });
194
+ return;
195
+ }
196
+
197
+ Object.defineProperty(xhrPrototype, 'response', {
198
+ get: function xmlHttpRequestResponseGet() {
199
+ if (this.responseType !== 'arraybuffer') {
200
+ return this.responseText;
201
+ }
202
+ var text = this.responseText;
203
+ var i, n = text.length;
204
+ var result = new Uint8Array(n);
205
+ for (i = 0; i < n; ++i) {
206
+ result[i] = text.charCodeAt(i) & 0xFF;
207
+ }
208
+ return result.buffer;
209
+ }
210
+ });
211
+ })();
212
+
213
+ // window.btoa (base64 encode function) ?
214
+ // Support: IE<10
215
+ (function checkWindowBtoaCompatibility() {
216
+ if ('btoa' in window) {
217
+ return;
218
+ }
219
+
220
+ var digits =
221
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
222
+
223
+ window.btoa = function windowBtoa(chars) {
224
+ var buffer = '';
225
+ var i, n;
226
+ for (i = 0, n = chars.length; i < n; i += 3) {
227
+ var b1 = chars.charCodeAt(i) & 0xFF;
228
+ var b2 = chars.charCodeAt(i + 1) & 0xFF;
229
+ var b3 = chars.charCodeAt(i + 2) & 0xFF;
230
+ var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
231
+ var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
232
+ var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
233
+ buffer += (digits.charAt(d1) + digits.charAt(d2) +
234
+ digits.charAt(d3) + digits.charAt(d4));
235
+ }
236
+ return buffer;
237
+ };
238
+ })();
239
+
240
+ // window.atob (base64 encode function)?
241
+ // Support: IE<10
242
+ (function checkWindowAtobCompatibility() {
243
+ if ('atob' in window) {
244
+ return;
245
+ }
246
+
247
+ // https://github.com/davidchambers/Base64.js
248
+ var digits =
249
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
250
+ window.atob = function (input) {
251
+ input = input.replace(/=+$/, '');
252
+ if (input.length % 4 === 1) {
253
+ throw new Error('bad atob input');
254
+ }
255
+ for (
256
+ // initialize result and counters
257
+ var bc = 0, bs, buffer, idx = 0, output = '';
258
+ // get next character
259
+ buffer = input.charAt(idx++);
260
+ // character found in table?
261
+ // initialize bit storage and add its ascii value
262
+ ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
263
+ // and if not first of each 4 characters,
264
+ // convert the first 8 bits to one ascii character
265
+ bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
266
+ ) {
267
+ // try to find character in table (0-63, not found => -1)
268
+ buffer = digits.indexOf(buffer);
269
+ }
270
+ return output;
271
+ };
272
+ })();
273
+
274
+ // Function.prototype.bind?
275
+ // Support: Android<4.0, iOS<6.0
276
+ (function checkFunctionPrototypeBindCompatibility() {
277
+ if (typeof Function.prototype.bind !== 'undefined') {
278
+ return;
279
+ }
280
+
281
+ Function.prototype.bind = function functionPrototypeBind(obj) {
282
+ var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
283
+ var bound = function functionPrototypeBindBound() {
284
+ var args = headArgs.concat(Array.prototype.slice.call(arguments));
285
+ return fn.apply(obj, args);
286
+ };
287
+ return bound;
288
+ };
289
+ })();
290
+
291
+ // HTMLElement dataset property
292
+ // Support: IE<11, Safari<5.1, Android<4.0
293
+ (function checkDatasetProperty() {
294
+ var div = document.createElement('div');
295
+ if ('dataset' in div) {
296
+ return; // dataset property exists
297
+ }
298
+
299
+ Object.defineProperty(HTMLElement.prototype, 'dataset', {
300
+ get: function() {
301
+ if (this._dataset) {
302
+ return this._dataset;
303
+ }
304
+
305
+ var dataset = {};
306
+ for (var j = 0, jj = this.attributes.length; j < jj; j++) {
307
+ var attribute = this.attributes[j];
308
+ if (attribute.name.substring(0, 5) !== 'data-') {
309
+ continue;
310
+ }
311
+ var key = attribute.name.substring(5).replace(/\-([a-z])/g,
312
+ function(all, ch) {
313
+ return ch.toUpperCase();
314
+ });
315
+ dataset[key] = attribute.value;
316
+ }
317
+
318
+ Object.defineProperty(this, '_dataset', {
319
+ value: dataset,
320
+ writable: false,
321
+ enumerable: false
322
+ });
323
+ return dataset;
324
+ },
325
+ enumerable: true
326
+ });
327
+ })();
328
+
329
+ // HTMLElement classList property
330
+ // Support: IE<10, Android<4.0, iOS<5.0
331
+ (function checkClassListProperty() {
332
+ var div = document.createElement('div');
333
+ if ('classList' in div) {
334
+ return; // classList property exists
335
+ }
336
+
337
+ function changeList(element, itemName, add, remove) {
338
+ var s = element.className || '';
339
+ var list = s.split(/\s+/g);
340
+ if (list[0] === '') {
341
+ list.shift();
342
+ }
343
+ var index = list.indexOf(itemName);
344
+ if (index < 0 && add) {
345
+ list.push(itemName);
346
+ }
347
+ if (index >= 0 && remove) {
348
+ list.splice(index, 1);
349
+ }
350
+ element.className = list.join(' ');
351
+ return (index >= 0);
352
+ }
353
+
354
+ var classListPrototype = {
355
+ add: function(name) {
356
+ changeList(this.element, name, true, false);
357
+ },
358
+ contains: function(name) {
359
+ return changeList(this.element, name, false, false);
360
+ },
361
+ remove: function(name) {
362
+ changeList(this.element, name, false, true);
363
+ },
364
+ toggle: function(name) {
365
+ changeList(this.element, name, true, true);
366
+ }
367
+ };
368
+
369
+ Object.defineProperty(HTMLElement.prototype, 'classList', {
370
+ get: function() {
371
+ if (this._classList) {
372
+ return this._classList;
373
+ }
374
+
375
+ var classList = Object.create(classListPrototype, {
376
+ element: {
377
+ value: this,
378
+ writable: false,
379
+ enumerable: true
380
+ }
381
+ });
382
+ Object.defineProperty(this, '_classList', {
383
+ value: classList,
384
+ writable: false,
385
+ enumerable: false
386
+ });
387
+ return classList;
388
+ },
389
+ enumerable: true
390
+ });
391
+ })();
392
+
393
+ // Check console compatibility
394
+ // In older IE versions the console object is not available
395
+ // unless console is open.
396
+ // Support: IE<10
397
+ (function checkConsoleCompatibility() {
398
+ if (!('console' in window)) {
399
+ window.console = {
400
+ log: function() {},
401
+ error: function() {},
402
+ warn: function() {}
403
+ };
404
+ } else if (!('bind' in console.log)) {
405
+ // native functions in IE9 might not have bind
406
+ console.log = (function(fn) {
407
+ return function(msg) { return fn(msg); };
408
+ })(console.log);
409
+ console.error = (function(fn) {
410
+ return function(msg) { return fn(msg); };
411
+ })(console.error);
412
+ console.warn = (function(fn) {
413
+ return function(msg) { return fn(msg); };
414
+ })(console.warn);
415
+ }
416
+ })();
417
+
418
+ // Check onclick compatibility in Opera
419
+ // Support: Opera<15
420
+ (function checkOnClickCompatibility() {
421
+ // workaround for reported Opera bug DSK-354448:
422
+ // onclick fires on disabled buttons with opaque content
423
+ function ignoreIfTargetDisabled(event) {
424
+ if (isDisabled(event.target)) {
425
+ event.stopPropagation();
426
+ }
427
+ }
428
+ function isDisabled(node) {
429
+ return node.disabled || (node.parentNode && isDisabled(node.parentNode));
430
+ }
431
+ if (navigator.userAgent.indexOf('Opera') !== -1) {
432
+ // use browser detection since we cannot feature-check this bug
433
+ document.addEventListener('click', ignoreIfTargetDisabled, true);
434
+ }
435
+ })();
436
+
437
+ // Checks if possible to use URL.createObjectURL()
438
+ // Support: IE
439
+ (function checkOnBlobSupport() {
440
+ // sometimes IE loosing the data created with createObjectURL(), see #3977
441
+ if (navigator.userAgent.indexOf('Trident') >= 0) {
442
+ PDFJS.disableCreateObjectURL = true;
443
+ }
444
+ })();
445
+
446
+ // Checks if navigator.language is supported
447
+ (function checkNavigatorLanguage() {
448
+ if ('language' in navigator) {
449
+ return;
450
+ }
451
+ PDFJS.locale = navigator.userLanguage || 'en-US';
452
+ })();
453
+
454
+ (function checkRangeRequests() {
455
+ // Safari has issues with cached range requests see:
456
+ // https://github.com/mozilla/pdf.js/issues/3260
457
+ // Last tested with version 6.0.4.
458
+ // Support: Safari 6.0+
459
+ var isSafari = Object.prototype.toString.call(
460
+ window.HTMLElement).indexOf('Constructor') > 0;
461
+
462
+ // Older versions of Android (pre 3.0) has issues with range requests, see:
463
+ // https://github.com/mozilla/pdf.js/issues/3381.
464
+ // Make sure that we only match webkit-based Android browsers,
465
+ // since Firefox/Fennec works as expected.
466
+ // Support: Android<3.0
467
+ var regex = /Android\s[0-2][^\d]/;
468
+ var isOldAndroid = regex.test(navigator.userAgent);
469
+
470
+ // Range requests are broken in Chrome 39 and 40, https://crbug.com/442318
471
+ var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent);
472
+
473
+ if (isSafari || isOldAndroid || isChromeWithRangeBug) {
474
+ PDFJS.disableRange = true;
475
+ PDFJS.disableStream = true;
476
+ }
477
+ })();
478
+
479
+ // Check if the browser supports manipulation of the history.
480
+ // Support: IE<10, Android<4.2
481
+ (function checkHistoryManipulation() {
482
+ // Android 2.x has so buggy pushState support that it was removed in
483
+ // Android 3.0 and restored as late as in Android 4.2.
484
+ // Support: Android 2.x
485
+ if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) {
486
+ PDFJS.disableHistory = true;
487
+ }
488
+ })();
489
+
490
+ // Support: IE<11, Chrome<21, Android<4.4, Safari<6
491
+ (function checkSetPresenceInImageData() {
492
+ // IE < 11 will use window.CanvasPixelArray which lacks set function.
493
+ if (window.CanvasPixelArray) {
494
+ if (typeof window.CanvasPixelArray.prototype.set !== 'function') {
495
+ window.CanvasPixelArray.prototype.set = function(arr) {
496
+ for (var i = 0, ii = this.length; i < ii; i++) {
497
+ this[i] = arr[i];
498
+ }
499
+ };
500
+ }
501
+ } else {
502
+ // Old Chrome and Android use an inaccessible CanvasPixelArray prototype.
503
+ // Because we cannot feature detect it, we rely on user agent parsing.
504
+ var polyfill = false, versionMatch;
505
+ if (navigator.userAgent.indexOf('Chrom') >= 0) {
506
+ versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
507
+ // Chrome < 21 lacks the set function.
508
+ polyfill = versionMatch && parseInt(versionMatch[2]) < 21;
509
+ } else if (navigator.userAgent.indexOf('Android') >= 0) {
510
+ // Android < 4.4 lacks the set function.
511
+ // Android >= 4.4 will contain Chrome in the user agent,
512
+ // thus pass the Chrome check above and not reach this block.
513
+ polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent);
514
+ } else if (navigator.userAgent.indexOf('Safari') >= 0) {
515
+ versionMatch = navigator.userAgent.
516
+ match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//);
517
+ // Safari < 6 lacks the set function.
518
+ polyfill = versionMatch && parseInt(versionMatch[1]) < 6;
519
+ }
520
+
521
+ if (polyfill) {
522
+ var contextPrototype = window.CanvasRenderingContext2D.prototype;
523
+ var createImageData = contextPrototype.createImageData;
524
+ contextPrototype.createImageData = function(w, h) {
525
+ var imageData = createImageData.call(this, w, h);
526
+ imageData.data.set = function(arr) {
527
+ for (var i = 0, ii = this.length; i < ii; i++) {
528
+ this[i] = arr[i];
529
+ }
530
+ };
531
+ return imageData;
532
+ };
533
+ // this closure will be kept referenced, so clear its vars
534
+ contextPrototype = null;
535
+ }
536
+ }
537
+ })();
538
+
539
+ // Support: IE<10, Android<4.0, iOS
540
+ (function checkRequestAnimationFrame() {
541
+ function fakeRequestAnimationFrame(callback) {
542
+ window.setTimeout(callback, 20);
543
+ }
544
+
545
+ var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
546
+ if (isIOS) {
547
+ // requestAnimationFrame on iOS is broken, replacing with fake one.
548
+ window.requestAnimationFrame = fakeRequestAnimationFrame;
549
+ return;
550
+ }
551
+ if ('requestAnimationFrame' in window) {
552
+ return;
553
+ }
554
+ window.requestAnimationFrame =
555
+ window.mozRequestAnimationFrame ||
556
+ window.webkitRequestAnimationFrame ||
557
+ fakeRequestAnimationFrame;
558
+ })();
559
+
560
+ (function checkCanvasSizeLimitation() {
561
+ var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
562
+ var isAndroid = /Android/g.test(navigator.userAgent);
563
+ if (isIOS || isAndroid) {
564
+ // 5MP
565
+ PDFJS.maxCanvasPixels = 5242880;
566
+ }
567
+ })();
568
+
569
+ // Disable fullscreen support for certain problematic configurations.
570
+ // Support: IE11+ (when embedded).
571
+ (function checkFullscreenSupport() {
572
+ var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 &&
573
+ window.parent !== window);
574
+ if (isEmbeddedIE) {
575
+ PDFJS.disableFullscreen = true;
576
+ }
577
+ })();
578
+
579
+ // Provides document.currentScript support
580
+ // Support: IE, Chrome<29.
581
+ (function checkCurrentScript() {
582
+ if ('currentScript' in document) {
583
+ return;
584
+ }
585
+ Object.defineProperty(document, 'currentScript', {
586
+ get: function () {
587
+ var scripts = document.getElementsByTagName('script');
588
+ return scripts[scripts.length - 1];
589
+ },
590
+ enumerable: true,
591
+ configurable: true
592
+ });
593
+ })();
assets/player/prototype.js CHANGED
The diff for this file is too large to render. See raw diff
 
assets/player/string.js CHANGED
@@ -1,3 +1,220 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:65eb706a354740aa2ccac3a879db735667b01766e60f6d9a6327b94faa1327c0
3
- size 7178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var SC = SC || {},
2
+ CoreDocs = CoreDocs || {},
3
+ NO = false,
4
+ YES = true;
5
+
6
+ // ==========================================================================
7
+ // This is copied from CoreDocs to facilitate automatically generating Strings.js files.
8
+ // ==========================================================================
9
+
10
+ CoreDocs.loc = function(input, comment) {
11
+ if (comment === undefined)
12
+ {
13
+ CoreDocs.error("\"" + input + "\" needs a comment to be picked up for loc.");
14
+ }
15
+
16
+ // When we call SproutCore's loc(), it will replace all %@ parameters, and there is no way to escape them.
17
+ // In the future, we should get an escaping method into SC, and/or take advantage of their loc's string replacement.
18
+ // For now, we use @@ instead of %@ as a preliminary parameter marker.
19
+ input = input.loc();
20
+ input = input.replace(/@@/g, "%@");
21
+ return input;
22
+ }
23
+
24
+ // ==========================================================================
25
+ // This is the necessary subset of sproutcore strings for use in localization.
26
+ // ==========================================================================
27
+
28
+ // ==========================================================================
29
+ // SproutCore -- JavaScript Application Framework
30
+ // copyright 2006-2008, Sprout Systems, Inc. and contributors.
31
+ // ==========================================================================
32
+
33
+ // These are basic enhancements to the string class used throughout
34
+ // SproutCore.
35
+
36
+ /**
37
+ @namespace
38
+
39
+ SproutCore implements a variety of enhancements to the built-in String
40
+ object that make it easy to perform common substitutions and conversions.
41
+
42
+ Most of the utility methods defined here mirror those found in Prototype
43
+ 1.6.
44
+
45
+ @since SproutCore 1.0
46
+ */
47
+ SC.String = {
48
+
49
+ // Interpolate string. looks for %@ or %@1; to control the order of params.
50
+ /**
51
+ Apply formatting options to the string. This will look for occurrences
52
+ of %@ in your string and substitute them with the arguments you pass into
53
+ this method. If you want to control the specific order of replacement,
54
+ you can add a number after the key as well to indicate which argument
55
+ you want to insert.
56
+
57
+ Ordered insertions are most useful when building loc strings where values
58
+ you need to insert may appear in different orders.
59
+
60
+ h3. Examples
61
+
62
+ {{{
63
+ "Hello %@ %@".fmt('John', 'Doe') => "Hello John Doe"
64
+ "Hello %@2, %@1".fmt('John', 'Doe') => "Hello Doe, John"
65
+ }}}
66
+
67
+ @param args {Object...} optional arguments
68
+ @returns {String} formatted string
69
+ */
70
+ fmt: function() {
71
+ // first, replace any ORDERED replacements.
72
+ var str = this.gsub(/%@([0-9]+)/, function(m) {
73
+ return (arguments[parseInt(m[1],0)-1] || '').toString();
74
+ }) ;
75
+
76
+ // now, replace any remaining %@ items. Use this indexOf() method b/c
77
+ // it is faster than split().
78
+ var ret = [] ;
79
+ var idx = -1 ;
80
+ var loc = 0 ;
81
+ var argIdx = 0;
82
+ while((idx = str.indexOf("%@",loc)) >= 0) {
83
+ // slice off initial part of string and push into ret. update loc.
84
+ ret.push(str.slice(loc,idx)) ;
85
+ loc = idx + 2 ; // 2 to skip '%@'.
86
+
87
+ // add in replacement.
88
+ var value = arguments[argIdx++] ;
89
+ if (value && value.toString) value = value.toString() ;
90
+ ret.push(value) ;
91
+ }
92
+
93
+ // include any remaining bits of the string.
94
+ if (loc < str.length) {
95
+ ret.push(str.slice(loc,str.length)) ;
96
+ }
97
+
98
+ // join return value.
99
+ return (ret.length > 1) ? ret.join('') : ret[0] ;
100
+ },
101
+
102
+ /**
103
+ Localizes the string. This will look up the reciever string as a key
104
+ in the current Strings hash. If the key matches, the loc'd value will be
105
+ used. The resulting string will also be passed through fmt() to insert
106
+ any variables.
107
+
108
+ @param args {Object...} optional arguments to interpolate also
109
+ @returns {String} the localized and formatted string.
110
+ */
111
+ loc: function() {
112
+ // NB: This could be implemented as a wrapper to locWithDefault() but
113
+ // it would add some overhead to deal with the arguments and adds stack
114
+ // frames, so we are keeping the implementation separate.
115
+
116
+ var kit = String[String.currentLanguage()];
117
+ var str = kit[this] ;
118
+ if (!str) str = String.English[this] || this ;
119
+ return str.fmt.apply(str,arguments) ;
120
+ }
121
+ } ;
122
+
123
+ // Apply SC.String mixin to built-in String object
124
+ for (var key in SC.String) {
125
+ String.prototype[key] = SC.String[key];
126
+ }
127
+
128
+ // Add strings for various languages to this collection. String.loc()
129
+ // method will try to localize the string passed using the current language.
130
+ // if the language is not available, it will use English.
131
+ Object.extend(String,
132
+ /** @scope String @static */ {
133
+
134
+ /**
135
+ The current browser language as a two letter code.
136
+ */
137
+ browserLanguage: ((navigator.language || navigator.browserLanguage).split('-', 1)[0]),
138
+
139
+ /**
140
+ If YES, localization will favor the detected language instead of the
141
+ preferred one.
142
+ */
143
+ useAutodetectedLanguage: NO,
144
+
145
+ /**
146
+ This property is set by the build tools to the current build language.
147
+ */
148
+ preferredLanguage: null,
149
+
150
+ /**
151
+ Returns the hash key to use for loc strings. The default implementation
152
+ will autodetect the browser language and look for a loc string to
153
+ match. If it can't find one then it will introspect to find loc strings
154
+ that are defined and use those instead.
155
+ */
156
+ currentLanguage: function () {
157
+ var ret = (this.useAutodetectedLanguage) ? (this.browserLanguage || this.preferredLanguage || 'en') : (this.preferredLanguage || this.browserLanguage || 'en') ;
158
+
159
+ // then try a couple of normalized forms...
160
+ if (!this[ret]) ret = this.normalizedLanguage(ret);
161
+ return ret ;
162
+ },
163
+
164
+ /**
165
+ Returns a normalized language string for the two letter country code.
166
+ */
167
+ normalizedLanguage: function(ret) {
168
+ switch(ret) {
169
+ case 'fr':
170
+ ret = 'French';
171
+ break ;
172
+ case 'de':
173
+ ret = 'German';
174
+ break ;
175
+ case 'ja':
176
+ case 'jp':
177
+ ret = 'Japanese';
178
+ break ;
179
+ case 'en':
180
+ ret = 'English' ;
181
+ break ;
182
+
183
+ case 'es':
184
+ ret = 'Spanish' ;
185
+ break;
186
+
187
+ default:
188
+ ret = "English";
189
+ break ;
190
+ }
191
+ return ret;
192
+ },
193
+
194
+ /**
195
+ Adds loc strings for the named language. This method takes care of
196
+ creating the localized string hash if it does not already exist.
197
+ The language can be one of the following or any two-letter country code.
198
+
199
+ English, French, German, Japanese, Spanish
200
+
201
+ @param language {String} the language code
202
+ @param strings {Hash} hash of loc strings.
203
+ @returns {this}
204
+ */
205
+ addStringsFor: function(language, strings) {
206
+ // convert language to a normalized name...
207
+ language = String.normalizedLanguage(language) ;
208
+ if (!String[language]) String[language] = {} ;
209
+ Object.extend(String[language], strings || {});
210
+ return this;
211
+ }
212
+
213
+ });
214
+
215
+ String.English = String.English || {};
216
+ String.French = String.French || {};
217
+ String.German = String.German || {};
218
+ String.Japanese = String.Japanese || {};
219
+ String.Spanish = String.Spanish || {};
220
+