1 /****************************************************************************
  2  Copyright (c) 2008-2010 Ricardo Quesada
  3  Copyright (c) 2011-2012 cocos2d-x.org
  4  Copyright (c) 2013-2014 Chukong Technologies 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 cc.DENSITYDPI_DEVICE = "device-dpi";
 34 cc.DENSITYDPI_HIGH = "high-dpi";
 35 cc.DENSITYDPI_MEDIUM = "medium-dpi";
 36 cc.DENSITYDPI_LOW = "low-dpi";
 37 
 38 cc.__BrowserGetter = {
 39     init: function(){
 40         this.html = document.getElementsByTagName("html")[0];
 41     },
 42     availWidth: function(frame){
 43         if(!frame || frame === this.html)
 44             return window.innerWidth;
 45         else
 46             return frame.clientWidth;
 47     },
 48     availHeight: function(frame){
 49         if(!frame || frame === this.html)
 50             return window.innerHeight;
 51         else
 52             return frame.clientHeight;
 53     },
 54     meta: {
 55         "width": "device-width",
 56         "user-scalable": "no"
 57     },
 58     adaptationType: cc.sys.browserType
 59 };
 60 
 61 if(window.navigator.userAgent.indexOf("OS 8_1_") > -1) //this mistake like MIUI, so use of MIUI treatment method
 62     cc.__BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_MIUI;
 63 
 64 if(cc.sys.os === cc.sys.OS_IOS) // All browsers are WebView
 65     cc.__BrowserGetter.adaptationType = cc.sys.BROWSER_TYPE_SAFARI;
 66 
 67 switch(cc.__BrowserGetter.adaptationType){
 68     case cc.sys.BROWSER_TYPE_SAFARI:
 69         cc.__BrowserGetter.meta["minimal-ui"] = "true";
 70         cc.__BrowserGetter.availWidth = function(frame){
 71             return frame.clientWidth;
 72         };
 73         cc.__BrowserGetter.availHeight = function(frame){
 74             return frame.clientHeight;
 75         };
 76         break;
 77     case cc.sys.BROWSER_TYPE_CHROME:
 78         cc.__BrowserGetter.__defineGetter__("target-densitydpi", function(){
 79             return cc.view._targetDensityDPI;
 80         });
 81     case cc.sys.BROWSER_TYPE_SOUGOU:
 82     case cc.sys.BROWSER_TYPE_UC:
 83         cc.__BrowserGetter.availWidth = function(frame){
 84             return frame.clientWidth;
 85         };
 86         cc.__BrowserGetter.availHeight = function(frame){
 87             return frame.clientHeight;
 88         };
 89         break;
 90     case cc.sys.BROWSER_TYPE_MIUI:
 91         cc.__BrowserGetter.init = function(view){
 92             if(view.__resizeWithBrowserSize) return;
 93             var resize = function(){
 94                 view.setDesignResolutionSize(
 95                     view._designResolutionSize.width,
 96                     view._designResolutionSize.height,
 97                     view._resolutionPolicy
 98                 );
 99                 window.removeEventListener("resize", resize, false);
100             };
101             window.addEventListener("resize", resize, false);
102         };
103         break;
104 }
105 
106 /**
107  * cc.view is the singleton object which represents the game window.<br/>
108  * It's main task include: <br/>
109  *  - Apply the design resolution policy<br/>
110  *  - Provide interaction with the window, like resize event on web, retina display support, etc...<br/>
111  *  - Manage the game view port which can be different with the window<br/>
112  *  - Manage the content scale and translation<br/>
113  * <br/>
114  * Since the cc.view is a singleton, you don't need to call any constructor or create functions,<br/>
115  * the standard way to use it is by calling:<br/>
116  *  - cc.view.methodName(); <br/>
117  * @class
118  * @name cc.view
119  * @extend cc.Class
120  */
121 cc.EGLView = cc.Class.extend(/** @lends cc.view# */{
122     _delegate: null,
123     // Size of parent node that contains cc.container and cc._canvas
124     _frameSize: null,
125     // resolution size, it is the size appropriate for the app resources.
126     _designResolutionSize: null,
127     _originalDesignResolutionSize: null,
128     // Viewport is the container's rect related to content's coordinates in pixel
129     _viewPortRect: null,
130     // The visible rect in content's coordinate in point
131     _visibleRect: null,
132 	_retinaEnabled: false,
133     _autoFullScreen: true,
134     // The device's pixel ratio (for retina displays)
135     _devicePixelRatio: 1,
136     // the view name
137     _viewName: "",
138     // Custom callback for resize event
139     _resizeCallback: null,
140     _scaleX: 1,
141     _originalScaleX: 1,
142     _scaleY: 1,
143     _originalScaleY: 1,
144     _indexBitsUsed: 0,
145     _maxTouches: 5,
146     _resolutionPolicy: null,
147     _rpExactFit: null,
148     _rpShowAll: null,
149     _rpNoBorder: null,
150     _rpFixedHeight: null,
151     _rpFixedWidth: null,
152     _initialized: false,
153 
154     _captured: false,
155     _wnd: null,
156     _hDC: null,
157     _hRC: null,
158     _supportTouch: false,
159     _contentTranslateLeftTop: null,
160 
161     // Parent node that contains cc.container and cc._canvas
162     _frame: null,
163     _frameZoomFactor: 1.0,
164     __resizeWithBrowserSize: false,
165     _isAdjustViewPort: true,
166     _targetDensityDPI: null,
167 
168     /**
169      * Constructor of cc.EGLView
170      */
171     ctor: function () {
172         var _t = this, d = document, _strategyer = cc.ContainerStrategy, _strategy = cc.ContentStrategy;
173 
174         cc.__BrowserGetter.init(this);
175 
176         _t._frame = (cc.container.parentNode === d.body) ? d.documentElement : cc.container.parentNode;
177         _t._frameSize = cc.size(0, 0);
178         _t._initFrameSize();
179 
180         var w = cc._canvas.width, h = cc._canvas.height;
181         _t._designResolutionSize = cc.size(w, h);
182         _t._originalDesignResolutionSize = cc.size(w, h);
183         _t._viewPortRect = cc.rect(0, 0, w, h);
184         _t._visibleRect = cc.rect(0, 0, w, h);
185         _t._contentTranslateLeftTop = {left: 0, top: 0};
186         _t._viewName = "Cocos2dHTML5";
187 
188 	    var sys = cc.sys;
189         _t.enableRetina(sys.os === sys.OS_IOS || sys.os === sys.OS_OSX);
190         cc.visibleRect && cc.visibleRect.init(_t._visibleRect);
191 
192         // Setup system default resolution policies
193         _t._rpExactFit = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.EXACT_FIT);
194         _t._rpShowAll = new cc.ResolutionPolicy(_strategyer.PROPORTION_TO_FRAME, _strategy.SHOW_ALL);
195         _t._rpNoBorder = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.NO_BORDER);
196         _t._rpFixedHeight = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_HEIGHT);
197         _t._rpFixedWidth = new cc.ResolutionPolicy(_strategyer.EQUAL_TO_FRAME, _strategy.FIXED_WIDTH);
198 
199         _t._hDC = cc._canvas;
200         _t._hRC = cc._renderContext;
201         _t._targetDensityDPI = cc.DENSITYDPI_HIGH;
202     },
203 
204     // Resize helper functions
205     _resizeEvent: function () {
206         var view;
207         if(this.setDesignResolutionSize){
208             view = this;
209         }else{
210             view = cc.view;
211         }
212 
213         // Check frame size changed or not
214         var prevFrameW = view._frameSize.width, prevFrameH = view._frameSize.height;
215         view._initFrameSize();
216         if (view._frameSize.width === prevFrameW && view._frameSize.height === prevFrameH)
217             return;
218 
219         // Frame size changed, do resize works
220         if (view._resizeCallback) {
221             view._resizeCallback.call();
222         }
223         var width = view._originalDesignResolutionSize.width;
224         var height = view._originalDesignResolutionSize.height;
225         if (width > 0)
226             view.setDesignResolutionSize(width, height, view._resolutionPolicy);
227     },
228 
229     /**
230      * <p>
231      * Sets view's target-densitydpi for android mobile browser. it can be set to:           <br/>
232      *   1. cc.DENSITYDPI_DEVICE, value is "device-dpi"                                      <br/>
233      *   2. cc.DENSITYDPI_HIGH, value is "high-dpi"  (default value)                         <br/>
234      *   3. cc.DENSITYDPI_MEDIUM, value is "medium-dpi" (browser's default value)            <br/>
235      *   4. cc.DENSITYDPI_LOW, value is "low-dpi"                                            <br/>
236      *   5. Custom value, e.g: "480"                                                         <br/>
237      * </p>
238      * @param {String} densityDPI
239      */
240     setTargetDensityDPI: function(densityDPI){
241         this._targetDensityDPI = densityDPI;
242         this._adjustViewportMeta();
243     },
244 
245     /**
246      * Returns the current target-densitydpi value of cc.view.
247      * @returns {String}
248      */
249     getTargetDensityDPI: function(){
250         return this._targetDensityDPI;
251     },
252 
253     /**
254      * Sets whether resize canvas automatically when browser's size changed.<br/>
255      * Useful only on web.
256      * @param {Boolean} enabled Whether enable automatic resize with browser's resize event
257      */
258     resizeWithBrowserSize: function (enabled) {
259         if (enabled) {
260             //enable
261             if (!this.__resizeWithBrowserSize) {
262                 this.__resizeWithBrowserSize = true;
263                 cc._addEventListener(window, 'resize', this._resizeEvent);
264                 cc._addEventListener(window, 'orientationchange', this._resizeEvent);
265             }
266         } else {
267             //disable
268             if (this.__resizeWithBrowserSize) {
269                 this.__resizeWithBrowserSize = false;
270                 window.removeEventListener('resize', this._resizeEvent);
271                 window.removeEventListener('orientationchange', this._resizeEvent);
272             }
273         }
274     },
275 
276     /**
277      * Sets the callback function for cc.view's resize action,<br/>
278      * this callback will be invoked before applying resolution policy, <br/>
279      * so you can do any additional modifications within the callback.<br/>
280      * Useful only on web.
281      * @param {Function|null} callback The callback function
282      */
283     setResizeCallback: function (callback) {
284         if (cc.isFunction(callback) || callback == null) {
285             this._resizeCallback = callback;
286         }
287     },
288 
289     _initFrameSize: function () {
290         var locFrameSize = this._frameSize;
291         locFrameSize.width = cc.__BrowserGetter.availWidth(this._frame);
292         locFrameSize.height = cc.__BrowserGetter.availHeight(this._frame);
293     },
294 
295     // hack
296     _adjustSizeKeepCanvasSize: function () {
297         var designWidth = this._originalDesignResolutionSize.width;
298         var designHeight = this._originalDesignResolutionSize.height;
299         if (designWidth > 0)
300             this.setDesignResolutionSize(designWidth, designHeight, this._resolutionPolicy);
301     },
302 
303     _setViewportMeta: function (metas, overwrite) {
304         var vp = document.getElementById("cocosMetaElement");
305         if(vp){
306             document.head.removeChild(vp);
307         }
308 
309         var elems = document.getElementsByName("viewport"),
310             currentVP = elems ? elems[0] : null,
311             content, key, pattern;
312 
313         vp = cc.newElement("meta");
314         vp.id = "cocosMetaElement";
315         vp.name = "viewport";
316         vp.content = "";
317 
318         content = currentVP ? currentVP.content : "";
319         for (key in metas) {
320             if (content.indexOf(key) == -1) {
321                 content += "," + key + "=" + metas[key];
322             }
323             else if (overwrite) {
324                 pattern = new RegExp(key+"\s*=\s*[^,]+");
325                 content.replace(pattern, key + "=" + metas[key]);
326             }
327         }
328         if(/^,/.test(content))
329             content = content.substr(1);
330 
331         vp.content = content;
332         // For adopting certain android devices which don't support second viewport
333         if (currentVP)
334             currentVP.content = content;
335 
336         document.head.appendChild(vp);
337     },
338 
339     _adjustViewportMeta: function () {
340         if (this._isAdjustViewPort) {
341             this._setViewportMeta(cc.__BrowserGetter.meta, false);
342         }
343     },
344 
345     // RenderTexture hacker
346     _setScaleXYForRenderTexture: function () {
347         //hack for RenderTexture on canvas mode when adapting multiple resolution resources
348         var scaleFactor = cc.contentScaleFactor();
349         this._scaleX = scaleFactor;
350         this._scaleY = scaleFactor;
351     },
352 
353     // Other helper functions
354     _resetScale: function () {
355         this._scaleX = this._originalScaleX;
356         this._scaleY = this._originalScaleY;
357     },
358 
359     // Useless, just make sure the compatibility temporarily, should be removed
360     _adjustSizeToBrowser: function () {
361     },
362 
363     initialize: function () {
364         this._initialized = true;
365     },
366 
367     /**
368      * Sets whether the engine modify the "viewport" meta in your web page.<br/>
369      * It's enabled by default, we strongly suggest you not to disable it.<br/>
370      * And even when it's enabled, you can still set your own "viewport" meta, it won't be overridden<br/>
371      * Only useful on web
372      * @param {Boolean} enabled Enable automatic modification to "viewport" meta
373      */
374     adjustViewPort: function (enabled) {
375         this._isAdjustViewPort = enabled;
376     },
377 
378 	/**
379 	 * Retina support is enabled by default for Apple device but disabled for other devices,<br/>
380 	 * it takes effect only when you called setDesignResolutionPolicy<br/>
381      * Only useful on web
382 	 * @param {Boolean} enabled  Enable or disable retina display
383 	 */
384 	enableRetina: function(enabled) {
385 		this._retinaEnabled = enabled ? true : false;
386 	},
387 
388 	/**
389 	 * Check whether retina display is enabled.<br/>
390      * Only useful on web
391 	 * @return {Boolean}
392 	 */
393 	isRetinaEnabled: function() {
394 		return this._retinaEnabled;
395 	},
396 
397     /**
398      * If enabled, the application will try automatically to enter full screen mode on mobile devices<br/>
399      * You can pass true as parameter to enable it and disable it by passing false.<br/>
400      * Only useful on web
401      * @param {Boolean} enabled  Enable or disable auto full screen on mobile devices
402      */
403     enableAutoFullScreen: function(enabled) {
404         this._autoFullScreen = enabled ? true : false;
405     },
406 
407     /**
408      * Check whether auto full screen is enabled.<br/>
409      * Only useful on web
410      * @return {Boolean} Auto full screen enabled or not
411      */
412     isAutoFullScreenEnabled: function() {
413         return this._autoFullScreen;
414     },
415 
416     /**
417      * Force destroying EGL view, subclass must implement this method.
418      */
419     end: function () {
420     },
421 
422     /**
423      * Get whether render system is ready(no matter opengl or canvas),<br/>
424      * this name is for the compatibility with cocos2d-x, subclass must implement this method.
425      * @return {Boolean}
426      */
427     isOpenGLReady: function () {
428         return (this._hDC !== null && this._hRC !== null);
429     },
430 
431     /*
432      * Set zoom factor for frame. This method is for debugging big resolution (e.g.new ipad) app on desktop.
433      * @param {Number} zoomFactor
434      */
435     setFrameZoomFactor: function (zoomFactor) {
436         this._frameZoomFactor = zoomFactor;
437         this.centerWindow();
438         cc.director.setProjection(cc.director.getProjection());
439     },
440 
441     /**
442      * Exchanges the front and back buffers, subclass must implement this method.
443      */
444     swapBuffers: function () {
445     },
446 
447     /**
448      * Open or close IME keyboard , subclass must implement this method.
449      * @param {Boolean} isOpen
450      */
451     setIMEKeyboardState: function (isOpen) {
452     },
453 
454     /**
455      * Sets the resolution translate on EGLView
456      * @param {Number} offsetLeft
457      * @param {Number} offsetTop
458      */
459     setContentTranslateLeftTop: function (offsetLeft, offsetTop) {
460         this._contentTranslateLeftTop = {left: offsetLeft, top: offsetTop};
461     },
462 
463     /**
464      * Returns the resolution translate on EGLView
465      * @return {cc.Size|Object}
466      */
467     getContentTranslateLeftTop: function () {
468         return this._contentTranslateLeftTop;
469     },
470 
471     /**
472      * Returns the frame size of the view.<br/>
473      * On native platforms, it returns the screen size since the view is a fullscreen view.<br/>
474      * On web, it returns the size of the canvas's outer DOM element.
475      * @return {cc.Size}
476      */
477     getFrameSize: function () {
478         return cc.size(this._frameSize.width, this._frameSize.height);
479     },
480 
481     /**
482      * On native, it sets the frame size of view.<br/>
483      * On web, it sets the size of the canvas's outer DOM element.
484      * @param {Number} width
485      * @param {Number} height
486      */
487     setFrameSize: function (width, height) {
488         this._frameSize.width = width;
489         this._frameSize.height = height;
490         this._frame.style.width = width + "px";
491         this._frame.style.height = height + "px";
492         //this.centerWindow();
493         this._resizeEvent();
494         cc.director.setProjection(cc.director.getProjection());
495     },
496 
497     /**
498      * Empty function
499      */
500     centerWindow: function () {
501     },
502 
503     /**
504      * Returns the visible area size of the view port.
505      * @return {cc.Size}
506      */
507     getVisibleSize: function () {
508         return cc.size(this._visibleRect.width,this._visibleRect.height);
509     },
510 
511     /**
512      * Returns the visible origin of the view port.
513      * @return {cc.Point}
514      */
515     getVisibleOrigin: function () {
516         return cc.p(this._visibleRect.x,this._visibleRect.y);
517     },
518 
519     /**
520      * Returns whether developer can set content's scale factor.
521      * @return {Boolean}
522      */
523     canSetContentScaleFactor: function () {
524         return true;
525     },
526 
527     /**
528      * Returns the current resolution policy
529      * @see cc.ResolutionPolicy
530      * @return {cc.ResolutionPolicy}
531      */
532     getResolutionPolicy: function () {
533         return this._resolutionPolicy;
534     },
535 
536     /**
537      * Sets the current resolution policy
538      * @see cc.ResolutionPolicy
539      * @param {cc.ResolutionPolicy|Number} resolutionPolicy
540      */
541     setResolutionPolicy: function (resolutionPolicy) {
542         var _t = this;
543         if (resolutionPolicy instanceof cc.ResolutionPolicy) {
544             _t._resolutionPolicy = resolutionPolicy;
545         }
546         // Ensure compatibility with JSB
547         else {
548             var _locPolicy = cc.ResolutionPolicy;
549             if(resolutionPolicy === _locPolicy.EXACT_FIT)
550                 _t._resolutionPolicy = _t._rpExactFit;
551             if(resolutionPolicy === _locPolicy.SHOW_ALL)
552                 _t._resolutionPolicy = _t._rpShowAll;
553             if(resolutionPolicy === _locPolicy.NO_BORDER)
554                 _t._resolutionPolicy = _t._rpNoBorder;
555             if(resolutionPolicy === _locPolicy.FIXED_HEIGHT)
556                 _t._resolutionPolicy = _t._rpFixedHeight;
557             if(resolutionPolicy === _locPolicy.FIXED_WIDTH)
558                 _t._resolutionPolicy = _t._rpFixedWidth;
559         }
560     },
561 
562     /**
563      * Sets the resolution policy with designed view size in points.<br/>
564      * The resolution policy include: <br/>
565      * [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.<br/>
566      * [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.<br/>
567      * [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.<br/>
568      * [4] ResolutionFixedHeight    Scale the content's height to screen's height and proportionally scale its width<br/>
569      * [5] ResolutionFixedWidth     Scale the content's width to screen's width and proportionally scale its height<br/>
570      * [cc.ResolutionPolicy]        [Web only feature] Custom resolution policy, constructed by cc.ResolutionPolicy<br/>
571      * @param {Number} width Design resolution width.
572      * @param {Number} height Design resolution height.
573      * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired
574      */
575     setDesignResolutionSize: function (width, height, resolutionPolicy) {
576         // Defensive code
577         if( !(width > 0 || height > 0) ){
578             cc.log(cc._LogInfos.EGLView_setDesignResolutionSize);
579             return;
580         }
581 
582         this.setResolutionPolicy(resolutionPolicy);
583         var policy = this._resolutionPolicy;
584         if (!policy){
585             cc.log(cc._LogInfos.EGLView_setDesignResolutionSize_2);
586             return;
587         }
588         policy.preApply(this);
589 
590         // Reinit frame size
591         if(cc.sys.isMobile)
592             this._adjustViewportMeta();
593 
594         this._initFrameSize();
595 
596         this._originalDesignResolutionSize.width = this._designResolutionSize.width = width;
597         this._originalDesignResolutionSize.height = this._designResolutionSize.height = height;
598 
599         var result = policy.apply(this, this._designResolutionSize);
600 
601         if(result.scale && result.scale.length === 2){
602             this._scaleX = result.scale[0];
603             this._scaleY = result.scale[1];
604         }
605 
606         if(result.viewport){
607             var vp = this._viewPortRect,
608                 vb = this._visibleRect,
609                 rv = result.viewport;
610 
611             vp.x = rv.x;
612             vp.y = rv.y;
613             vp.width = rv.width;
614             vp.height = rv.height;
615 
616             vb.x = -vp.x / this._scaleX;
617             vb.y = -vp.y / this._scaleY;
618             vb.width = cc._canvas.width / this._scaleX;
619             vb.height = cc._canvas.height / this._scaleY;
620             cc._renderContext.setOffset && cc._renderContext.setOffset(vp.x, -vp.y)
621         }
622 
623         // reset director's member variables to fit visible rect
624         var director = cc.director;
625         director._winSizeInPoints.width = this._designResolutionSize.width;
626         director._winSizeInPoints.height = this._designResolutionSize.height;
627         policy.postApply(this);
628         cc.winSize.width = director._winSizeInPoints.width;
629         cc.winSize.height = director._winSizeInPoints.height;
630 
631         if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
632             // reset director's member variables to fit visible rect
633             director._createStatsLabel();
634             director.setGLDefaultValues();
635         }
636 
637         this._originalScaleX = this._scaleX;
638         this._originalScaleY = this._scaleY;
639         // For editbox
640         if (cc.DOM)
641             cc.DOM._resetEGLViewDiv();
642         cc.visibleRect && cc.visibleRect.init(this._visibleRect);
643     },
644 
645     /**
646      * Returns the designed size for the view.
647      * Default resolution size is the same as 'getFrameSize'.
648      * @return {cc.Size}
649      */
650     getDesignResolutionSize: function () {
651         return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
652     },
653 
654     /**
655      * Sets the document body to desired pixel resolution and fit the game content to it.
656      * This function is very useful for adaptation in mobile browsers.
657      * In some HD android devices, the resolution is very high, but its browser performance may not be very good.
658      * In this case, enabling retina display is very costy and not suggested, and if retina is disabled, the image may be blurry.
659      * But this API can be helpful to set a desired pixel resolution which is in between.
660      * This API will do the following:
661      *     1. Set viewport's width to the desired width in pixel
662      *     2. Set body width to the exact pixel resolution
663      *     3. The resolution policy will be reset with designed view size in points.
664      * @param {Number} width Design resolution width.
665      * @param {Number} height Design resolution height.
666      * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired
667      */
668     setRealPixelResolution: function (width, height, resolutionPolicy) {
669         // Set viewport's width
670         this._setViewportMeta({"width": width, "user-scalable": "no"}, true);
671 
672         // Set body width to the exact pixel resolution
673         document.body.style.width = width + "px";
674         document.body.style.height = "100%";
675         document.body.style.left = "0px";
676         document.body.style.top = "0px";
677 
678         // Reset the resolution size and policy
679         this.setDesignResolutionSize(width, height, resolutionPolicy);
680     },
681 
682     /**
683      * Sets view port rectangle with points.
684      * @param {Number} x
685      * @param {Number} y
686      * @param {Number} w width
687      * @param {Number} h height
688      */
689     setViewPortInPoints: function (x, y, w, h) {
690         var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
691         cc._renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
692             (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
693             (w * locScaleX * locFrameZoomFactor),
694             (h * locScaleY * locFrameZoomFactor));
695     },
696 
697     /**
698      * Sets Scissor rectangle with points.
699      * @param {Number} x
700      * @param {Number} y
701      * @param {Number} w
702      * @param {Number} h
703      */
704     setScissorInPoints: function (x, y, w, h) {
705         var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
706         cc._renderContext.scissor((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
707             (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
708             (w * locScaleX * locFrameZoomFactor),
709             (h * locScaleY * locFrameZoomFactor));
710     },
711 
712     /**
713      * Returns whether GL_SCISSOR_TEST is enable
714      * @return {Boolean}
715      */
716     isScissorEnabled: function () {
717         var gl = cc._renderContext;
718         return gl.isEnabled(gl.SCISSOR_TEST);
719     },
720 
721     /**
722      * Returns the current scissor rectangle
723      * @return {cc.Rect}
724      */
725     getScissorRect: function () {
726         var gl = cc._renderContext, scaleX = this._scaleX, scaleY = this._scaleY;
727         var boxArr = gl.getParameter(gl.SCISSOR_BOX);
728         return cc.rect((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / scaleY,
729             boxArr[2] / scaleX, boxArr[3] / scaleY);
730     },
731 
732     /**
733      * Sets the name of the view
734      * @param {String} viewName
735      */
736     setViewName: function (viewName) {
737         if (viewName != null && viewName.length > 0) {
738             this._viewName = viewName;
739         }
740     },
741 
742     /**
743      * Returns the name of the view
744      * @return {String}
745      */
746     getViewName: function () {
747         return this._viewName;
748     },
749 
750     /**
751      * Returns the view port rectangle.
752      * @return {cc.Rect}
753      */
754     getViewPortRect: function () {
755         return this._viewPortRect;
756     },
757 
758     /**
759      * Returns scale factor of the horizontal direction (X axis).
760      * @return {Number}
761      */
762     getScaleX: function () {
763         return this._scaleX;
764     },
765 
766     /**
767      * Returns scale factor of the vertical direction (Y axis).
768      * @return {Number}
769      */
770     getScaleY: function () {
771         return this._scaleY;
772     },
773 
774     /**
775      * Returns device pixel ratio for retina display.
776      * @return {Number}
777      */
778     getDevicePixelRatio: function() {
779         return this._devicePixelRatio;
780     },
781 
782     /**
783      * Returns the real location in view for a translation based on a related position
784      * @param {Number} tx The X axis translation
785      * @param {Number} ty The Y axis translation
786      * @param {Object} relatedPos The related position object including "left", "top", "width", "height" informations
787      * @return {cc.Point}
788      */
789     convertToLocationInView: function (tx, ty, relatedPos) {
790         return {x: this._devicePixelRatio * (tx - relatedPos.left), y: this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty)};
791     },
792 
793     _convertMouseToLocationInView: function(point, relatedPos) {
794         var locViewPortRect = this._viewPortRect, _t = this;
795         point.x = ((_t._devicePixelRatio * (point.x - relatedPos.left)) - locViewPortRect.x) / _t._scaleX;
796         point.y = (_t._devicePixelRatio * (relatedPos.top + relatedPos.height - point.y) - locViewPortRect.y) / _t._scaleY;
797     },
798 
799     _convertTouchesWithScale: function(touches){
800         var locViewPortRect = this._viewPortRect, locScaleX = this._scaleX, locScaleY = this._scaleY, selTouch, selPoint, selPrePoint;
801         for( var i = 0; i < touches.length; i ++){
802             selTouch = touches[i];
803             selPoint = selTouch._point;
804 	        selPrePoint = selTouch._prevPoint;
805             selTouch._setPoint((selPoint.x - locViewPortRect.x) / locScaleX,
806                 (selPoint.y - locViewPortRect.y) / locScaleY);
807             selTouch._setPrevPoint((selPrePoint.x - locViewPortRect.x) / locScaleX,
808                 (selPrePoint.y - locViewPortRect.y) / locScaleY);
809         }
810     }
811 });
812 
813 /**
814  * @function
815  * @return {cc.EGLView}
816  * @private
817  */
818 cc.EGLView._getInstance = function () {
819     if (!this._instance) {
820         this._instance = this._instance || new cc.EGLView();
821         this._instance.initialize();
822     }
823     return this._instance;
824 };
825 
826 /**
827  * <p>cc.ContainerStrategy class is the root strategy class of container's scale strategy,
828  * it controls the behavior of how to scale the cc.container and cc._canvas object</p>
829  *
830  * @class
831  * @extends cc.Class
832  */
833 cc.ContainerStrategy = cc.Class.extend(/** @lends cc.ContainerStrategy# */{
834     /**
835      * Manipulation before appling the strategy
836      * @param {cc.view} The target view
837      */
838     preApply: function (view) {
839     },
840 
841     /**
842      * Function to apply this strategy
843      * @param {cc.view} view
844      * @param {cc.Size} designedResolution
845      */
846     apply: function (view, designedResolution) {
847     },
848 
849     /**
850      * Manipulation after applying the strategy
851      * @param {cc.view} view  The target view
852      */
853     postApply: function (view) {
854 
855     },
856 
857     _setupContainer: function (view, w, h) {
858         var frame = view._frame;
859         if (cc.view._autoFullScreen && cc.sys.isMobile && frame === document.documentElement) {
860             // Automatically full screen when user touches on mobile version
861             cc.screen.autoFullScreen(frame);
862         }
863 
864         var locCanvasElement = cc._canvas, locContainer = cc.container;
865         // Setup container
866         locContainer.style.width = locCanvasElement.style.width = w + "px";
867         locContainer.style.height = locCanvasElement.style.height = h + "px";
868         // Setup pixel ratio for retina display
869         var devicePixelRatio = view._devicePixelRatio = 1;
870         if (view.isRetinaEnabled())
871             devicePixelRatio = view._devicePixelRatio = window.devicePixelRatio || 1;
872         // Setup canvas
873         locCanvasElement.width = w * devicePixelRatio;
874         locCanvasElement.height = h * devicePixelRatio;
875         cc._renderContext.resetCache && cc._renderContext.resetCache();
876 
877         var body = document.body, style;
878         if (body && (style = body.style)) {
879             style.paddingTop = style.paddingTop || "0px";
880             style.paddingRight = style.paddingRight || "0px";
881             style.paddingBottom = style.paddingBottom || "0px";
882             style.paddingLeft = style.paddingLeft || "0px";
883             style.borderTop = style.borderTop || "0px";
884             style.borderRight = style.borderRight || "0px";
885             style.borderBottom = style.borderBottom || "0px";
886             style.borderLeft = style.borderLeft || "0px";
887             style.marginTop = style.marginTop || "0px";
888             style.marginRight = style.marginRight || "0px";
889             style.marginBottom = style.marginBottom || "0px";
890             style.marginLeft = style.marginLeft || "0px";
891         }
892     },
893 
894     _fixContainer: function () {
895         // Add container to document body
896         document.body.insertBefore(cc.container, document.body.firstChild);
897         // Set body's width height to window's size, and forbid overflow, so that game will be centered
898         var bs = document.body.style;
899         bs.width = window.innerWidth + "px";
900         bs.height = window.innerHeight + "px";
901         bs.overflow = "hidden";
902         // Body size solution doesn't work on all mobile browser so this is the aleternative: fixed container
903         var contStyle = cc.container.style;
904         contStyle.position = "fixed";
905         contStyle.left = contStyle.top = "0px";
906         // Reposition body
907         document.body.scrollTop = 0;
908     }
909 });
910 
911 /**
912  * <p>cc.ContentStrategy class is the root strategy class of content's scale strategy,
913  * it controls the behavior of how to scale the scene and setup the viewport for the game</p>
914  *
915  * @class
916  * @extends cc.Class
917  */
918 cc.ContentStrategy = cc.Class.extend(/** @lends cc.ContentStrategy# */{
919 
920     _result: {
921         scale: [1, 1],
922         viewport: null
923     },
924 
925     _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
926 	    // Makes content fit better the canvas
927 	    Math.abs(containerW - contentW) < 2 && (contentW = containerW);
928 	    Math.abs(containerH - contentH) < 2 && (contentH = containerH);
929 
930         var viewport = cc.rect(Math.round((containerW - contentW) / 2),
931                                Math.round((containerH - contentH) / 2),
932                                contentW, contentH);
933 
934         // Translate the content
935         if (cc._renderType === cc._RENDER_TYPE_CANVAS){
936             //TODO: modify something for setTransform
937             //cc._renderContext.translate(viewport.x, viewport.y + contentH);
938         }
939 
940         this._result.scale = [scaleX, scaleY];
941         this._result.viewport = viewport;
942         return this._result;
943     },
944 
945     /**
946      * Manipulation before applying the strategy
947      * @param {cc.view} view The target view
948      */
949     preApply: function (view) {
950     },
951 
952     /**
953      * Function to apply this strategy
954      * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
955      * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
956      * @param {cc.view} view
957      * @param {cc.Size} designedResolution
958      * @return {object} scaleAndViewportRect
959      */
960     apply: function (view, designedResolution) {
961         return {"scale": [1, 1]};
962     },
963 
964     /**
965      * Manipulation after applying the strategy
966      * @param {cc.view} view The target view
967      */
968     postApply: function (view) {
969     }
970 });
971 
972 (function () {
973 
974 // Container scale strategys
975     /**
976      * @class
977      * @extends cc.ContainerStrategy
978      */
979     var EqualToFrame = cc.ContainerStrategy.extend({
980         apply: function (view) {
981             this._setupContainer(view, view._frameSize.width, view._frameSize.height);
982         }
983     });
984 
985     /**
986      * @class
987      * @extends cc.ContainerStrategy
988      */
989     var ProportionalToFrame = cc.ContainerStrategy.extend({
990         apply: function (view, designedResolution) {
991             var frameW = view._frameSize.width, frameH = view._frameSize.height, containerStyle = cc.container.style,
992                 designW = designedResolution.width, designH = designedResolution.height,
993                 scaleX = frameW / designW, scaleY = frameH / designH,
994                 containerW, containerH;
995 
996             scaleX < scaleY ? (containerW = frameW, containerH = designH * scaleX) : (containerW = designW * scaleY, containerH = frameH);
997 
998             // Adjust container size with integer value
999             var offx = Math.round((frameW - containerW) / 2);
1000             var offy = Math.round((frameH - containerH) / 2);
1001             containerW = frameW - 2 * offx;
1002             containerH = frameH - 2 * offy;
1003 
1004             this._setupContainer(view, containerW, containerH);
1005             // Setup container's margin
1006             containerStyle.marginLeft = offx + "px";
1007             containerStyle.marginRight = offx + "px";
1008             containerStyle.marginTop = offy + "px";
1009             containerStyle.marginBottom = offy + "px";
1010         }
1011     });
1012 
1013     /**
1014      * @class
1015      * @extends EqualToFrame
1016      */
1017     var EqualToWindow = EqualToFrame.extend({
1018         preApply: function (view) {
1019 	        this._super(view);
1020             view._frame = document.documentElement;
1021         },
1022 
1023         apply: function (view) {
1024             this._super(view);
1025             this._fixContainer();
1026         }
1027     });
1028 
1029     /**
1030      * @class
1031      * @extends ProportionalToFrame
1032      */
1033     var ProportionalToWindow = ProportionalToFrame.extend({
1034         preApply: function (view) {
1035 	        this._super(view);
1036             view._frame = document.documentElement;
1037         },
1038 
1039         apply: function (view, designedResolution) {
1040             this._super(view, designedResolution);
1041             this._fixContainer();
1042         }
1043     });
1044 
1045     /**
1046      * @class
1047      * @extends cc.ContainerStrategy
1048      */
1049     var OriginalContainer = cc.ContainerStrategy.extend({
1050         apply: function (view) {
1051             this._setupContainer(view, cc._canvas.width, cc._canvas.height);
1052         }
1053     });
1054 
1055 // #NOT STABLE on Android# Alias: Strategy that makes the container's size equals to the window's size
1056 //    cc.ContainerStrategy.EQUAL_TO_WINDOW = new EqualToWindow();
1057 // #NOT STABLE on Android# Alias: Strategy that scale proportionally the container's size to window's size
1058 //    cc.ContainerStrategy.PROPORTION_TO_WINDOW = new ProportionalToWindow();
1059 // Alias: Strategy that makes the container's size equals to the frame's size
1060     cc.ContainerStrategy.EQUAL_TO_FRAME = new EqualToFrame();
1061 // Alias: Strategy that scale proportionally the container's size to frame's size
1062     cc.ContainerStrategy.PROPORTION_TO_FRAME = new ProportionalToFrame();
1063 // Alias: Strategy that keeps the original container's size
1064     cc.ContainerStrategy.ORIGINAL_CONTAINER = new OriginalContainer();
1065 
1066 // Content scale strategys
1067     var ExactFit = cc.ContentStrategy.extend({
1068         apply: function (view, designedResolution) {
1069             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1070                 scaleX = containerW / designedResolution.width, scaleY = containerH / designedResolution.height;
1071 
1072             return this._buildResult(containerW, containerH, containerW, containerH, scaleX, scaleY);
1073         }
1074     });
1075 
1076     var ShowAll = cc.ContentStrategy.extend({
1077         apply: function (view, designedResolution) {
1078             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1079                 designW = designedResolution.width, designH = designedResolution.height,
1080                 scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
1081                 contentW, contentH;
1082 
1083 	        scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
1084                 : (scale = scaleY, contentW = designW * scale, contentH = containerH);
1085 
1086             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1087         }
1088     });
1089 
1090     var NoBorder = cc.ContentStrategy.extend({
1091         apply: function (view, designedResolution) {
1092             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1093                 designW = designedResolution.width, designH = designedResolution.height,
1094                 scaleX = containerW / designW, scaleY = containerH / designH, scale,
1095                 contentW, contentH;
1096 
1097             scaleX < scaleY ? (scale = scaleY, contentW = designW * scale, contentH = containerH)
1098                 : (scale = scaleX, contentW = containerW, contentH = designH * scale);
1099 
1100             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1101         }
1102     });
1103 
1104     var FixedHeight = cc.ContentStrategy.extend({
1105         apply: function (view, designedResolution) {
1106             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1107                 designH = designedResolution.height, scale = containerH / designH,
1108                 contentW = containerW, contentH = containerH;
1109 
1110             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1111         },
1112 
1113         postApply: function (view) {
1114             cc.director._winSizeInPoints = view.getVisibleSize();
1115         }
1116     });
1117 
1118     var FixedWidth = cc.ContentStrategy.extend({
1119         apply: function (view, designedResolution) {
1120             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1121                 designW = designedResolution.width, scale = containerW / designW,
1122                 contentW = containerW, contentH = containerH;
1123 
1124             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1125         },
1126 
1127         postApply: function (view) {
1128             cc.director._winSizeInPoints = view.getVisibleSize();
1129         }
1130     });
1131 
1132 // Alias: Strategy to scale the content's size to container's size, non proportional
1133     cc.ContentStrategy.EXACT_FIT = new ExactFit();
1134 // Alias: Strategy to scale the content's size proportionally to maximum size and keeps the whole content area to be visible
1135     cc.ContentStrategy.SHOW_ALL = new ShowAll();
1136 // Alias: Strategy to scale the content's size proportionally to fill the whole container area
1137     cc.ContentStrategy.NO_BORDER = new NoBorder();
1138 // Alias: Strategy to scale the content's height to container's height and proportionally scale its width
1139     cc.ContentStrategy.FIXED_HEIGHT = new FixedHeight();
1140 // Alias: Strategy to scale the content's width to container's width and proportionally scale its height
1141     cc.ContentStrategy.FIXED_WIDTH = new FixedWidth();
1142 
1143 })();
1144 
1145 /**
1146  * <p>cc.ResolutionPolicy class is the root strategy class of scale strategy,
1147  * its main task is to maintain the compatibility with Cocos2d-x</p>
1148  *
1149  * @class
1150  * @extends cc.Class
1151  * @param {cc.ContainerStrategy} containerStg The container strategy
1152  * @param {cc.ContentStrategy} contentStg The content strategy
1153  */
1154 cc.ResolutionPolicy = cc.Class.extend(/** @lends cc.ResolutionPolicy# */{
1155 	_containerStrategy: null,
1156     _contentStrategy: null,
1157 
1158     /**
1159      * Constructor of cc.ResolutionPolicy
1160      * @param {cc.ContainerStrategy} containerStg
1161      * @param {cc.ContentStrategy} contentStg
1162      */
1163     ctor: function (containerStg, contentStg) {
1164         this.setContainerStrategy(containerStg);
1165         this.setContentStrategy(contentStg);
1166     },
1167 
1168     /**
1169      * Manipulation before applying the resolution policy
1170      * @param {cc.view} view The target view
1171      */
1172     preApply: function (view) {
1173         this._containerStrategy.preApply(view);
1174         this._contentStrategy.preApply(view);
1175     },
1176 
1177     /**
1178      * Function to apply this resolution policy
1179      * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
1180      * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
1181      * @param {cc.view} view The target view
1182      * @param {cc.Size} designedResolution The user defined design resolution
1183      * @return {object} An object contains the scale X/Y values and the viewport rect
1184      */
1185     apply: function (view, designedResolution) {
1186         this._containerStrategy.apply(view, designedResolution);
1187         return this._contentStrategy.apply(view, designedResolution);
1188     },
1189 
1190     /**
1191      * Manipulation after appyling the strategy
1192      * @param {cc.view} view The target view
1193      */
1194     postApply: function (view) {
1195         this._containerStrategy.postApply(view);
1196         this._contentStrategy.postApply(view);
1197     },
1198 
1199     /**
1200      * Setup the container's scale strategy
1201      * @param {cc.ContainerStrategy} containerStg
1202      */
1203     setContainerStrategy: function (containerStg) {
1204         if (containerStg instanceof cc.ContainerStrategy)
1205             this._containerStrategy = containerStg;
1206     },
1207 
1208     /**
1209      * Setup the content's scale strategy
1210      * @param {cc.ContentStrategy} contentStg
1211      */
1212     setContentStrategy: function (contentStg) {
1213         if (contentStg instanceof cc.ContentStrategy)
1214             this._contentStrategy = contentStg;
1215     }
1216 });
1217 
1218 /**
1219  * @memberOf cc.ResolutionPolicy#
1220  * @name EXACT_FIT
1221  * @constant
1222  * @type Number
1223  * @static
1224  * The entire application is visible in the specified area without trying to preserve the original aspect ratio.<br/>
1225  * Distortion can occur, and the application may appear stretched or compressed.
1226  */
1227 cc.ResolutionPolicy.EXACT_FIT = 0;
1228 
1229 /**
1230  * @memberOf cc.ResolutionPolicy#
1231  * @name NO_BORDER
1232  * @constant
1233  * @type Number
1234  * @static
1235  * The entire application fills the specified area, without distortion but possibly with some cropping,<br/>
1236  * while maintaining the original aspect ratio of the application.
1237  */
1238 cc.ResolutionPolicy.NO_BORDER = 1;
1239 
1240 /**
1241  * @memberOf cc.ResolutionPolicy#
1242  * @name SHOW_ALL
1243  * @constant
1244  * @type Number
1245  * @static
1246  * The entire application is visible in the specified area without distortion while maintaining the original<br/>
1247  * aspect ratio of the application. Borders can appear on two sides of the application.
1248  */
1249 cc.ResolutionPolicy.SHOW_ALL = 2;
1250 
1251 /**
1252  * @memberOf cc.ResolutionPolicy#
1253  * @name FIXED_HEIGHT
1254  * @constant
1255  * @type Number
1256  * @static
1257  * The application takes the height of the design resolution size and modifies the width of the internal<br/>
1258  * canvas so that it fits the aspect ratio of the device<br/>
1259  * no distortion will occur however you must make sure your application works on different<br/>
1260  * aspect ratios
1261  */
1262 cc.ResolutionPolicy.FIXED_HEIGHT = 3;
1263 
1264 /**
1265  * @memberOf cc.ResolutionPolicy#
1266  * @name FIXED_WIDTH
1267  * @constant
1268  * @type Number
1269  * @static
1270  * The application takes the width of the design resolution size and modifies the height of the internal<br/>
1271  * canvas so that it fits the aspect ratio of the device<br/>
1272  * no distortion will occur however you must make sure your application works on different<br/>
1273  * aspect ratios
1274  */
1275 cc.ResolutionPolicy.FIXED_WIDTH = 4;
1276 
1277 /**
1278  * @memberOf cc.ResolutionPolicy#
1279  * @name UNKNOWN
1280  * @constant
1281  * @type Number
1282  * @static
1283  * Unknow policy
1284  */
1285 cc.ResolutionPolicy.UNKNOWN = 5;