Handle canvas clip antialiasing during reprojection

This commit is contained in:
Petr Sloup
2015-08-13 15:01:58 +02:00
parent 3cc8291df4
commit 4c236a64b8

View File

@@ -1,6 +1,8 @@
goog.provide('ol.reproj');
goog.require('goog.array');
goog.require('goog.labs.userAgent.browser');
goog.require('goog.labs.userAgent.platform');
goog.require('goog.math');
goog.require('ol.dom');
goog.require('ol.extent');
@@ -58,6 +60,20 @@ ol.reproj.WrapXRendering_ = {
};
/**
* We need to employ more sophisticated solution
* if the web browser antialiases clipping edges on canvas.
*
* Currently only Chrome does not antialias the edges, but this is probably
* going to be "fixed" in the future: http://crbug.com/424291
*
* @type {boolean}
* @private
*/
ol.reproj.browserAntialiasesClip_ = !goog.labs.userAgent.browser.isChrome() ||
goog.labs.userAgent.platform.isIos();
/**
* Renders the source into the canvas based on the triangulation.
* @param {CanvasRenderingContext2D} context
@@ -154,8 +170,6 @@ ol.reproj.renderTriangles = function(context,
var targetTL = ol.extent.getTopLeft(targetExtent);
context.globalCompositeOperation = 'copy';
goog.array.forEach(triangulation.getTriangles(), function(tri, i, arr) {
context.save();
@@ -229,25 +243,29 @@ ol.reproj.renderTriangles = function(context,
return;
}
var centroidX = (u0 + u1 + u2) / 3, centroidY = (v0 + v1 + v2) / 3;
var calcClipPoint = function(u, v) {
// Enlarges the triangle by 1 pixel to ensure overlap and rounds to whole
// pixels to ensure correct cross-browser behavior.
// Gecko does antialiasing differently than WebKit.
var dX = u - centroidX, dY = v - centroidY;
var distance = Math.sqrt(dX * dX + dY * dY);
return [Math.round(u + dX / distance), Math.round(v + dY / distance)];
};
var p0 = calcClipPoint(u0, v0);
var p1 = calcClipPoint(u1, v1);
var p2 = calcClipPoint(u2, v2);
context.beginPath();
context.moveTo(p0[0], p0[1]);
context.lineTo(p1[0], p1[1]);
context.lineTo(p2[0], p2[1]);
if (ol.reproj.browserAntialiasesClip_) {
// Enlarge the clipping triangle by 1 pixel to ensure the edges overlap
// in order to mask gaps caused by antialiasing.
var centroidX = (u0 + u1 + u2) / 3, centroidY = (v0 + v1 + v2) / 3;
var calcClipPoint = function(u, v) {
var dX = u - centroidX, dY = v - centroidY;
var distance = Math.sqrt(dX * dX + dY * dY);
return [Math.round(u + dX / distance), Math.round(v + dY / distance)];
};
var p0 = calcClipPoint(u0, v0);
var p1 = calcClipPoint(u1, v1);
var p2 = calcClipPoint(u2, v2);
context.moveTo(p0[0], p0[1]);
context.lineTo(p1[0], p1[1]);
context.lineTo(p2[0], p2[1]);
} else {
context.moveTo(u0, v0);
context.lineTo(u1, v1);
context.lineTo(u2, v2);
}
context.closePath();
context.clip();
@@ -266,8 +284,6 @@ ol.reproj.renderTriangles = function(context,
if (opt_renderEdges) {
context.save();
context.globalCompositeOperation = 'source-over';
context.strokeStyle = 'black';
context.lineWidth = 1;