Clearing for 2DRenderer of polygons now implemented, except for the way transparencey is done 2D and GL renderers produce identical results. Fixed code to only clear on layers with clearing polygons.
Clearing for 2DRenderer of polygons now implemented, except for the way transparencey is done 2D and GL renderers produce identical results. Fixed code to only clear on layers with clearing polygons.

--- a/src/js/circuit/PCB/Element.js
+++ b/src/js/circuit/PCB/Element.js
@@ -88,6 +88,8 @@
 			ctx.restore();
 		};
 
+		Element.prototype.clear = function(ctx){};
+
 		Element.prototype.renderText = function(gl, shaderProgram){
 
 			var sym, rot, mvMatrix;

--- a/src/js/circuit/PCB/ElementArc.js
+++ b/src/js/circuit/PCB/ElementArc.js
@@ -47,7 +47,9 @@
 			ctx.closePath();
 	
 		};
-	
+
+		ElementArc.prototype.clear = function(ctx){};
+
 		ElementArc.prototype.renderGL = function(gl, shaderProgram){
 	
 			var outerRadius, innerRadius, radiusRatio;

--- a/src/js/circuit/PCB/ElementLine.js
+++ b/src/js/circuit/PCB/ElementLine.js
@@ -10,27 +10,46 @@
 
 	};
 
+	ElementLine.prototype._createCache = function(){
+
+		this._cache = {};
+
+		this._cache.x1 = this.x1;
+		this._cache.y1 = this.y1;
+		this._cache.x2 = this.x2;
+		this._cache.y2 = this.y2;
+		if(this.parent){
+			this._cache.x1 += this.parent.mx;
+			this._cache.y1 += this.parent.my;
+			this._cache.x2 += this.parent.mx;
+			this._cache.y2 += this.parent.my;
+		}
+
+	};
+
+	ElementLine.prototype._prepareRender = function(ctx, thick){
+
+		if(!this._cache) this._createCache();
+
+		ctx.lineCap = 'round';
+		ctx.lineWidth = thick;
+
+		ctx.beginPath();
+		ctx.moveTo(this._cache.x1, this._cache.y1);
+		ctx.lineTo(this._cache.x2, this._cache.y2);
+
+	};
+
 	ElementLine.prototype.render = function(ctx, color) {
 
-		var x1 = this.x1, y1 = this.y1, x2 = this.x2, y2 = this.y2;
-		
-		if(this.parent){
-			x1 += this.parent.mx;
-			y1 += this.parent.my;
-			x2 += this.parent.mx;
-			y2 += this.parent.my;
-		}
-
-		ctx.beginPath();
-		ctx.moveTo(x1, y1);
-		ctx.lineTo(x2, y2);
-		ctx.lineCap = 'round';
-		ctx.lineWidth = this.thick;
 		ctx.strokeStyle = color;
+		this._prepareRender(ctx, this.thick, color);
 		ctx.stroke();
 		ctx.closePath();
 
 	};
+
+	ElementLine.prototype.clear = function(ctx){};
 
 	ElementLine.prototype.renderGL = function(gl, shaderProgram){
 
@@ -39,11 +58,6 @@
 		gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.vertexBuffer.numItems);
 
 		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
-
-		//gl.lineWidth(this.thick * gl.scaleFactor);
-		//gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-		//gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
-		//gl.drawArrays(gl.LINES, 0, this.pointBuffer.numItems);
 
 		gl.uniform1f(shaderProgram.pointsizeUniform, this.thick*gl.scaleFactor);
 		gl.uniform1f(shaderProgram.roundPointsUniform, true);

--- a/src/js/circuit/PCB/Layer.js
+++ b/src/js/circuit/PCB/Layer.js
@@ -17,32 +17,88 @@
 	
 			if(parts) this.parts = parts;
 			else this.parts = [];
+
+			this.polygons = [];
 	
 		};
 	
 		Layer.SOLDER = 0;
 		Layer.TOP = 1;
-	
-		Layer.prototype.addPart = function(part){
-	
-			this.parts.push(part);
-	
+
+		Layer.prototype._renderPolygons = function(ctx, color, pins, elements){
+
+			// render clear polygons first
+			for(i = 0; i < this.polygons.length; i++)
+				this.polygons[i].render(ctx, color);
+
+			// clear pins, same layer pads, and other clearing objects
+			ctx.globalCompositeOperation = "destination-out";
+			ctx.fillStyle = '#FFFFFF';
+			for(i = 0; i < this.parts.length; i++)
+					this.parts[i].clear(ctx);
+			if(elements)
+				for(i = 0; i < elements.parts.length; i++)
+					elements.parts[i].clear(ctx);
+			if(pins)
+				for(i = 0; i < pins.parts.length; i++)
+					pins.parts[i].clear(ctx);
+			ctx.globalCompositeOperation = "source-over";
+
+			// Render non clearing polygons
+
+		}
+
+		Layer.prototype._renderPolygonsGL = function(gl, shaderProgram, color, pins, elements){
+
+			// render clear polygons first
+			gl.uniform4f(shaderProgram.vColorUniform, color.r, color.g, color.b, 1.0);
+			for(i = 0; i < this.polygons.length; i++)
+				this.polygons[i].renderGL(gl, shaderProgram);
+
+			// render alpha of pins, same layer pads, and other clearing objects
+			gl.uniform4f(shaderProgram.vColorUniform, 0.0, 0.0, 0.0, 0.0);
+			for(i = 0; i < this.parts.length; i++)
+				this.parts[i].clearGL(gl, shaderProgram);
+			if(pins)
+				for(i = 0; i < pins.parts.length; i++)
+					pins.parts[i].clearGL(gl, shaderProgram);
+			if(elements)
+				for(i = 0; i < elements.parts.length; i++)
+					elements.parts[i].clearGL(gl, shaderProgram);
+
+			// render non clear polygons
+
+		}
+
+		Layer.prototype.isEmpty = function(){
+			return this.parts.length == 0 && this.polygons.length == 0;
+		}
+
+		Layer.prototype.hasPolygons = function(){
+			return this.polygons.length != 0;
 		};
 
-		Layer.prototype.isEmpty = function(){
-			return this.parts.length == 0;
-		}
+		Layer.prototype.addPart = function(part){
+			this.parts.push(part);
+		};
 
-		Layer.prototype.render = function(ctx, color){
+		Layer.prototype.seperatePolygons = function(){
+			for(var i = 0; i < this.parts.length; i++)
+				if(this.parts[i] instanceof Polygon)
+					this.polygons.push(this.parts.splice(i, 1)[0]);
+		};
+
+		Layer.prototype.render = function(ctx, color, pins, elements){
 
 			if(!color) color = this.pcbv.getLayerColors()[this.number-1];
-	
-			for(var p = 0; p < this.parts.length; p++)
-				this.parts[p].render(ctx, color);
-	
+
+			if(this.hasPolygons()) this._renderPolygons(ctx, color, pins, elements);
+			for(var i = 0; i < this.parts.length; i++)
+				this.parts[i].render(ctx, color);
+			
 		};
 	
-		Layer.prototype.renderGL = function(gl, shaderProgram, oMatrix, mvMatrix, color, pins, elements){
+		Layer.prototype.renderGL = function(gl, shaderProgram, color, pins, elements){
 	
 			gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
 
@@ -50,38 +106,10 @@
 			gl.clearColor(0.0, 0.0, 0.0, 0.0);
 			gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 	
-			// render clear polygons first
-			// render alpha of pins, same layer pads, and other clearing objects
-			// render non clear polygons
-			// render rest like normal
-	
+			if(this.hasPolygons()) this._renderPolygonsGL(gl, shaderProgram, color, pins, elements);
 			gl.uniform4f(shaderProgram.vColorUniform, color.r, color.g, color.b, 1.0);
-	
-			var i;
-
-			for(i = 0; i < this.parts.length; i++)
-				if(this.parts[i] instanceof Polygon)
-					this.parts[i].renderGL(gl, shaderProgram);
-
-			gl.uniform4f(shaderProgram.vColorUniform, 0.0, 0.0, 0.0, 0.0);
-			for(i = 0; i < this.parts.length; i++)
-				if(!(this.parts[i] instanceof Polygon))
-					this.parts[i].clearGL(gl, shaderProgram);
-
-			if(pins){
-				for(i = 0; i < pins.parts.length; i++)
-					pins.parts[i].clearGL(gl, shaderProgram);
-			}
-			if(elements){
-				for(i = 0; i < elements.parts.length; i++)
-					elements.parts[i].clearGL(gl, shaderProgram);
-			}
-
-			gl.uniform4f(shaderProgram.vColorUniform, color.r, color.g, color.b, 1.0);
-
-			for(i = 0; i < this.parts.length; i++)
-				if(!(this.parts[i] instanceof Polygon))
-					this.parts[i].renderGL(gl, shaderProgram);
+			for(var i = 0; i < this.parts.length; i++)
+				this.parts[i].renderGL(gl, shaderProgram);
 
 		}
 	
@@ -102,7 +130,9 @@
 			var i;
 			for(i = 0; i < this.parts.length; i++)
 				this.parts[i].setup3DArrayBuffer(gl, 0, 0);
-	
+			for(i = 0; i < this.polygons.length; i++)
+				this.polygons[i].setup3DArrayBuffer(gl, 0, 0);
+
 		}
 	
 		Layer.prototype.resizeFrameBuffer = function(gl){

--- a/src/js/circuit/PCB/Line.js
+++ b/src/js/circuit/PCB/Line.js
@@ -29,6 +29,16 @@
 		};
 	
 		Class.extend(ElementLine, Line);
+
+		Line.prototype.clear = function(ctx){
+
+			if(this.flags.clearline){
+				this._prepareRender(ctx, this.thick + this.clearance);
+				ctx.stroke();
+				ctx.closePath();
+			}
+
+		};
 
 		Line.prototype.clearGL = function(gl, shaderProgram){
 

--- a/src/js/circuit/PCB/Pad.js
+++ b/src/js/circuit/PCB/Pad.js
@@ -1,14 +1,14 @@
 define(function() {
 
 	// Pad [x1 y1 x2 y2 thickness clearance mask name pad_number flags]
-	var Pad = function(x1, y1, x2, y2, thick, clear, mask, name, pnum, flags) {
+	var Pad = function(x1, y1, x2, y2, thick, clearance, mask, name, pnum, flags) {
 
 		this.x1 = x1;
 		this.y1 = y1;
 		this.x2 = x2;
 		this.y2 = y2;
 		this.thick = thick;
-		this.clear = clear;
+		this.clearance = clearance;
 		this.mask = mask;
 		this.name = name;
 		this.pnum = pnum;
@@ -16,29 +16,40 @@
 
 	};
 
+	Pad.prototype._createCache = function(){
+	
+		var x1, y2, x2, y2, thk;
+
+		this._cache = {};
+
+		x1 = this.x1;
+		y1 = this.y1;
+		x2 = this.x2;
+		y2 = this.y2;
+		if(this.parent){
+			x1 += this.parent.mx;
+			y1 += this.parent.my;
+			x2 += this.parent.mx;
+			y2 += this.parent.my;
+		}
+
+		thk = this.thick;
+		this._cache.rx1 = x1 - (thk / 2);
+		this._cache.ry1 = y1 - (thk / 2);
+		this._cache.rx2 = x2 - x1 + thk;
+		this._cache.ry2 = y2 - y1 + thk;
+
+		thk = this.thick + this.clearance;
+		this._cache.rcx1 = x1 - (thk / 2);
+		this._cache.rcy1 = y1 - (thk / 2);
+		this._cache.rcx2 = x2 - x1 + thk;
+		this._cache.rcy2 = y2 - y1 + thk;
+
+	};
+
 	Pad.prototype.render = function(ctx, color) {
 
-		if(!this._cache){
-			
-			var x1, y2, x2, y2;
-
-			this._cache = {};
-
-			x1 = this.x1;
-			y1 = this.y1;
-			x2 = this.x2;
-			y2 = this.y2;
-			if(this.parent){
-				x1 += this.parent.mx;
-				y1 += this.parent.my;
-				x2 += this.parent.mx;
-				y2 += this.parent.my;
-			}
-			this._cache.rx1 = x1 - (this.thick / 2);
-			this._cache.ry1 = y1 - (this.thick / 2);
-			this._cache.rx2 = x2 - x1 + (this.thick);
-			this._cache.ry2 = y2 - y1 + (this.thick);
-		}
+		if(!this._cache) this._createCache();
 
 		if (color == '#FFFFFF')
 			ctx.fillStyle = color;
@@ -53,14 +64,25 @@
 
 	};
 
+	Pad.prototype.clear = function(ctx){
+
+		if(!this._cache) this._createCache();
+
+		ctx.fillRect(
+			this._cache.rcx1,
+			this._cache.rcy1,
+			this._cache.rcx2,
+			this._cache.rcy2);
+
+	};
+
 	Pad.prototype.renderGL = function(gl, shaderProgram){
 
-		gl.uniform4f(shaderProgram.vColorUniform, 0.35, 0.35, 0.35, 1.0);
 		gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
 		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
 		gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.vertexBuffer.numItems);
 
-	}
+	};
 
 	Pad.prototype.clearGL = function(gl, shaderProgram){
 
@@ -112,7 +134,7 @@
 	Pad.prototype.setup3DArrayBuffer = function(gl, x, y){
 
 		this.vertexBuffer = this.generatePadBuffer(gl, this.thick);
-		this.clearBuffer = this.generatePadBuffer(gl, this.thick + this.clear);
+		this.clearBuffer = this.generatePadBuffer(gl, this.thick + this.clearance);
 
 	};
 

--- a/src/js/circuit/PCB/Pin.js
+++ b/src/js/circuit/PCB/Pin.js
@@ -1,12 +1,12 @@
 define(function() {
 
 	// Pin [x y thickness clearance mask drillholedia name number flags]
-	var Pin = function(x, y, thick, clear, mask, drill, name, num, flags) {
+	var Pin = function(x, y, thick, clearance, mask, drill, name, num, flags) {
 
 		this.x = x;
 		this.y = y;
 		this.thick = thick;
-		this.clear = clear;
+		this.clearance = clearance;
 		this.mask = mask;
 		this.drill = drill;
 		this.name = name;
@@ -21,22 +21,24 @@
 
 	};
 
+	Pin.prototype._createCache = function(){
+
+		this._cache = {};
+
+		this._cache.x = this.x;
+		this._cache.y = this.y;
+		if(this.parent){
+			this._cache.x += this.parent.mx;
+			this._cache.y += this.parent.my;
+		}
+		this._cache.rx = this._cache.x - (this.thick / 2);
+		this._cache.ry = this._cache.y - (this.thick / 2);
+
+	}
+
 	Pin.prototype.render = function(ctx, color) {
 
-		if(!this._cache){
-
-			this._cache = {};
-
-			this._cache.x = this.x;
-			this._cache.y = this.y;
-			if(this.parent){
-				this._cache.x += this.parent.mx;
-				this._cache.y += this.parent.my;
-			}
-			this._cache.rx = this._cache.x - (this.thick / 2);
-			this._cache.ry = this._cache.y - (this.thick / 2);
-
-		}
+		if(!this._cache) this._createCache();
 
 		if(color == '#FFFFFF')
 			return;
@@ -55,6 +57,17 @@
 		ctx.arc(this._cache.x, this._cache.y, this.drill / 2, 0, Math.PI * 2, true);
 		ctx.closePath();
 		ctx.fillStyle = '#E5E5E5'; // TODO: set colors to global option
+		ctx.fill();
+
+	};
+
+	Pin.prototype.clear = function(ctx){
+
+		if(!this._cache) this._createCache();
+
+		ctx.beginPath();
+		ctx.arc(this._cache.x, this._cache.y, (this.clearance + this.thick) / 2.0, 0, Math.PI * 2, true);
+		ctx.closePath();
 		ctx.fill();
 
 	};
@@ -89,7 +102,7 @@
 		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
 		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, (this.thick + this.clear) * gl.scaleFactor);
+		gl.uniform1f(shaderProgram.pointsizeUniform, (this.thick + this.clearance) * gl.scaleFactor);
 		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
 
 		gl.uniform1f(shaderProgram.roundPointsUniform, false);

--- a/src/js/circuit/PCB/Renderers/GLRenderer.js
+++ b/src/js/circuit/PCB/Renderers/GLRenderer.js
@@ -218,23 +218,23 @@
 
 			if(side == Layer.TOP){
 
-				this.topSilk.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0}, this.pins, null);
-				this.bottomSilk.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
-
-				this.top.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
-				this.solder.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0}, this.pins, null);
+				this.topSilk.renderGL(gl, this.shaderProgram, {r: 0.0, g: 0.0, b: 0.0}, this.pins, null);
+				this.bottomSilk.renderGL(gl, this.shaderProgram, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
+
+				this.top.renderGL(gl, this.shaderProgram, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
+				this.solder.renderGL(gl, this.shaderProgram, {r: 0.35, g: 0.35, b: 0.35}, this.pins, null);
 
 			} else {
 
-				this.topSilk.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
-				this.bottomSilk.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0}, this.pins, null);
-
-				this.top.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0}, this.pins, null);
-				this.solder.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
-
-			}
-
-			this.pins.renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0}, null);
+				this.topSilk.renderGL(gl, this.shaderProgram, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
+				this.bottomSilk.renderGL(gl, this.shaderProgram,{r: 0.0, g: 0.0, b: 0.0}, this.pins, null);
+
+				this.top.renderGL(gl, this.shaderProgram, {r: 0.35, g: 0.35, b: 0.35}, this.pins, null);
+				this.solder.renderGL(gl, this.shaderProgram, {r: 1.0, g: 1.0, b: 1.0}, this.pins, null);
+
+			}
+
+			this.pins.renderGL(gl, this.shaderProgram, {r: 1.0, g: 1.0, b: 1.0}, null);
 
 			for(l = 0; l < this.otherLayers.length; l++){
 
@@ -245,11 +245,11 @@
 				b = parseInt(color.substring(5, 7), 16) / 256;
 
 				if(this.otherLayers[l].name == "bottom")
-					this.otherLayers[l].renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: r, g: g, b: b}, this.pins, this.solder);
+					this.otherLayers[l].renderGL(gl, this.shaderProgram, {r: r, g: g, b: b}, this.pins, this.solder);
 				else if(this.otherLayers[l].name == "top")
-					this.otherLayers[l].renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: r, g: g, b: b}, this.pins, this.top);
+					this.otherLayers[l].renderGL(gl, this.shaderProgram, {r: r, g: g, b: b}, this.pins, this.top);
 				else
-					this.otherLayers[l].renderGL(gl, this.shaderProgram, oMatrix, mvMatrix, {r: r, g: g, b: b}, this.pins, null);
+					this.otherLayers[l].renderGL(gl, this.shaderProgram, {r: r, g: g, b: b}, this.pins, null);
 
 			}
 

--- a/src/js/circuit/PCB/Renderers/Renderer.js
+++ b/src/js/circuit/PCB/Renderers/Renderer.js
@@ -55,6 +55,8 @@
 			else
 				this.otherLayers.push(layer);
 
+			layer.seperatePolygons();
+
 		};
 
 		Renderer.prototype.destroy = function(){throw new NotImplementedException("Renderer.destroy is virtual function");};

--- a/src/js/circuit/PCB/Renderers/TwoDRenderer.js
+++ b/src/js/circuit/PCB/Renderers/TwoDRenderer.js
@@ -18,12 +18,19 @@
 
 		Class.extend(Renderer, TwoDRenderer);
 
-		TwoDRenderer._renderLayer = function(ctx, bufferCtx, bufferCanvas, layer, color, pins, components){
+		TwoDRenderer.prototype._renderLayer = function(ctx, bufferCtx, bufferCanvas, layer, color){
+
+			var components = null;
 
 			if(layer && !layer.isEmpty()){
+
+				if(layer.name == "bottom") components = this.solder;
+				else if(layer.name == "top") components = this.top;
+
 				bufferCtx.clearRect(0, 0, bufferCanvas.width, bufferCanvas.height);
-				layer.render(bufferCtx, color);
+				layer.render(bufferCtx, color, this.pins, components);
 				ctx.drawImage(bufferCanvas, 0, 0);
+
 			}
 
 		};
@@ -76,23 +83,23 @@
 			this.ctx.globalAlpha = 0.5;
 			if(side != Layer.TOP){
 
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.topSilk, '#FFFFFF', null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.solder, '#FFFFFF', null, null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.topSilk, '#FFFFFF', null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.solder, '#FFFFFF', null);
 	        	for(l = this.otherLayers.length - 1; l >= 0; l--)
-					TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.otherLayers[l], null, null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.top, '#000000', null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.pins, null, null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.bottomSilk, '#000000', null, null);
+	        		this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.otherLayers[l], null, null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.top, '#000000', null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.pins, null, null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.bottomSilk, '#000000', null);
 
 	        } else {
 
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.bottomSilk, '#FFFFFF', null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.top, '#FFFFFF', null, null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.bottomSilk, '#FFFFFF', null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.top, '#FFFFFF', null);
 	        	for(l = 0; l < this.otherLayers.length; l++)
-					TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.otherLayers[l], null, null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.solder, '#000000', null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.pins, null, null, null);
-	        	TwoDRenderer._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.topSilk, '#000000', null, null);
+	        		this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.otherLayers[l], null, null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.solder, '#000000', null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.pins, null, null);
+	        	this._renderLayer(this.ctx, this.bufferCtx, this.bufferCanvas, this.topSilk, '#000000', null);
 
 	        }
 		

--- a/src/js/circuit/PCB/Text.js
+++ b/src/js/circuit/PCB/Text.js
@@ -53,7 +53,9 @@
 			ctx.restore();
 	
 		};
-	
+
+		Text.prototype.clear = function(ctx){};
+
 		Text.prototype.renderGL = function(gl, shaderProgram){
 
 			var sym, mvMatrix;

--- a/src/js/circuit/PCB/Via.js
+++ b/src/js/circuit/PCB/Via.js
@@ -21,6 +21,15 @@
 		ctx.arc(this.x, this.y, this.id / 2, 0, Math.PI * 2, true);
 		ctx.closePath();
 		ctx.fillStyle = '#E5E5E5'; // TODO: set colors to global option
+		ctx.fill();
+
+	};
+
+	Via.prototype.clear = function(ctx){
+
+		ctx.beginPath();
+		ctx.arc(this.x, this.y, (this.clearance + this.od) / 2.0, 0, Math.PI * 2, true);
+		ctx.closePath();
 		ctx.fill();
 
 	};