1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * @ignore
 29  */
 30 cc.Touches = [];
 31 cc.TouchesIntergerDict = {};
 32 
 33 /**
 34  * @namespace cc.view is the shared view object.
 35  * @name cc.view
 36  */
 37 cc.EGLView = cc.Class.extend(/** @lends cc.view# */{
 38     _delegate: null,
 39     // Size of parent node that contains cc.container and cc._canvas
 40     _frameSize: null,
 41     // resolution size, it is the size appropriate for the app resources.
 42     _designResolutionSize: null,
 43     _originalDesignResolutionSize: null,
 44     // Viewport is the container's rect related to content's coordinates in pixel
 45     _viewPortRect: null,
 46     // The visible rect in content's coordinate in point
 47     _visibleRect: null,
 48 	_retinaEnabled: false,
 49     // The device's pixel ratio (for retina displays)
 50     _devicePixelRatio: 1,
 51     // the view name
 52     _viewName: "",
 53     // Custom callback for resize event
 54     _resizeCallback: null,
 55     _scaleX: 1,
 56     _originalScaleX: 1,
 57     _scaleY: 1,
 58     _originalScaleY: 1,
 59     _indexBitsUsed: 0,
 60     _maxTouches: 5,
 61     _resolutionPolicy: null,
 62     _rpExactFit: null,
 63     _rpShowAll: null,
 64     _rpNoBorder: null,
 65     _rpFixedHeight: null,
 66     _rpFixedWidth: null,
 67     _initialized: false,
 68 
 69     _captured: false,
 70     _wnd: null,
 71     _hDC: null,
 72     _hRC: null,
 73     _supportTouch: false,
 74     _contentTranslateLeftTop: null,
 75 
 76     // Parent node that contains cc.container and cc._canvas
 77     _frame: null,
 78     _frameZoomFactor: 1.0,
 79     __resizeWithBrowserSize: false,
 80     _isAdjustViewPort: true,
 81 
 82     ctor: function () {
 83         this._frame = (cc.container.parentNode === document.body) ? document.documentElement : cc.container.parentNode;
 84         this._frameSize = cc.size(0, 0);
 85         this._initFrameSize();
 86 
 87         var w = cc._canvas.width, h = cc._canvas.height;
 88         this._designResolutionSize = cc.size(w, h);
 89         this._originalDesignResolutionSize = cc.size(w, h);
 90         this._viewPortRect = cc.rect(0, 0, w, h);
 91         this._visibleRect = cc.rect(0, 0, w, h);
 92         this._contentTranslateLeftTop = {left: 0, top: 0};
 93         this._viewName = "Cocos2dHTML5";
 94 
 95 	    var sys = cc.sys;
 96 	    this.enableRetina(sys.os == sys.OS_IOS || sys.os == sys.OS_OSX);
 97 
 98         cc.visibleRect.init(this._designResolutionSize);
 99 
100         // Setup system default resolution policies
101         this._rpExactFit = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.EXACT_FIT);
102         this._rpShowAll = new cc.ResolutionPolicy(cc.ContainerStrategy.PROPORTION_TO_FRAME, cc.ContentStrategy.SHOW_ALL);
103         this._rpNoBorder = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.NO_BORDER);
104         this._rpFixedHeight = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.FIXED_HEIGHT);
105         this._rpFixedWidth = new cc.ResolutionPolicy(cc.ContainerStrategy.EQUAL_TO_FRAME, cc.ContentStrategy.FIXED_WIDTH);
106 
107         this._hDC = cc._canvas;
108         this._hRC = cc._renderContext;
109     },
110 
111     // Resize helper functions
112     _resizeEvent: function () {
113         var width = this._originalDesignResolutionSize.width;
114         var height = this._originalDesignResolutionSize.height;
115         if (this._resizeCallback) {
116             this._initFrameSize();
117             this._resizeCallback.call();
118         }
119         if (width > 0)
120             this.setDesignResolutionSize(width, height, this._resolutionPolicy);
121     },
122 
123     resizeWithBrowserSize: function (enabled) {
124         var adjustSize;
125         if (enabled) {
126             //enable
127             if (!this.__resizeWithBrowserSize) {
128                 this.__resizeWithBrowserSize = true;
129                 adjustSize = this._resizeEvent.bind(this);
130                 window.addEventListener('resize', adjustSize, false);
131             }
132         } else {
133             //disable
134             if (this.__resizeWithBrowserSize) {
135                 this.__resizeWithBrowserSize = true;
136                 adjustSize = this._resizeEvent.bind(this);
137                 window.removeEventListener('resize', adjustSize, false);
138             }
139         }
140     },
141 
142     setResizeCallback: function (callback) {
143         if (typeof callback == "function" || callback == null) {
144             this._resizeCallback = callback;
145         }
146     },
147 
148     _initFrameSize: function () {
149         var locFrameSize = this._frameSize;
150         locFrameSize.width = this._frame.clientWidth;
151         locFrameSize.height = this._frame.clientHeight;
152     },
153 
154     // hack
155     _adjustSizeKeepCanvasSize: function (width, height) {
156         var designWidth = this._originalDesignResolutionSize.width;
157         var designHeight = this._originalDesignResolutionSize.height;
158         if (designWidth > 0)
159             this.setDesignResolutionSize(designWidth, designHeight, this._resolutionPolicy);
160     },
161 
162     _setViewPortMeta: function (width, height) {
163         if (this._isAdjustViewPort) {
164 	        var viewportMetas = {"user-scalable": "no", "maximum-scale": "1.0", "initial-scale": "1.0"}, elems = document.getElementsByName("viewport"), vp, content;
165             if (elems.length == 0) {
166                 vp = document.createElement("meta");
167                 vp.name = "viewport";
168                 vp.content = "";
169                 document.head.appendChild(vp);
170             }
171             else vp = elems[0];
172 
173 	        // For avoiding Android Firefox issue, to remove once firefox fixes its issue.
174 	        if (cc.sys.isMobile && cc.sys.browserType == cc.sys.BROWSER_TYPE_FIREFOX) {
175 		        vp.content = "initial-scale:1";
176 		        return;
177 	        }
178 
179             content = vp.content;
180             for (var key in viewportMetas) {
181                 var pattern = new RegExp(key);
182                 if (!pattern.test(content)) {
183                     content += (content == "" ? "" : ",") + key + "=" + viewportMetas[key];
184                 }
185             }
186             /*
187             if(width<=320){
188                 width = 321;
189             }
190             if(height)
191                 content ="height="+height+","+content;
192             if(width)
193                 content ="width="+width+","+content;
194             */
195             vp.content = content;
196         }
197     },
198 
199     // RenderTexture hacker
200     _setScaleXYForRenderTexture: function () {
201         //hack for RenderTexture on canvas mode when adapting multiple resolution resources
202         var scaleFactor = cc.CONTENT_SCALE_FACTOR();
203         this._scaleX = scaleFactor;
204         this._scaleY = scaleFactor;
205     },
206 
207     // Other helper functions
208     _resetScale: function () {
209         this._scaleX = this._originalScaleX;
210         this._scaleY = this._originalScaleY;
211     },
212 
213     // Useless, just make sure the compatibility temporarily, should be removed
214     _adjustSizeToBrowser: function () {
215     },
216 
217     /**
218      * init
219      */
220     initialize: function () {
221         this._initialized = true;
222     },
223 
224     adjustViewPort: function (enabled) {
225         this._isAdjustViewPort = enabled;
226     },
227 
228 	/**
229 	 * Retina support is enabled by default for Apple device but disabled for other devices,
230 	 * it takes effect only when you called setDesignResolutionPolicy
231 	 * @param {Boolean} enabled  Enable or disable retina display
232 	 */
233 	enableRetina: function(enabled) {
234 		this._retinaEnabled = enabled ? true : false;
235 	},
236 
237 	/**
238 	 * Check whether retina display is enabled.
239 	 * @return {Boolean}
240 	 */
241 	isRetinaEnabled: function() {
242 		return this._retinaEnabled;
243 	},
244 
245     /**
246      * Force destroying EGL view, subclass must implement this method.
247      */
248     end: function () {
249     },
250 
251     /**
252      * Get whether render system is ready(no matter opengl or canvas),
253      * this name is for the compatibility with cocos2d-x, subclass must implement this method.
254      * @return {Boolean}
255      */
256     isOpenGLReady: function () {
257         return (this._hDC != null && this._hRC != null);
258     },
259 
260     /*
261      * Set zoom factor for frame. This method is for debugging big resolution (e.g.new ipad) app on desktop.
262      * @param {Number} zoomFactor
263      */
264     setFrameZoomFactor: function (zoomFactor) {
265         this._frameZoomFactor = zoomFactor;
266         this.centerWindow();
267         cc.director.setProjection(cc.director.getProjection());
268     },
269 
270     /**
271      * Exchanges the front and back buffers, subclass must implement this method.
272      */
273     swapBuffers: function () {
274     },
275 
276     /**
277      * Open or close IME keyboard , subclass must implement this method.
278      */
279     setIMEKeyboardState: function (isOpen) {
280         if (isOpen) {
281             // [EAGLView sharedEGLView] becomeFirstResponder
282         } else {
283             //  [EAGLView sharedEGLView] resignFirstResponder
284         }
285     },
286 
287     /**
288      * <p>
289      *   The resolution translate on EGLView
290      * </p>
291      * @param {Number} offsetLeft
292      * @param {Number} offsetTop
293      */
294     setContentTranslateLeftTop: function (offsetLeft, offsetTop) {
295         this._contentTranslateLeftTop = {left: offsetLeft, top: offsetTop};
296     },
297 
298     /**
299      * <p>
300      *   get the resolution translate on EGLView
301      * </p>
302      * @return {cc.Size|Object}
303      */
304     getContentTranslateLeftTop: function () {
305         return this._contentTranslateLeftTop;
306     },
307 
308     /**
309      * Get the frame size of EGL view.
310      * In general, it returns the screen size since the EGL view is a fullscreen view.
311      * @return {cc.Size}
312      */
313     getFrameSize: function () {
314         return cc.size(this._frameSize.width, this._frameSize.height);
315     },
316 
317     /**
318      * Set the frame size of EGL view.
319      * @param {Number} width
320      * @param {Number} height
321      */
322     setFrameSize: function (width, height) {
323         this._frameSize.width = width;
324         this._frameSize.height = height;
325         this._frame.style.width = width + "px";
326         this._frame.style.height = height + "px";
327         //this.centerWindow();
328         this._resizeEvent();
329         cc.director.setProjection(cc.director.getProjection());
330     },
331 
332     centerWindow: function () {
333     },
334 
335     /**
336      * Get the visible area size of OpenGL view port.
337      * @return {cc.Size}
338      */
339     getVisibleSize: function () {
340         return cc.size(this._visibleRect.width,this._visibleRect.height);
341     },
342 
343     /**
344      * Get the visible origin of OpenGL view port.
345      * @return {cc.Point}
346      */
347     getVisibleOrigin: function () {
348         return cc.p(this._visibleRect.x,this._visibleRect.y);
349     },
350 
351     canSetContentScaleFactor: function () {
352         return true;
353     },
354 
355     /**
356      * Get the current resolution policy
357      * @return {cc.ResolutionPolicy}
358      */
359     getResolutionPolicy: function () {
360         return this._resolutionPolicy;
361     },
362 
363     /**
364      * Set the current resolution policy
365      * @param {cc.ResolutionPolicy|Number} resolutionPolicy
366      */
367     setResolutionPolicy: function (resolutionPolicy) {
368         if (resolutionPolicy instanceof cc.ResolutionPolicy) {
369             this._resolutionPolicy = resolutionPolicy;
370         }
371         // Ensure compatibility with JSB
372         else {
373             switch (resolutionPolicy) {
374                 case cc.ResolutionPolicy.EXACT_FIT:
375                     this._resolutionPolicy = this._rpExactFit;
376                     break;
377                 case cc.ResolutionPolicy.SHOW_ALL:
378                     this._resolutionPolicy = this._rpShowAll;
379                     break;
380                 case cc.ResolutionPolicy.NO_BORDER:
381                     this._resolutionPolicy = this._rpNoBorder;
382                     break;
383                 case cc.ResolutionPolicy.FIXED_HEIGHT:
384                     this._resolutionPolicy = this._rpFixedHeight;
385                     break;
386                 case cc.ResolutionPolicy.FIXED_WIDTH:
387                     this._resolutionPolicy = this._rpFixedWidth;
388                     break;
389             }
390         }
391     },
392 
393     /**
394      * Set the design resolution size.
395      * @param {Number} width Design resolution width.
396      * @param {Number} height Design resolution height.
397      * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired, you may choose:
398      * [1] ResolutionExactFit       Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio, your game view will be stretched.
399      * [2] ResolutionNoBorder       Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two areas of your game view will be cut.
400      * [3] ResolutionShowAll        Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two black borders will be shown.
401      * [4] ResolutionFixedHeight    Scale the content's height to screen's height and proportionally scale its width
402      * [5] ResolutionFixedWidth     Scale the content's width to screen's width and proportionally scale its height
403      * [cc.ResolutionPolicy]        Custom resolution policy, constructed by cc.ResolutionPolicy
404      */
405     setDesignResolutionSize: function (width, height, resolutionPolicy) {
406         // Defensive code
407         if (isNaN(width) || width == 0 || isNaN(height) || height == 0) {
408             cc.log("Resolution not valid");
409             return;
410         }
411         this.setResolutionPolicy(resolutionPolicy);
412         var policy = this._resolutionPolicy;
413         if (policy)
414             policy.preApply(this);
415         else {
416             cc.log("should set resolutionPolicy");
417             return;
418         }
419 
420         // Reinit frame size
421         var frameW = this._frameSize.width, frameH = this._frameSize.height;
422         if (cc.sys.isMobile)
423             this._setViewPortMeta(this._frameSize.width, this._frameSize.height);
424         this._initFrameSize();
425         // No change
426         if (resolutionPolicy == this._resolutionPolicy
427             && width == this._originalDesignResolutionSize.width && height == this._originalDesignResolutionSize.height
428             && frameW == this._frameSize.width && frameH == this._frameSize.height)
429             return;
430         this._designResolutionSize = cc.size(width, height);
431         this._originalDesignResolutionSize = cc.size(width, height);
432 
433         var result = policy.apply(this, this._designResolutionSize);
434         if (result.scale && result.scale.length == 2) {
435             this._scaleX = result.scale[0];
436             this._scaleY = result.scale[1];
437         }
438         if (result.viewport) {
439             var vp = this._viewPortRect = result.viewport, visible = this._visibleRect;
440             visible.width = cc._canvas.width / this._scaleX;
441             visible.height = cc._canvas.height / this._scaleY;
442             visible.x = -vp.x / this._scaleX;
443             visible.y = -vp.y / this._scaleY;
444         }
445 
446         // reset director's member variables to fit visible rect
447         var director = cc.director;
448         director._winSizeInPoints = this.getDesignResolutionSize();
449 
450         policy.postApply(this);
451 
452         if (cc._renderType == cc._RENDER_TYPE_WEBGL) {
453             // reset director's member variables to fit visible rect
454             director._createStatsLabel();
455             director.setGLDefaultValues();
456         }
457 
458         this._originalScaleX = this._scaleX;
459         this._originalScaleY = this._scaleY;
460         // For editbox
461         if (cc.DOM) {
462             cc.DOM._resetEGLViewDiv();
463         }
464 
465         cc.visibleRect.init(this.getVisibleSize());
466     },
467 
468     /**
469      * Get design resolution size.
470      * Default resolution size is the same as 'getFrameSize'.
471      * @return {cc.Size}
472      */
473     getDesignResolutionSize: function () {
474         return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
475     },
476 
477     /**
478      * Set opengl view port rectangle with points.
479      * @param {Number} x
480      * @param {Number} y
481      * @param {Number} w width
482      * @param {Number} h height
483      */
484     setViewPortInPoints: function (x, y, w, h) {
485         var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
486         cc._renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
487             (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
488             (w * locScaleX * locFrameZoomFactor),
489             (h * locScaleY * locFrameZoomFactor));
490     },
491 
492     /**
493      * Set Scissor rectangle with points.
494      * @param {Number} x
495      * @param {Number} y
496      * @param {Number} w
497      * @param {Number} h
498      */
499     setScissorInPoints: function (x, y, w, h) {
500         var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
501         cc._renderContext.scissor((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
502             (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
503             (w * locScaleX * locFrameZoomFactor),
504             (h * locScaleY * locFrameZoomFactor));
505     },
506 
507     /**
508      * Get whether GL_SCISSOR_TEST is enable
509      */
510     isScissorEnabled: function () {
511         var gl = cc._renderContext;
512         return gl.isEnabled(gl.SCISSOR_TEST);
513     },
514 
515     /**
516      * Get the current scissor rectangle
517      * @return {cc.Rect}
518      */
519     getScissorRect: function () {
520         var gl = cc._renderContext, scaleX = this._scaleX, scaleY = this._scaleY;
521         var boxArr = gl.getParameter(gl.SCISSOR_BOX);
522         return cc.rect((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / scaleY,
523             boxArr[2] / scaleX, boxArr[3] / scaleY);
524     },
525 
526     /**
527      * @param {String} viewName
528      */
529     setViewName: function (viewName) {
530         if (viewName != null && viewName.length > 0) {
531             this._viewName = viewName;
532         }
533     },
534 
535     /**
536      * get view name
537      * @return {String}
538      */
539     getViewName: function () {
540         return this._viewName;
541     },
542 
543     /**
544      * Get the opengl view port rectangle.
545      */
546     getViewPortRect: function () {
547         return this._viewPortRect;
548     },
549 
550     /**
551      * Get scale factor of the horizontal direction.
552      */
553     getScaleX: function () {
554         return this._scaleX;
555     },
556 
557     /**
558      * Get scale factor of the vertical direction.
559      */
560     getScaleY: function () {
561         return this._scaleY;
562     },
563 
564     /**
565      * Get device pixel ratio for retina display.
566      */
567     getDevicePixelRatio: function() {
568         return this._devicePixelRatio;
569     },
570 
571     /**
572      * Get the real location in view
573      */
574     convertToLocationInView: function (tx, ty, relatedPos) {
575         return {x: this._devicePixelRatio * (tx - relatedPos.left), y: this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty)};
576     },
577 
578     _convertMouseToLocationInView: function(point, relatedPos) {
579         var locViewPortRect = this._viewPortRect;
580         point.x = ((this._devicePixelRatio * (point.x - relatedPos.left)) - locViewPortRect.x) / this._scaleX;
581         point.y = (this._devicePixelRatio * (relatedPos.top + relatedPos.height - point.y) - locViewPortRect.y) / this._scaleY;
582     },
583 
584     _convertTouchesWithScale: function(touches){
585         var locViewPortRect = this._viewPortRect, locScaleX = this._scaleX, locScaleY = this._scaleY, selTouch, selPoint, selPrePoint;
586         for( var i = 0; i < touches.length; i ++){
587             selTouch = touches[i];
588             selPoint = selTouch._point;
589 	        selPrePoint = selTouch._prevPoint;
590             selTouch._setPoint((selPoint.x - locViewPortRect.x) / locScaleX,
591                 (selPoint.y - locViewPortRect.y) / locScaleY);
592             selTouch._setPrevPoint((selPrePoint.x - locViewPortRect.x) / locScaleX,
593                 (selPrePoint.y - locViewPortRect.y) / locScaleY);
594         }
595     }
596 });
597 
598 cc.EGLView._getInstance = function () {
599     if (!this._instance) {
600         this._instance = this._instance || new cc.EGLView();
601         this._instance.initialize();
602     }
603     return this._instance;
604 };
605 
606 /**
607  * <p>cc.ContainerStrategy class is the root strategy class of container's scale strategy,
608  * it controls the behavior of how to scale the cc.container and cc._canvas object</p>
609  *
610  * @class
611  * @extends cc.Class
612  */
613 cc.ContainerStrategy = cc.Class.extend(/** @lends cc.ContainerStrategy# */{
614     /**
615      * Manipulation before appling the strategy
616      * @param {cc.view} The target view
617      */
618     preApply: function (view) {
619     },
620 
621     /**
622      * Function to apply this strategy
623      * @param {cc.view} view
624      * @param {cc.Size} designedResolution
625      */
626     apply: function (view, designedResolution) {
627     },
628 
629     /**
630      * Manipulation after applying the strategy
631      * @param {cc.view} view  The target view
632      */
633     postApply: function (view) {
634 
635     },
636 
637     _setupContainer: function (view, w, h) {
638         var frame = view._frame;
639         if (cc.sys.isMobile && frame == document.documentElement) {
640             // Automatically full screen when user touches on mobile version
641             cc.screen.autoFullScreen(frame);
642         }
643 
644         var locCanvasElement = cc._canvas, locContainer = cc.container;
645         // Setup container
646         locContainer.style.width = locCanvasElement.style.width = w + "px";
647         locContainer.style.height = locCanvasElement.style.height = h + "px";
648         // Setup pixel ratio for retina display
649         var devicePixelRatio = view._devicePixelRatio = 1;
650         if (view.isRetinaEnabled())
651             devicePixelRatio = view._devicePixelRatio = window.devicePixelRatio || 1;
652         // Setup canvas
653         locCanvasElement.width = w * devicePixelRatio;
654         locCanvasElement.height = h * devicePixelRatio;
655 
656         var body = document.body, style;
657         if (body && (style = body.style)) {
658             style.paddingTop = style.paddingTop || "0px";
659             style.paddingRight = style.paddingRight || "0px";
660             style.paddingBottom = style.paddingBottom || "0px";
661             style.paddingLeft = style.paddingLeft || "0px";
662             style.borderTop = style.borderTop || "0px";
663             style.borderRight = style.borderRight || "0px";
664             style.borderBottom = style.borderBottom || "0px";
665             style.borderLeft = style.borderLeft || "0px";
666             style.marginTop = style.marginTop || "0px";
667             style.marginRight = style.marginRight || "0px";
668             style.marginBottom = style.marginBottom || "0px";
669             style.marginLeft = style.marginLeft || "0px";
670         }
671     },
672 
673     _fixContainer: function () {
674         // Add container to document body
675         document.body.insertBefore(cc.container, document.body.firstChild);
676         // Set body's width height to window's size, and forbid overflow, so that game will be centered
677         var bs = document.body.style;
678         bs.width = window.innerWidth + "px";
679         bs.height = window.innerHeight + "px";
680         bs.overflow = "hidden";
681         // Body size solution doesn't work on all mobile browser so this is the aleternative: fixed container
682         var contStyle = cc.container.style;
683         contStyle.position = "fixed";
684         contStyle.left = contStyle.top = "0px";
685         // Reposition body
686         document.body.scrollTop = 0;
687     }
688 });
689 
690 /**
691  * <p>cc.ContentStrategy class is the root strategy class of content's scale strategy,
692  * it controls the behavior of how to scale the scene and setup the viewport for the game</p>
693  *
694  * @class
695  * @extends cc.Class
696  */
697 cc.ContentStrategy = cc.Class.extend(/** @lends cc.ContentStrategy# */{
698 
699     _result: {
700         scale: [1, 1],
701         viewport: null
702     },
703 
704     _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
705 	    // Makes content fit better the canvas
706 	    Math.abs(containerW - contentW) < 2 && (contentW = containerW);
707 	    Math.abs(containerH - contentH) < 2 && (contentH = containerH);
708 
709         var viewport = cc.rect(Math.round((containerW - contentW) / 2),
710                                Math.round((containerH - contentH) / 2),
711                                contentW, contentH);
712 
713         // Translate the content
714         if (cc._renderType == cc._RENDER_TYPE_CANVAS)
715             cc._renderContext.translate(viewport.x, viewport.y + contentH);
716 
717         this._result.scale = [scaleX, scaleY];
718         this._result.viewport = viewport;
719         return this._result;
720     },
721 
722     /**
723      * Manipulation before applying the strategy
724      * @param {cc.view} view The target view
725      */
726     preApply: function (view) {
727     },
728 
729     /**
730      * Function to apply this strategy
731      * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
732      * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
733      * @param {cc.view} view
734      * @param {cc.Size} designedResolution
735      * @return {object} scaleAndViewportRect
736      */
737     apply: function (view, designedResolution) {
738         return {"scale": [1, 1]};
739     },
740 
741     /**
742      * Manipulation after applying the strategy
743      * @param {cc.view} view The target view
744      */
745     postApply: function (view) {
746     }
747 });
748 
749 (function () {
750 
751 // Container scale strategys
752     var EqualToFrame = cc.ContainerStrategy.extend({
753         apply: function (view) {
754             this._setupContainer(view, view._frameSize.width, view._frameSize.height);
755         }
756     });
757 
758     var ProportionalToFrame = cc.ContainerStrategy.extend({
759         apply: function (view, designedResolution) {
760             var frameW = view._frameSize.width, frameH = view._frameSize.height, containerStyle = cc.container.style,
761                 designW = designedResolution.width, designH = designedResolution.height,
762                 scaleX = frameW / designW, scaleY = frameH / designH,
763                 containerW, containerH;
764 
765             scaleX < scaleY ? (containerW = frameW, containerH = designH * scaleX) : (containerW = designW * scaleY, containerH = frameH);
766 
767             // Adjust container size with integer value
768             var offx = Math.round((frameW - containerW) / 2);
769             var offy = Math.round((frameH - containerH) / 2);
770             containerW = frameW - 2 * offx;
771             containerH = frameH - 2 * offy;
772 
773             this._setupContainer(view, containerW, containerH);
774             // Setup container's margin
775             containerStyle.marginLeft = offx + "px";
776             containerStyle.marginRight = offx + "px";
777             containerStyle.marginTop = offy + "px";
778             containerStyle.marginBottom = offy + "px";
779         }
780     });
781 
782     var EqualToWindow = EqualToFrame.extend({
783         preApply: function (view) {
784 	        this._super(view);
785             view._frame = document.documentElement;
786         },
787 
788         apply: function (view) {
789             this._super(view);
790             this._fixContainer();
791         }
792     });
793 
794     var ProportionalToWindow = ProportionalToFrame.extend({
795         preApply: function (view) {
796 	        this._super(view);
797             view._frame = document.documentElement;
798         },
799 
800         apply: function (view, designedResolution) {
801             this._super(view, designedResolution);
802             this._fixContainer();
803         }
804     });
805 
806     var OriginalContainer = cc.ContainerStrategy.extend({
807         apply: function (view) {
808             this._setupContainer(view, cc._canvas.width, cc._canvas.height);
809         }
810     });
811 
812 // #NOT STABLE on Android# Alias: Strategy that makes the container's size equals to the window's size
813 //    cc.ContainerStrategy.EQUAL_TO_WINDOW = new EqualToWindow();
814 // #NOT STABLE on Android# Alias: Strategy that scale proportionally the container's size to window's size
815 //    cc.ContainerStrategy.PROPORTION_TO_WINDOW = new ProportionalToWindow();
816 // Alias: Strategy that makes the container's size equals to the frame's size
817     cc.ContainerStrategy.EQUAL_TO_FRAME = new EqualToFrame();
818 // Alias: Strategy that scale proportionally the container's size to frame's size
819     cc.ContainerStrategy.PROPORTION_TO_FRAME = new ProportionalToFrame();
820 // Alias: Strategy that keeps the original container's size
821     cc.ContainerStrategy.ORIGINAL_CONTAINER = new OriginalContainer();
822 
823 // Content scale strategys
824     var ExactFit = cc.ContentStrategy.extend({
825         apply: function (view, designedResolution) {
826             var containerW = cc._canvas.width, containerH = cc._canvas.height,
827                 scaleX = containerW / designedResolution.width, scaleY = containerH / designedResolution.height;
828 
829             return this._buildResult(containerW, containerH, containerW, containerH, scaleX, scaleY);
830         }
831     });
832 
833     var ShowAll = cc.ContentStrategy.extend({
834         apply: function (view, designedResolution) {
835             var containerW = cc._canvas.width, containerH = cc._canvas.height,
836                 designW = designedResolution.width, designH = designedResolution.height,
837                 scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
838                 contentW, contentH;
839 
840 	        scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
841                 : (scale = scaleY, contentW = designW * scale, contentH = containerH);
842 
843             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
844         }
845     });
846 
847     var NoBorder = cc.ContentStrategy.extend({
848         apply: function (view, designedResolution) {
849             var containerW = cc._canvas.width, containerH = cc._canvas.height,
850                 designW = designedResolution.width, designH = designedResolution.height,
851                 scaleX = containerW / designW, scaleY = containerH / designH, scale,
852                 contentW, contentH;
853 
854             scaleX < scaleY ? (scale = scaleY, contentW = designW * scale, contentH = containerH)
855                 : (scale = scaleX, contentW = containerW, contentH = designH * scale);
856 
857             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
858         }
859     });
860 
861     var FixedHeight = cc.ContentStrategy.extend({
862         apply: function (view, designedResolution) {
863             var containerW = cc._canvas.width, containerH = cc._canvas.height,
864                 designH = designedResolution.height, scale = containerH / designH,
865                 contentW = containerW, contentH = containerH;
866 
867             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
868         },
869 
870         postApply: function (view) {
871             cc.director._winSizeInPoints = view.getVisibleSize();
872         }
873     });
874 
875     var FixedWidth = cc.ContentStrategy.extend({
876         apply: function (view, designedResolution) {
877             var containerW = cc._canvas.width, containerH = cc._canvas.height,
878                 designW = designedResolution.width, scale = containerW / designW,
879                 contentW = containerW, contentH = containerH;
880 
881             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
882         },
883 
884         postApply: function (view) {
885             cc.director._winSizeInPoints = view.getVisibleSize();
886         }
887     });
888 
889 // Alias: Strategy to scale the content's size to container's size, non proportional
890     cc.ContentStrategy.EXACT_FIT = new ExactFit();
891 // Alias: Strategy to scale the content's size proportionally to maximum size and keeps the whole content area to be visible
892     cc.ContentStrategy.SHOW_ALL = new ShowAll();
893 // Alias: Strategy to scale the content's size proportionally to fill the whole container area
894     cc.ContentStrategy.NO_BORDER = new NoBorder();
895 // Alias: Strategy to scale the content's height to container's height and proportionally scale its width
896     cc.ContentStrategy.FIXED_HEIGHT = new FixedHeight();
897 // Alias: Strategy to scale the content's width to container's width and proportionally scale its height
898     cc.ContentStrategy.FIXED_WIDTH = new FixedWidth();
899 
900 })();
901 
902 /**
903  * <p>cc.ResolutionPolicy class is the root strategy class of scale strategy,
904  * its main task is to maintain the compatibility with Cocos2d-x</p>
905  *
906  * @class
907  * @extends cc.Class
908  */
909 cc.ResolutionPolicy = cc.Class.extend(/** @lends cc.ResolutionPolicy# */{
910 	_containerStrategy: null,
911     _contentStrategy: null,
912 
913     ctor: function (containerStg, contentStg) {
914         this.setContainerStrategy(containerStg);
915         this.setContentStrategy(contentStg);
916     },
917 
918     /**
919      * Manipulation before applying the resolution policy
920      * @param {cc.view} view The target view
921      */
922     preApply: function (view) {
923         this._containerStrategy.preApply(view);
924         this._contentStrategy.preApply(view);
925     },
926 
927     /**
928      * Function to apply this resolution policy
929      * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
930      * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
931      * @param {cc.view} view The target view
932      * @param {cc.Size} designedResolution The user defined design resolution
933      * @return {object} An object contains the scale X/Y values and the viewport rect
934      */
935     apply: function (view, designedResolution) {
936         this._containerStrategy.apply(view, designedResolution);
937         return this._contentStrategy.apply(view, designedResolution);
938     },
939 
940     /**
941      * Manipulation after appyling the strategy
942      * @param {cc.view} view The target view
943      */
944     postApply: function (view) {
945         this._containerStrategy.postApply(view);
946         this._contentStrategy.postApply(view);
947     },
948 
949     /**
950      * Setup the container's scale strategy
951      * @param {cc.ContainerStrategy} containerStg
952      */
953     setContainerStrategy: function (containerStg) {
954         if (containerStg instanceof cc.ContainerStrategy)
955             this._containerStrategy = containerStg;
956     },
957 
958     /**
959      * Setup the content's scale strategy
960      * @param {cc.ContentStrategy} contentStg
961      */
962     setContentStrategy: function (contentStg) {
963         if (contentStg instanceof cc.ContentStrategy)
964             this._contentStrategy = contentStg;
965     }
966 });
967 
968 /*
969  * @memberOf cc.ResolutionPolicy#
970  * @name EXACT_FIT
971  * @const
972  * @static
973  * The entire application is visible in the specified area without trying to preserve the original aspect ratio.<br/>
974  * Distortion can occur, and the application may appear stretched or compressed.
975  */
976 cc.ResolutionPolicy.EXACT_FIT = 0;
977 
978 /*
979  * @memberOf cc.ResolutionPolicy#
980  * @name NO_BORDER
981  * @const
982  * @static
983  * The entire application fills the specified area, without distortion but possibly with some cropping,<br/>
984  * while maintaining the original aspect ratio of the application.
985  */
986 cc.ResolutionPolicy.NO_BORDER = 1;
987 
988 /*
989  * @memberOf cc.ResolutionPolicy#
990  * @name SHOW_ALL
991  * @const
992  * @static
993  * The entire application is visible in the specified area without distortion while maintaining the original<br/>
994  * aspect ratio of the application. Borders can appear on two sides of the application.
995  */
996 cc.ResolutionPolicy.SHOW_ALL = 2;
997 
998 /*
999  * @memberOf cc.ResolutionPolicy#
1000  * @name FIXED_HEIGHT
1001  * @const
1002  * @static
1003  * The application takes the height of the design resolution size and modifies the width of the internal<br/>
1004  * canvas so that it fits the aspect ratio of the device<br/>
1005  * no distortion will occur however you must make sure your application works on different<br/>
1006  * aspect ratios
1007  */
1008 cc.ResolutionPolicy.FIXED_HEIGHT = 3;
1009 
1010 /*
1011  * @memberOf cc.ResolutionPolicy#
1012  * @name FIXED_WIDTH
1013  * @const
1014  * @static
1015  * The application takes the width of the design resolution size and modifies the height of the internal<br/>
1016  * canvas so that it fits the aspect ratio of the device<br/>
1017  * no distortion will occur however you must make sure your application works on different<br/>
1018  * aspect ratios
1019  */
1020 cc.ResolutionPolicy.FIXED_WIDTH = 4;
1021 
1022 /*
1023  * @memberOf cc.ResolutionPolicy#
1024  * @name UNKNOWN
1025  * @const
1026  * @static
1027  * Unknow policy
1028  */
1029 cc.ResolutionPolicy.UNKNOWN = 5;