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._setViewPortMeta();
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 () {
304         if (this._isAdjustViewPort) {
305             var vp = document.getElementById("cocosMetaElement");
306             if(vp){
307                 document.head.removeChild(vp);
308             }
309 
310             var viewportMetas,
311                 elems = document.getElementsByName("viewport"),
312                 currentVP = elems ? elems[0] : null,
313                 content;
314 
315             vp = cc.newElement("meta");
316             vp.id = "cocosMetaElement";
317             vp.name = "viewport";
318             vp.content = "";
319 
320             viewportMetas = cc.__BrowserGetter.meta;
321 
322             content = currentVP ? currentVP.content : "";
323             for (var key in viewportMetas) {
324                 var pattern = new RegExp(key);
325                 if (!pattern.test(content)) {
326                     content += "," + key + "=" + viewportMetas[key];
327                 }
328             }
329             if(/^,/.test(content))
330                 content = content.substr(1);
331 
332             vp.content = content;
333             // For adopting certain android devices which don't support second viewport
334             if (currentVP)
335                 currentVP.content = content;
336 
337             document.head.appendChild(vp);
338         }
339     },
340 
341     // RenderTexture hacker
342     _setScaleXYForRenderTexture: function () {
343         //hack for RenderTexture on canvas mode when adapting multiple resolution resources
344         var scaleFactor = cc.contentScaleFactor();
345         this._scaleX = scaleFactor;
346         this._scaleY = scaleFactor;
347     },
348 
349     // Other helper functions
350     _resetScale: function () {
351         this._scaleX = this._originalScaleX;
352         this._scaleY = this._originalScaleY;
353     },
354 
355     // Useless, just make sure the compatibility temporarily, should be removed
356     _adjustSizeToBrowser: function () {
357     },
358 
359     initialize: function () {
360         this._initialized = true;
361     },
362 
363     /**
364      * Sets whether the engine modify the "viewport" meta in your web page.<br/>
365      * It's enabled by default, we strongly suggest you not to disable it.<br/>
366      * And even when it's enabled, you can still set your own "viewport" meta, it won't be overridden<br/>
367      * Only useful on web
368      * @param {Boolean} enabled Enable automatic modification to "viewport" meta
369      */
370     adjustViewPort: function (enabled) {
371         this._isAdjustViewPort = enabled;
372     },
373 
374 	/**
375 	 * Retina support is enabled by default for Apple device but disabled for other devices,<br/>
376 	 * it takes effect only when you called setDesignResolutionPolicy<br/>
377      * Only useful on web
378 	 * @param {Boolean} enabled  Enable or disable retina display
379 	 */
380 	enableRetina: function(enabled) {
381 		this._retinaEnabled = enabled ? true : false;
382 	},
383 
384 	/**
385 	 * Check whether retina display is enabled.<br/>
386      * Only useful on web
387 	 * @return {Boolean}
388 	 */
389 	isRetinaEnabled: function() {
390 		return this._retinaEnabled;
391 	},
392 
393     /**
394      * If enabled, the application will try automatically to enter full screen mode on mobile devices<br/>
395      * You can pass true as parameter to enable it and disable it by passing false.<br/>
396      * Only useful on web
397      * @param {Boolean} enabled  Enable or disable auto full screen on mobile devices
398      */
399     enableAutoFullScreen: function(enabled) {
400         this._autoFullScreen = enabled ? true : false;
401     },
402 
403     /**
404      * Check whether auto full screen is enabled.<br/>
405      * Only useful on web
406      * @return {Boolean} Auto full screen enabled or not
407      */
408     isAutoFullScreenEnabled: function() {
409         return this._autoFullScreen;
410     },
411 
412     /**
413      * Force destroying EGL view, subclass must implement this method.
414      */
415     end: function () {
416     },
417 
418     /**
419      * Get whether render system is ready(no matter opengl or canvas),<br/>
420      * this name is for the compatibility with cocos2d-x, subclass must implement this method.
421      * @return {Boolean}
422      */
423     isOpenGLReady: function () {
424         return (this._hDC !== null && this._hRC !== null);
425     },
426 
427     /*
428      * Set zoom factor for frame. This method is for debugging big resolution (e.g.new ipad) app on desktop.
429      * @param {Number} zoomFactor
430      */
431     setFrameZoomFactor: function (zoomFactor) {
432         this._frameZoomFactor = zoomFactor;
433         this.centerWindow();
434         cc.director.setProjection(cc.director.getProjection());
435     },
436 
437     /**
438      * Exchanges the front and back buffers, subclass must implement this method.
439      */
440     swapBuffers: function () {
441     },
442 
443     /**
444      * Open or close IME keyboard , subclass must implement this method.
445      * @param {Boolean} isOpen
446      */
447     setIMEKeyboardState: function (isOpen) {
448     },
449 
450     /**
451      * Sets the resolution translate on EGLView
452      * @param {Number} offsetLeft
453      * @param {Number} offsetTop
454      */
455     setContentTranslateLeftTop: function (offsetLeft, offsetTop) {
456         this._contentTranslateLeftTop = {left: offsetLeft, top: offsetTop};
457     },
458 
459     /**
460      * Returns the resolution translate on EGLView
461      * @return {cc.Size|Object}
462      */
463     getContentTranslateLeftTop: function () {
464         return this._contentTranslateLeftTop;
465     },
466 
467     /**
468      * Returns the frame size of the view.<br/>
469      * On native platforms, it returns the screen size since the view is a fullscreen view.<br/>
470      * On web, it returns the size of the canvas's outer DOM element.
471      * @return {cc.Size}
472      */
473     getFrameSize: function () {
474         return cc.size(this._frameSize.width, this._frameSize.height);
475     },
476 
477     /**
478      * On native, it sets the frame size of view.<br/>
479      * On web, it sets the size of the canvas's outer DOM element.
480      * @param {Number} width
481      * @param {Number} height
482      */
483     setFrameSize: function (width, height) {
484         this._frameSize.width = width;
485         this._frameSize.height = height;
486         this._frame.style.width = width + "px";
487         this._frame.style.height = height + "px";
488         //this.centerWindow();
489         this._resizeEvent();
490         cc.director.setProjection(cc.director.getProjection());
491     },
492 
493     /**
494      * Empty function
495      */
496     centerWindow: function () {
497     },
498 
499     /**
500      * Returns the visible area size of the view port.
501      * @return {cc.Size}
502      */
503     getVisibleSize: function () {
504         return cc.size(this._visibleRect.width,this._visibleRect.height);
505     },
506 
507     /**
508      * Returns the visible origin of the view port.
509      * @return {cc.Point}
510      */
511     getVisibleOrigin: function () {
512         return cc.p(this._visibleRect.x,this._visibleRect.y);
513     },
514 
515     /**
516      * Returns whether developer can set content's scale factor.
517      * @return {Boolean}
518      */
519     canSetContentScaleFactor: function () {
520         return true;
521     },
522 
523     /**
524      * Returns the current resolution policy
525      * @see cc.ResolutionPolicy
526      * @return {cc.ResolutionPolicy}
527      */
528     getResolutionPolicy: function () {
529         return this._resolutionPolicy;
530     },
531 
532     /**
533      * Sets the current resolution policy
534      * @see cc.ResolutionPolicy
535      * @param {cc.ResolutionPolicy|Number} resolutionPolicy
536      */
537     setResolutionPolicy: function (resolutionPolicy) {
538         var _t = this;
539         if (resolutionPolicy instanceof cc.ResolutionPolicy) {
540             _t._resolutionPolicy = resolutionPolicy;
541         }
542         // Ensure compatibility with JSB
543         else {
544             var _locPolicy = cc.ResolutionPolicy;
545             if(resolutionPolicy === _locPolicy.EXACT_FIT)
546                 _t._resolutionPolicy = _t._rpExactFit;
547             if(resolutionPolicy === _locPolicy.SHOW_ALL)
548                 _t._resolutionPolicy = _t._rpShowAll;
549             if(resolutionPolicy === _locPolicy.NO_BORDER)
550                 _t._resolutionPolicy = _t._rpNoBorder;
551             if(resolutionPolicy === _locPolicy.FIXED_HEIGHT)
552                 _t._resolutionPolicy = _t._rpFixedHeight;
553             if(resolutionPolicy === _locPolicy.FIXED_WIDTH)
554                 _t._resolutionPolicy = _t._rpFixedWidth;
555         }
556     },
557 
558     /**
559      * Sets the resolution policy with designed view size in points.<br/>
560      * The resolution policy include: <br/>
561      * [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/>
562      * [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/>
563      * [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/>
564      * [4] ResolutionFixedHeight    Scale the content's height to screen's height and proportionally scale its width<br/>
565      * [5] ResolutionFixedWidth     Scale the content's width to screen's width and proportionally scale its height<br/>
566      * [cc.ResolutionPolicy]        [Web only feature] Custom resolution policy, constructed by cc.ResolutionPolicy<br/>
567      * @param {Number} width Design resolution width.
568      * @param {Number} height Design resolution height.
569      * @param {cc.ResolutionPolicy|Number} resolutionPolicy The resolution policy desired
570      */
571     setDesignResolutionSize: function (width, height, resolutionPolicy) {
572         // Defensive code
573         if( !(width > 0 || height > 0) ){
574             cc.log(cc._LogInfos.EGLView_setDesignResolutionSize);
575             return;
576         }
577 
578         this.setResolutionPolicy(resolutionPolicy);
579         var policy = this._resolutionPolicy;
580         if (!policy){
581             cc.log(cc._LogInfos.EGLView_setDesignResolutionSize_2);
582             return;
583         }
584         policy.preApply(this);
585 
586         // Reinit frame size
587         if(cc.sys.isMobile)
588             this._setViewPortMeta();
589 
590         this._initFrameSize();
591 
592         this._originalDesignResolutionSize.width = this._designResolutionSize.width = width;
593         this._originalDesignResolutionSize.height = this._designResolutionSize.height = height;
594 
595         var result = policy.apply(this, this._designResolutionSize);
596 
597         if(result.scale && result.scale.length === 2){
598             this._scaleX = result.scale[0];
599             this._scaleY = result.scale[1];
600         }
601 
602         if(result.viewport){
603             var vp = this._viewPortRect,
604                 vb = this._visibleRect,
605                 rv = result.viewport;
606 
607             vp.x = rv.x;
608             vp.y = rv.y;
609             vp.width = rv.width;
610             vp.height = rv.height;
611 
612             vb.x = -vp.x / this._scaleX;
613             vb.y = -vp.y / this._scaleY;
614             vb.width = cc._canvas.width / this._scaleX;
615             vb.height = cc._canvas.height / this._scaleY;
616             cc._renderContext.setOffset && cc._renderContext.setOffset(vp.x, -vp.y)
617         }
618 
619         // reset director's member variables to fit visible rect
620         var director = cc.director;
621         director._winSizeInPoints.width = this._designResolutionSize.width;
622         director._winSizeInPoints.height = this._designResolutionSize.height;
623         policy.postApply(this);
624         cc.winSize.width = director._winSizeInPoints.width;
625         cc.winSize.height = director._winSizeInPoints.height;
626 
627         if (cc._renderType === cc._RENDER_TYPE_WEBGL) {
628             // reset director's member variables to fit visible rect
629             director._createStatsLabel();
630             director.setGLDefaultValues();
631         }
632 
633         this._originalScaleX = this._scaleX;
634         this._originalScaleY = this._scaleY;
635         // For editbox
636         if (cc.DOM)
637             cc.DOM._resetEGLViewDiv();
638         cc.visibleRect && cc.visibleRect.init(this._visibleRect);
639     },
640 
641     /**
642      * Returns the designed size for the view.
643      * Default resolution size is the same as 'getFrameSize'.
644      * @return {cc.Size}
645      */
646     getDesignResolutionSize: function () {
647         return cc.size(this._designResolutionSize.width, this._designResolutionSize.height);
648     },
649 
650     /**
651      * Sets view port rectangle with points.
652      * @param {Number} x
653      * @param {Number} y
654      * @param {Number} w width
655      * @param {Number} h height
656      */
657     setViewPortInPoints: function (x, y, w, h) {
658         var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
659         cc._renderContext.viewport((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
660             (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
661             (w * locScaleX * locFrameZoomFactor),
662             (h * locScaleY * locFrameZoomFactor));
663     },
664 
665     /**
666      * Sets Scissor rectangle with points.
667      * @param {Number} x
668      * @param {Number} y
669      * @param {Number} w
670      * @param {Number} h
671      */
672     setScissorInPoints: function (x, y, w, h) {
673         var locFrameZoomFactor = this._frameZoomFactor, locScaleX = this._scaleX, locScaleY = this._scaleY;
674         cc._renderContext.scissor((x * locScaleX * locFrameZoomFactor + this._viewPortRect.x * locFrameZoomFactor),
675             (y * locScaleY * locFrameZoomFactor + this._viewPortRect.y * locFrameZoomFactor),
676             (w * locScaleX * locFrameZoomFactor),
677             (h * locScaleY * locFrameZoomFactor));
678     },
679 
680     /**
681      * Returns whether GL_SCISSOR_TEST is enable
682      * @return {Boolean}
683      */
684     isScissorEnabled: function () {
685         var gl = cc._renderContext;
686         return gl.isEnabled(gl.SCISSOR_TEST);
687     },
688 
689     /**
690      * Returns the current scissor rectangle
691      * @return {cc.Rect}
692      */
693     getScissorRect: function () {
694         var gl = cc._renderContext, scaleX = this._scaleX, scaleY = this._scaleY;
695         var boxArr = gl.getParameter(gl.SCISSOR_BOX);
696         return cc.rect((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / scaleY,
697             boxArr[2] / scaleX, boxArr[3] / scaleY);
698     },
699 
700     /**
701      * Sets the name of the view
702      * @param {String} viewName
703      */
704     setViewName: function (viewName) {
705         if (viewName != null && viewName.length > 0) {
706             this._viewName = viewName;
707         }
708     },
709 
710     /**
711      * Returns the name of the view
712      * @return {String}
713      */
714     getViewName: function () {
715         return this._viewName;
716     },
717 
718     /**
719      * Returns the view port rectangle.
720      * @return {cc.Rect}
721      */
722     getViewPortRect: function () {
723         return this._viewPortRect;
724     },
725 
726     /**
727      * Returns scale factor of the horizontal direction (X axis).
728      * @return {Number}
729      */
730     getScaleX: function () {
731         return this._scaleX;
732     },
733 
734     /**
735      * Returns scale factor of the vertical direction (Y axis).
736      * @return {Number}
737      */
738     getScaleY: function () {
739         return this._scaleY;
740     },
741 
742     /**
743      * Returns device pixel ratio for retina display.
744      * @return {Number}
745      */
746     getDevicePixelRatio: function() {
747         return this._devicePixelRatio;
748     },
749 
750     /**
751      * Returns the real location in view for a translation based on a related position
752      * @param {Number} tx The X axis translation
753      * @param {Number} ty The Y axis translation
754      * @param {Object} relatedPos The related position object including "left", "top", "width", "height" informations
755      * @return {cc.Point}
756      */
757     convertToLocationInView: function (tx, ty, relatedPos) {
758         return {x: this._devicePixelRatio * (tx - relatedPos.left), y: this._devicePixelRatio * (relatedPos.top + relatedPos.height - ty)};
759     },
760 
761     _convertMouseToLocationInView: function(point, relatedPos) {
762         var locViewPortRect = this._viewPortRect, _t = this;
763         point.x = ((_t._devicePixelRatio * (point.x - relatedPos.left)) - locViewPortRect.x) / _t._scaleX;
764         point.y = (_t._devicePixelRatio * (relatedPos.top + relatedPos.height - point.y) - locViewPortRect.y) / _t._scaleY;
765     },
766 
767     _convertTouchesWithScale: function(touches){
768         var locViewPortRect = this._viewPortRect, locScaleX = this._scaleX, locScaleY = this._scaleY, selTouch, selPoint, selPrePoint;
769         for( var i = 0; i < touches.length; i ++){
770             selTouch = touches[i];
771             selPoint = selTouch._point;
772 	        selPrePoint = selTouch._prevPoint;
773             selTouch._setPoint((selPoint.x - locViewPortRect.x) / locScaleX,
774                 (selPoint.y - locViewPortRect.y) / locScaleY);
775             selTouch._setPrevPoint((selPrePoint.x - locViewPortRect.x) / locScaleX,
776                 (selPrePoint.y - locViewPortRect.y) / locScaleY);
777         }
778     }
779 });
780 
781 /**
782  * @function
783  * @return {cc.EGLView}
784  * @private
785  */
786 cc.EGLView._getInstance = function () {
787     if (!this._instance) {
788         this._instance = this._instance || new cc.EGLView();
789         this._instance.initialize();
790     }
791     return this._instance;
792 };
793 
794 /**
795  * <p>cc.ContainerStrategy class is the root strategy class of container's scale strategy,
796  * it controls the behavior of how to scale the cc.container and cc._canvas object</p>
797  *
798  * @class
799  * @extends cc.Class
800  */
801 cc.ContainerStrategy = cc.Class.extend(/** @lends cc.ContainerStrategy# */{
802     /**
803      * Manipulation before appling the strategy
804      * @param {cc.view} The target view
805      */
806     preApply: function (view) {
807     },
808 
809     /**
810      * Function to apply this strategy
811      * @param {cc.view} view
812      * @param {cc.Size} designedResolution
813      */
814     apply: function (view, designedResolution) {
815     },
816 
817     /**
818      * Manipulation after applying the strategy
819      * @param {cc.view} view  The target view
820      */
821     postApply: function (view) {
822 
823     },
824 
825     _setupContainer: function (view, w, h) {
826         var frame = view._frame;
827         if (cc.view._autoFullScreen && cc.sys.isMobile && frame === document.documentElement) {
828             // Automatically full screen when user touches on mobile version
829             cc.screen.autoFullScreen(frame);
830         }
831 
832         var locCanvasElement = cc._canvas, locContainer = cc.container;
833         // Setup container
834         locContainer.style.width = locCanvasElement.style.width = w + "px";
835         locContainer.style.height = locCanvasElement.style.height = h + "px";
836         // Setup pixel ratio for retina display
837         var devicePixelRatio = view._devicePixelRatio = 1;
838         if (view.isRetinaEnabled())
839             devicePixelRatio = view._devicePixelRatio = window.devicePixelRatio || 1;
840         // Setup canvas
841         locCanvasElement.width = w * devicePixelRatio;
842         locCanvasElement.height = h * devicePixelRatio;
843         cc._renderContext.resetCache && cc._renderContext.resetCache();
844 
845         var body = document.body, style;
846         if (body && (style = body.style)) {
847             style.paddingTop = style.paddingTop || "0px";
848             style.paddingRight = style.paddingRight || "0px";
849             style.paddingBottom = style.paddingBottom || "0px";
850             style.paddingLeft = style.paddingLeft || "0px";
851             style.borderTop = style.borderTop || "0px";
852             style.borderRight = style.borderRight || "0px";
853             style.borderBottom = style.borderBottom || "0px";
854             style.borderLeft = style.borderLeft || "0px";
855             style.marginTop = style.marginTop || "0px";
856             style.marginRight = style.marginRight || "0px";
857             style.marginBottom = style.marginBottom || "0px";
858             style.marginLeft = style.marginLeft || "0px";
859         }
860     },
861 
862     _fixContainer: function () {
863         // Add container to document body
864         document.body.insertBefore(cc.container, document.body.firstChild);
865         // Set body's width height to window's size, and forbid overflow, so that game will be centered
866         var bs = document.body.style;
867         bs.width = window.innerWidth + "px";
868         bs.height = window.innerHeight + "px";
869         bs.overflow = "hidden";
870         // Body size solution doesn't work on all mobile browser so this is the aleternative: fixed container
871         var contStyle = cc.container.style;
872         contStyle.position = "fixed";
873         contStyle.left = contStyle.top = "0px";
874         // Reposition body
875         document.body.scrollTop = 0;
876     }
877 });
878 
879 /**
880  * <p>cc.ContentStrategy class is the root strategy class of content's scale strategy,
881  * it controls the behavior of how to scale the scene and setup the viewport for the game</p>
882  *
883  * @class
884  * @extends cc.Class
885  */
886 cc.ContentStrategy = cc.Class.extend(/** @lends cc.ContentStrategy# */{
887 
888     _result: {
889         scale: [1, 1],
890         viewport: null
891     },
892 
893     _buildResult: function (containerW, containerH, contentW, contentH, scaleX, scaleY) {
894 	    // Makes content fit better the canvas
895 	    Math.abs(containerW - contentW) < 2 && (contentW = containerW);
896 	    Math.abs(containerH - contentH) < 2 && (contentH = containerH);
897 
898         var viewport = cc.rect(Math.round((containerW - contentW) / 2),
899                                Math.round((containerH - contentH) / 2),
900                                contentW, contentH);
901 
902         // Translate the content
903         if (cc._renderType === cc._RENDER_TYPE_CANVAS){
904             //TODO: modify something for setTransform
905             //cc._renderContext.translate(viewport.x, viewport.y + contentH);
906         }
907 
908         this._result.scale = [scaleX, scaleY];
909         this._result.viewport = viewport;
910         return this._result;
911     },
912 
913     /**
914      * Manipulation before applying the strategy
915      * @param {cc.view} view The target view
916      */
917     preApply: function (view) {
918     },
919 
920     /**
921      * Function to apply this strategy
922      * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
923      * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
924      * @param {cc.view} view
925      * @param {cc.Size} designedResolution
926      * @return {object} scaleAndViewportRect
927      */
928     apply: function (view, designedResolution) {
929         return {"scale": [1, 1]};
930     },
931 
932     /**
933      * Manipulation after applying the strategy
934      * @param {cc.view} view The target view
935      */
936     postApply: function (view) {
937     }
938 });
939 
940 (function () {
941 
942 // Container scale strategys
943     /**
944      * @class
945      * @extends cc.ContainerStrategy
946      */
947     var EqualToFrame = cc.ContainerStrategy.extend({
948         apply: function (view) {
949             this._setupContainer(view, view._frameSize.width, view._frameSize.height);
950         }
951     });
952 
953     /**
954      * @class
955      * @extends cc.ContainerStrategy
956      */
957     var ProportionalToFrame = cc.ContainerStrategy.extend({
958         apply: function (view, designedResolution) {
959             var frameW = view._frameSize.width, frameH = view._frameSize.height, containerStyle = cc.container.style,
960                 designW = designedResolution.width, designH = designedResolution.height,
961                 scaleX = frameW / designW, scaleY = frameH / designH,
962                 containerW, containerH;
963 
964             scaleX < scaleY ? (containerW = frameW, containerH = designH * scaleX) : (containerW = designW * scaleY, containerH = frameH);
965 
966             // Adjust container size with integer value
967             var offx = Math.round((frameW - containerW) / 2);
968             var offy = Math.round((frameH - containerH) / 2);
969             containerW = frameW - 2 * offx;
970             containerH = frameH - 2 * offy;
971 
972             this._setupContainer(view, containerW, containerH);
973             // Setup container's margin
974             containerStyle.marginLeft = offx + "px";
975             containerStyle.marginRight = offx + "px";
976             containerStyle.marginTop = offy + "px";
977             containerStyle.marginBottom = offy + "px";
978         }
979     });
980 
981     /**
982      * @class
983      * @extends EqualToFrame
984      */
985     var EqualToWindow = EqualToFrame.extend({
986         preApply: function (view) {
987 	        this._super(view);
988             view._frame = document.documentElement;
989         },
990 
991         apply: function (view) {
992             this._super(view);
993             this._fixContainer();
994         }
995     });
996 
997     /**
998      * @class
999      * @extends ProportionalToFrame
1000      */
1001     var ProportionalToWindow = ProportionalToFrame.extend({
1002         preApply: function (view) {
1003 	        this._super(view);
1004             view._frame = document.documentElement;
1005         },
1006 
1007         apply: function (view, designedResolution) {
1008             this._super(view, designedResolution);
1009             this._fixContainer();
1010         }
1011     });
1012 
1013     /**
1014      * @class
1015      * @extends cc.ContainerStrategy
1016      */
1017     var OriginalContainer = cc.ContainerStrategy.extend({
1018         apply: function (view) {
1019             this._setupContainer(view, cc._canvas.width, cc._canvas.height);
1020         }
1021     });
1022 
1023 // #NOT STABLE on Android# Alias: Strategy that makes the container's size equals to the window's size
1024 //    cc.ContainerStrategy.EQUAL_TO_WINDOW = new EqualToWindow();
1025 // #NOT STABLE on Android# Alias: Strategy that scale proportionally the container's size to window's size
1026 //    cc.ContainerStrategy.PROPORTION_TO_WINDOW = new ProportionalToWindow();
1027 // Alias: Strategy that makes the container's size equals to the frame's size
1028     cc.ContainerStrategy.EQUAL_TO_FRAME = new EqualToFrame();
1029 // Alias: Strategy that scale proportionally the container's size to frame's size
1030     cc.ContainerStrategy.PROPORTION_TO_FRAME = new ProportionalToFrame();
1031 // Alias: Strategy that keeps the original container's size
1032     cc.ContainerStrategy.ORIGINAL_CONTAINER = new OriginalContainer();
1033 
1034 // Content scale strategys
1035     var ExactFit = cc.ContentStrategy.extend({
1036         apply: function (view, designedResolution) {
1037             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1038                 scaleX = containerW / designedResolution.width, scaleY = containerH / designedResolution.height;
1039 
1040             return this._buildResult(containerW, containerH, containerW, containerH, scaleX, scaleY);
1041         }
1042     });
1043 
1044     var ShowAll = cc.ContentStrategy.extend({
1045         apply: function (view, designedResolution) {
1046             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1047                 designW = designedResolution.width, designH = designedResolution.height,
1048                 scaleX = containerW / designW, scaleY = containerH / designH, scale = 0,
1049                 contentW, contentH;
1050 
1051 	        scaleX < scaleY ? (scale = scaleX, contentW = containerW, contentH = designH * scale)
1052                 : (scale = scaleY, contentW = designW * scale, contentH = containerH);
1053 
1054             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1055         }
1056     });
1057 
1058     var NoBorder = cc.ContentStrategy.extend({
1059         apply: function (view, designedResolution) {
1060             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1061                 designW = designedResolution.width, designH = designedResolution.height,
1062                 scaleX = containerW / designW, scaleY = containerH / designH, scale,
1063                 contentW, contentH;
1064 
1065             scaleX < scaleY ? (scale = scaleY, contentW = designW * scale, contentH = containerH)
1066                 : (scale = scaleX, contentW = containerW, contentH = designH * scale);
1067 
1068             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1069         }
1070     });
1071 
1072     var FixedHeight = cc.ContentStrategy.extend({
1073         apply: function (view, designedResolution) {
1074             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1075                 designH = designedResolution.height, scale = containerH / designH,
1076                 contentW = containerW, contentH = containerH;
1077 
1078             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1079         },
1080 
1081         postApply: function (view) {
1082             cc.director._winSizeInPoints = view.getVisibleSize();
1083         }
1084     });
1085 
1086     var FixedWidth = cc.ContentStrategy.extend({
1087         apply: function (view, designedResolution) {
1088             var containerW = cc._canvas.width, containerH = cc._canvas.height,
1089                 designW = designedResolution.width, scale = containerW / designW,
1090                 contentW = containerW, contentH = containerH;
1091 
1092             return this._buildResult(containerW, containerH, contentW, contentH, scale, scale);
1093         },
1094 
1095         postApply: function (view) {
1096             cc.director._winSizeInPoints = view.getVisibleSize();
1097         }
1098     });
1099 
1100 // Alias: Strategy to scale the content's size to container's size, non proportional
1101     cc.ContentStrategy.EXACT_FIT = new ExactFit();
1102 // Alias: Strategy to scale the content's size proportionally to maximum size and keeps the whole content area to be visible
1103     cc.ContentStrategy.SHOW_ALL = new ShowAll();
1104 // Alias: Strategy to scale the content's size proportionally to fill the whole container area
1105     cc.ContentStrategy.NO_BORDER = new NoBorder();
1106 // Alias: Strategy to scale the content's height to container's height and proportionally scale its width
1107     cc.ContentStrategy.FIXED_HEIGHT = new FixedHeight();
1108 // Alias: Strategy to scale the content's width to container's width and proportionally scale its height
1109     cc.ContentStrategy.FIXED_WIDTH = new FixedWidth();
1110 
1111 })();
1112 
1113 /**
1114  * <p>cc.ResolutionPolicy class is the root strategy class of scale strategy,
1115  * its main task is to maintain the compatibility with Cocos2d-x</p>
1116  *
1117  * @class
1118  * @extends cc.Class
1119  * @param {cc.ContainerStrategy} containerStg The container strategy
1120  * @param {cc.ContentStrategy} contentStg The content strategy
1121  */
1122 cc.ResolutionPolicy = cc.Class.extend(/** @lends cc.ResolutionPolicy# */{
1123 	_containerStrategy: null,
1124     _contentStrategy: null,
1125 
1126     /**
1127      * Constructor of cc.ResolutionPolicy
1128      * @param {cc.ContainerStrategy} containerStg
1129      * @param {cc.ContentStrategy} contentStg
1130      */
1131     ctor: function (containerStg, contentStg) {
1132         this.setContainerStrategy(containerStg);
1133         this.setContentStrategy(contentStg);
1134     },
1135 
1136     /**
1137      * Manipulation before applying the resolution policy
1138      * @param {cc.view} view The target view
1139      */
1140     preApply: function (view) {
1141         this._containerStrategy.preApply(view);
1142         this._contentStrategy.preApply(view);
1143     },
1144 
1145     /**
1146      * Function to apply this resolution policy
1147      * The return value is {scale: [scaleX, scaleY], viewport: {cc.Rect}},
1148      * The target view can then apply these value to itself, it's preferred not to modify directly its private variables
1149      * @param {cc.view} view The target view
1150      * @param {cc.Size} designedResolution The user defined design resolution
1151      * @return {object} An object contains the scale X/Y values and the viewport rect
1152      */
1153     apply: function (view, designedResolution) {
1154         this._containerStrategy.apply(view, designedResolution);
1155         return this._contentStrategy.apply(view, designedResolution);
1156     },
1157 
1158     /**
1159      * Manipulation after appyling the strategy
1160      * @param {cc.view} view The target view
1161      */
1162     postApply: function (view) {
1163         this._containerStrategy.postApply(view);
1164         this._contentStrategy.postApply(view);
1165     },
1166 
1167     /**
1168      * Setup the container's scale strategy
1169      * @param {cc.ContainerStrategy} containerStg
1170      */
1171     setContainerStrategy: function (containerStg) {
1172         if (containerStg instanceof cc.ContainerStrategy)
1173             this._containerStrategy = containerStg;
1174     },
1175 
1176     /**
1177      * Setup the content's scale strategy
1178      * @param {cc.ContentStrategy} contentStg
1179      */
1180     setContentStrategy: function (contentStg) {
1181         if (contentStg instanceof cc.ContentStrategy)
1182             this._contentStrategy = contentStg;
1183     }
1184 });
1185 
1186 /**
1187  * @memberOf cc.ResolutionPolicy#
1188  * @name EXACT_FIT
1189  * @constant
1190  * @type Number
1191  * @static
1192  * The entire application is visible in the specified area without trying to preserve the original aspect ratio.<br/>
1193  * Distortion can occur, and the application may appear stretched or compressed.
1194  */
1195 cc.ResolutionPolicy.EXACT_FIT = 0;
1196 
1197 /**
1198  * @memberOf cc.ResolutionPolicy#
1199  * @name NO_BORDER
1200  * @constant
1201  * @type Number
1202  * @static
1203  * The entire application fills the specified area, without distortion but possibly with some cropping,<br/>
1204  * while maintaining the original aspect ratio of the application.
1205  */
1206 cc.ResolutionPolicy.NO_BORDER = 1;
1207 
1208 /**
1209  * @memberOf cc.ResolutionPolicy#
1210  * @name SHOW_ALL
1211  * @constant
1212  * @type Number
1213  * @static
1214  * The entire application is visible in the specified area without distortion while maintaining the original<br/>
1215  * aspect ratio of the application. Borders can appear on two sides of the application.
1216  */
1217 cc.ResolutionPolicy.SHOW_ALL = 2;
1218 
1219 /**
1220  * @memberOf cc.ResolutionPolicy#
1221  * @name FIXED_HEIGHT
1222  * @constant
1223  * @type Number
1224  * @static
1225  * The application takes the height of the design resolution size and modifies the width of the internal<br/>
1226  * canvas so that it fits the aspect ratio of the device<br/>
1227  * no distortion will occur however you must make sure your application works on different<br/>
1228  * aspect ratios
1229  */
1230 cc.ResolutionPolicy.FIXED_HEIGHT = 3;
1231 
1232 /**
1233  * @memberOf cc.ResolutionPolicy#
1234  * @name FIXED_WIDTH
1235  * @constant
1236  * @type Number
1237  * @static
1238  * The application takes the width of the design resolution size and modifies the height of the internal<br/>
1239  * canvas so that it fits the aspect ratio of the device<br/>
1240  * no distortion will occur however you must make sure your application works on different<br/>
1241  * aspect ratios
1242  */
1243 cc.ResolutionPolicy.FIXED_WIDTH = 4;
1244 
1245 /**
1246  * @memberOf cc.ResolutionPolicy#
1247  * @name UNKNOWN
1248  * @constant
1249  * @type Number
1250  * @static
1251  * Unknow policy
1252  */
1253 cc.ResolutionPolicy.UNKNOWN = 5;