/*
 * L.Handler.TouchZoom is used internally by L.Map to add touch-zooming on Webkit-powered mobile browsers.
 */

L.Map.mergeOptions({
	touchZoom: L.Browser.touch && !L.Browser.android
});

L.Map.TouchZoom = L.Handler.extend({
	addHooks: function () {
		L.DomEvent.addListener(this._map._container, 'touchstart', this._onTouchStart, this);
	},

	removeHooks: function () {
		L.DomEvent.removeListener(this._map._container, 'touchstart', this._onTouchStart, this);
	},

	_onTouchStart: function (e) {
		var map = this._map;

		if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; }

		var p1 = map.mouseEventToLayerPoint(e.touches[0]),
			p2 = map.mouseEventToLayerPoint(e.touches[1]),
			viewCenter = map.containerPointToLayerPoint(map.getSize().divideBy(2));

		this._startCenter = p1.add(p2).divideBy(2, true);
		this._startLatLng = this._map.layerPointToLatLng(this._startCenter);
		console.log("center: " + this._startLatLng);
		this._startDist = p1.distanceTo(p2);

		this._moved = false;
		this._zooming = true;

		this._centerOffset = viewCenter.subtract(this._startCenter);

		L.DomEvent
			.addListener(document, 'touchmove', this._onTouchMove, this)
			.addListener(document, 'touchend', this._onTouchEnd, this);

		L.DomEvent.preventDefault(e);
	},

	_onTouchMove: function (e) {
		if (!e.touches || e.touches.length !== 2) { return; }

		var map = this._map;

		var p1 = map.mouseEventToLayerPoint(e.touches[0]),
			p2 = map.mouseEventToLayerPoint(e.touches[1]);

		this._scale = p1.distanceTo(p2) / this._startDist;
		this._delta = p1.add(p2).divideBy(2, true).subtract(this._startCenter);

		if (this._scale === 1) { return; }

		var zoom = this._map._zoom + Math.log(this._scale) / Math.log(2);

		//console.log("scale: " + this._scale);
		console.log("zoom: " + zoom);
		console.log("newTopLeft: " + this._map._getNewTopLeftPoint(this._startLatLng, zoom));

		if (!this._moved) {
			map._mapPane.className += ' leaflet-zoom-anim leaflet-touching';

			map
				//.fire('zoomstart', { center: center, zoom: zoom, newTopLeft: this._map._getNewTopLeftPoint(center, zoom) })
			.fire('zoomstart', { center: this._startLatLng, zoom: zoom, newTopLeft: this._map._getNewTopLeftPoint(this._startLatLng, zoom) })
			.fire('movestart')
				._prepareTileBg();

			this._moved = true;
		} else {
			map.fire('zoomstart', { center: this._startLatLng, zoom: zoom, newTopLeft: this._map._getNewTopLeftPoint(this._startLatLng, zoom) });
		}

		// Used 2 translates instead of transform-origin because of a very strange bug -
		// it didn't count the origin on the first touch-zoom but worked correctly afterwards

		map._tileBg.style.webkitTransform =
			L.DomUtil.getTranslateString(this._delta) + ' ' +
            L.DomUtil.getScaleString(this._scale, this._startCenter);

		L.DomEvent.preventDefault(e);
	},

	_onTouchEnd: function (e) {
		if (!this._moved || !this._zooming) { return; }

		this._zooming = false;
		this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-touching', ''); //TODO toggleClass util

		L.DomEvent
			.removeListener(document, 'touchmove', this._onTouchMove)
			.removeListener(document, 'touchend', this._onTouchEnd);

		var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale),
			centerPoint = this._map.getPixelOrigin().add(this._startCenter).add(centerOffset),
			center = this._map.unproject(centerPoint),

			oldZoom = this._map.getZoom(),
			floatZoomDelta = Math.log(this._scale) / Math.LN2,
			roundZoomDelta = (floatZoomDelta > 0 ? Math.ceil(floatZoomDelta) : Math.floor(floatZoomDelta)),
			zoom = this._map._limitZoom(oldZoom + roundZoomDelta),
			finalScale = Math.pow(2, zoom - oldZoom);

		this._map._runAnimation(center, zoom, finalScale / this._scale, this._startCenter.add(centerOffset), true);
	}
});

L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom);
@@ -849,126 +849,8 @@
 e);%0A
-%09%09this._startLatLng = this._map.layerPointToLatLng(this._startCenter);%0A%09%09console.log(%22center: %22 + this._startLatLng);%0A
 %09%09th
@@ -1631,110 +1631,107 @@
 %0A%0A%09%09
-//console.log(%22scale: %22 + this._scale);%0A%09%09console.log(%22zoom: %22 + zoom);%0A%09%09console.log(%22newTopLeft: %22 +
+var centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale),%0A%09%09%09centerPoint =
  thi
@@ -1741,52 +1741,110 @@
 map.
-_
 get
-NewTopLeftPoint(this._startLatLng, zoom)
+PixelOrigin().add(this._startCenter).add(centerOffset),%0A%09%09%09center = this._map.unproject(centerPoint
 );%0A%0A
@@ -1945,18 +1945,16 @@
 map%0A%09%09%09%09
-//
 .fire('z
@@ -2058,140 +2058,8 @@
 %7D)%0A%09
-%09%09.fire('zoomstart', %7B center: this._startLatLng, zoom: zoom, newTopLeft: this._map._getNewTopLeftPoint(this._startLatLng, zoom) %7D)%0A
 %09%09%09.
@@ -2169,33 +2169,22 @@
 center: 
-this._startLatLng
+center
 , zoom: 
@@ -2235,25 +2235,14 @@
 int(
-this._startLatLng
+center
 , zo
@@ -3491,24 +3491,145 @@
  oldZoom);%0A%0A
+%09%09this._map.fire('zoomstart', %7B center: center, zoom: zoom, newTopLeft: this._map._getNewTopLeftPoint(center, zoom) %7D);%0A%0A
 %09%09this._map.

Fix up TouchZoom free-zoom. 'zoomstart' event is abused a bit now, might need to fix that.