Merge branch 'dev' master
Merge branch 'dev'
Version 1.5, only major problem is polygon areas render fully even when
its non contiguous

--- a/src/data/pcb/PCBList.json
+++ b/src/data/pcb/PCBList.json
@@ -1,4 +1,5 @@
 [
+	"ThermalTest.pcb",
 	"FT817USB.pcb",
 	"FTDI.pcb",
 	"H_Bridge.pcb",
@@ -9,3 +10,4 @@
 	"USBMRF24.pcb",
 	"XBeeMainBoard.pcb"
 ]
+

--- a/src/data/pcb/SoftRockLiteIIRX.pcb
+++ b/src/data/pcb/SoftRockLiteIIRX.pcb
@@ -5,12 +5,12 @@
 
 PCB["" 255900 90000]
 
-Grid[500.0 0 0 0]
+Grid[0.0 0 0 0]
 Cursor[0 0 0.000000]
 PolyArea[200000000.000000]
 Thermal[0.500000]
 DRC[600 600 600 600 1300 700]
-Flags("nameonpcb,uniquename")
+Flags("nameonpcb,alldirection")
 Groups("1,c:2:3:4:5:6,s:7:8")
 Styles["Signal,1500,4200,2600,1000:Power,2500,6000,3500,1000:Fat,4000,15000,12700,1000:Skinny,600,2402,1181,600"]
 
@@ -792,9 +792,7 @@
 Via[171000 60500 4200 2000 0 2600 "" ""]
 Via[122500 25000 4200 2000 0 2600 "" ""]
 Via[141000 22000 4200 2000 0 2600 "" ""]
-Via[4000 20500 4200 2000 0 2600 "" ""]
 Via[145000 63000 4200 2000 0 2600 "" ""]
-Via[65500 67000 4200 2000 0 2600 "" ""]
 Via[70500 71500 4200 2000 0 2600 "" ""]
 Via[76000 74000 4200 2000 0 2600 "" ""]
 Via[88500 80500 4200 2000 0 2600 "" ""]
@@ -802,15 +800,17 @@
 Via[155000 32000 4200 2000 0 2600 "" ""]
 Via[165000 56000 4200 2000 0 2600 "" ""]
 Via[160500 11500 4200 2000 0 2600 "" ""]
+Via[163000 32000 4200 2000 0 2600 "" ""]
 Via[155000 37500 4200 2000 0 2600 "" ""]
-Via[163000 32000 4200 2000 0 2600 "" ""]
-Via[52000 62500 4200 2000 0 2600 "" ""]
-Via[108000 85500 4200 2000 0 2600 "" ""]
+Via[108000 85500 4200 2000 0 2600 "" "thermal(5S)"]
+Via[4000 20500 4200 2000 0 2600 "" "thermal(5S)"]
+Via[65500 67000 4200 2000 0 2600 "" ""]
+Via[52000 62500 4700 2000 0 2600 "" "thermal(0S,1S,2S,5S)"]
 
 Element["" "HC49U_1" "X1" "rect_100" 22000 9000 -11000 6500 0 100 ""]
 (
 	Pin[10000 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2,thermal(5+)"]
 	ElementLine [-20500 -5000 -20500 5000 1000]
 	ElementLine [20500 -5000 20500 5000 1000]
 	ElementLine [-17700 -7500 17700 -7500 1000]
@@ -822,7 +822,7 @@
 
 	)
 
-Element["" "TO92_tri" "Q1" "unknown" 66000 14000 6000 -9400 0 100 ""]
+Element["" "TO92_tri" "Q1" "unknown" 66000 14000 6500 -7000 0 100 ""]
 (
 	Pin[0 5000 4400 2000 5000 3000 "3" "3" ""]
 	Pin[-2400 0 4400 2000 5000 3000 "2" "2" ""]
@@ -907,6 +907,324 @@
 
 	)
 
+Element["" "SIP2" "ANT" "unknown" 247500 73000 -1000 -6500 1 100 ""]
+(
+	Pin[0 0 6000 2000 6600 2800 "1" "1" ""]
+	Pin[0 10000 6000 2000 6600 2800 "2" "2" ""]
+
+	)
+
+Element["" "ind_180" "L1" "unknown" 224000 69000 -6500 -20500 0 100 ""]
+(
+	Pin[-5000 9000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[5000 -9000 5400 2000 5400 3000 "1" "1" ""]
+	ElementLine [5000 -3700 5000 14000 1000]
+	ElementLine [-5000 -14000 -5000 3700 1000]
+	ElementLine [-5000 14000 5000 14000 1000]
+	ElementLine [-5000 -14000 5000 -14000 1000]
+
+	)
+
+Element["onsolder" "1206_2" "C14" "0.01uF" 214000 60000 1000 10500 0 100 "auto"]
+(
+	Pad[6400 0 6400 0 6600 2000 6600 "1" "1" "onsolder,square,edge2"]
+	Pad[-6400 0 -6400 0 6600 2000 6600 "2" "2" "onsolder,square"]
+
+	)
+
+Element["" "rect_100" "C3" "unknown" 237500 67500 -2500 -9500 0 100 ""]
+(
+	Pin[0 10000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
+	ElementLine [3600 -3300 3600 13600 1000]
+	ElementLine [-3600 -3300 -3600 13600 1000]
+	ElementLine [-3600 13600 3600 13600 1000]
+	ElementLine [-3600 -3300 3600 -3300 1000]
+
+	)
+
+Element["" "rect_100" "C4" "unknown" 209000 83000 -3000 -20500 0 100 ""]
+(
+	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
+	ElementLine [-3600 -13600 -3600 3300 1000]
+	ElementLine [3600 -13600 3600 3300 1000]
+	ElementLine [-3600 -13600 3600 -13600 1000]
+	ElementLine [-3600 3300 3600 3300 1000]
+
+	)
+
+Element["" "SIP2" "PWR" "unknown" 248000 19500 -16000 2000 0 100 ""]
+(
+	Pin[0 0 6000 2000 6600 2800 "1" "1" "thermal(5+)"]
+	Pin[0 -10000 6000 2000 6600 2800 "2" "2" ""]
+
+	)
+
+Element["" "res_vert" "R5" "unknown" 119000 73000 -4500 -10500 0 100 ""]
+(
+	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [-6400 0 -3600 0 1000]
+	ElementArc [0 0 3600 3600 180 360 1000]
+
+	)
+
+Element["onsolder" "1206_2" "C16" "0.1uF" 89000 64900 -250 -11250 0 100 "auto"]
+(
+	Pad[0 -6400 0 -6400 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[0 6400 0 6400 6600 2000 6600 "2" "2" "onsolder,square"]
+
+	)
+
+Element["" "res_vert" "R2" "10" 145500 80500 3500 -10500 0 100 ""]
+(
+	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [3600 0 6400 0 1000]
+	ElementArc [0 0 3600 3600 0 360 1000]
+
+	)
+
+Element["" "res_vert" "R4" "1k" 204500 37500 -13000 -3000 0 100 ""]
+(
+	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2,thermal(5+)"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [3600 0 6400 0 1000]
+	ElementArc [0 0 3600 3600 0 360 1000]
+
+	)
+
+Element["" "res_vert" "R3" "1k" 194000 47500 -13000 -3000 0 100 ""]
+(
+	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [3600 0 6400 0 1000]
+	ElementArc [0 0 3600 3600 0 360 1000]
+
+	)
+
+Element["onsolder" "1206_2" "C13" "0.1uF" 234500 26100 -14050 9250 0 100 "auto"]
+(
+	Pad[0 6400 0 6400 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[0 -6400 0 -6400 6600 2000 6600 "2" "2" "onsolder,square"]
+
+	)
+
+Element["" "TO92_tri" "U1" "unknown" 199000 11500 -17800 -7400 0 100 ""]
+(
+	Pin[-5000 0 4400 2000 5000 3000 "3" "3" "edge2"]
+	Pin[0 -2400 4400 2000 5000 3000 "2" "2" "edge2,thermal(5+)"]
+	Pin[5000 0 4400 2000 5000 3000 "1" "1" "edge2"]
+	ElementLine [-10000 4200 10000 4200 1000]
+	ElementLine [10000 -2800 10000 4200 1000]
+	ElementLine [-10000 -2800 -10000 4200 1000]
+	ElementLine [-10000 -2800 -5200 -7600 1000]
+	ElementLine [10000 -2800 5200 -7600 1000]
+	ElementLine [-5200 -7600 5200 -7600 1000]
+
+	)
+
+Element["" "diode_100" "D1" "unknown" 230000 9500 -17000 -7000 0 100 ""]
+(
+	Pin[5000 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	Pin[-5000 0 5400 2000 5400 3000 "1" "1" "square,edge2"]
+	ElementLine [-3000 4000 -1000 4000 1000]
+	ElementLine [2000 4000 5000 4000 1000]
+	ElementLine [-1000 1000 -1000 7000 1000]
+	ElementLine [2000 1000 2000 7000 1000]
+	ElementLine [-1000 4000 2000 1000 1000]
+	ElementLine [-1000 4000 2000 7000 1000]
+
+	)
+
+Element["" "TO92_tri" "Q2" "unknown" 99500 14000 8000 -12500 0 100 ""]
+(
+	Pin[0 -5000 4400 2000 5000 3000 "3" "3" ""]
+	Pin[2400 0 4400 2000 5000 3000 "2" "2" ""]
+	Pin[0 5000 4400 2000 5000 3000 "1" "1" ""]
+	ElementLine [-4200 -10000 -4200 10000 1000]
+	ElementLine [-4200 10000 2800 10000 1000]
+	ElementLine [-4200 -10000 2800 -10000 1000]
+	ElementLine [2800 -10000 7600 -5200 1000]
+	ElementLine [2800 10000 7600 5200 1000]
+	ElementLine [7600 -5200 7600 5200 1000]
+
+	)
+
+Element["" "res_vert" "R11" "10" 122500 9000 4000 4000 0 100 ""]
+(
+	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [3600 0 6400 0 1000]
+	ElementArc [0 0 3600 3600 0 360 1000]
+
+	)
+
+Element["" "res_vert" "R17" "475" 109500 32000 7500 -4000 0 100 ""]
+(
+	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2,thermal(5+)"]
+	ElementLine [-6400 0 -3600 0 1000]
+	ElementArc [0 0 3600 3600 180 360 1000]
+
+	)
+
+Element["" "rect_100" "C12" "22pF" 76000 27500 -14500 -2000 0 100 ""]
+(
+	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
+	ElementLine [-3600 -13600 -3600 3300 1000]
+	ElementLine [3600 -13600 3600 3300 1000]
+	ElementLine [-3600 -13600 3600 -13600 1000]
+	ElementLine [-3600 3300 3600 3300 1000]
+
+	)
+
+Element["" "res_vert" "R14" "475" 76500 36500 -17500 1500 0 100 ""]
+(
+	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2,thermal(5+)"]
+	ElementLine [-6400 0 -3600 0 1000]
+	ElementArc [0 0 3600 3600 180 360 1000]
+
+	)
+
+Element["" "rect_100" "C10" "unknown" 50500 17000 -1500 4000 0 100 ""]
+(
+	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
+	ElementLine [-3600 -13600 -3600 3300 1000]
+	ElementLine [3600 -13600 3600 3300 1000]
+	ElementLine [-3600 -13600 3600 -13600 1000]
+	ElementLine [-3600 3300 3600 3300 1000]
+
+	)
+
+Element["" "res_vert" "R13" "10k" 20000 24500 -10000 4500 0 100 ""]
+(
+	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2,thermal(5+)"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [-6400 0 -3600 0 1000]
+	ElementArc [0 0 3600 3600 180 360 1000]
+
+	)
+
+Element["" "res_vert" "R12" "10k" 40000 24500 -14500 3500 0 100 ""]
+(
+	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [-6400 0 -3600 0 1000]
+	ElementArc [0 0 3600 3600 180 360 1000]
+
+	)
+
+Element["" "res_vert" "R15" "1k" 86500 9000 -14000 -7500 0 100 ""]
+(
+	Pin[0 10000 5400 2000 5400 3000 "1" "1" ""]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" ""]
+	ElementLine [0 3600 0 6400 1000]
+	ElementArc [0 0 3600 3600 270 360 1000]
+
+	)
+
+Element["" "res_vert" "R16" "22.1k" 86500 27000 4000 12000 0 100 ""]
+(
+	Pin[0 10000 5400 2000 5400 3000 "1" "1" "thermal(5+)"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" ""]
+	ElementLine [0 3600 0 6400 1000]
+	ElementArc [0 0 3600 3600 270 360 1000]
+
+	)
+
+Element["" "rect_100" "C5" "47nF" 129500 78500 5500 -11500 0 100 ""]
+(
+	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" "thermal(5+)"]
+	ElementLine [-3600 -13600 -3600 3300 1000]
+	ElementLine [3600 -13600 3600 3300 1000]
+	ElementLine [-3600 -13600 3600 -13600 1000]
+	ElementLine [-3600 3300 3600 3300 1000]
+
+	)
+
+Element["" "rect_100" "C6" "47nF" 129500 58000 6500 -13500 0 100 ""]
+(
+	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
+	ElementLine [-3600 -13600 -3600 3300 1000]
+	ElementLine [3600 -13600 3600 3300 1000]
+	ElementLine [-3600 -13600 3600 -13600 1000]
+	ElementLine [-3600 3300 3600 3300 1000]
+
+	)
+
+Element["onsolder" "1206_2" "C17" "0.1uF" 57500 74400 -6550 -9950 0 100 "auto"]
+(
+	Pad[0 -6400 0 -6400 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[0 6400 0 6400 6600 2000 6600 "2" "2" "onsolder,square"]
+
+	)
+
+Element["onsolder" "1206_2" "C18" "0.1uF" 31600 75000 -19150 3150 0 100 "auto"]
+(
+	Pad[-6400 0 -6400 0 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[6400 0 6400 0 6600 2000 6600 "2" "2" "onsolder,square,edge2"]
+
+	)
+
+Element["onsolder" "1206_2" "C21" "0.01uF" 132500 23600 -4750 16550 0 100 "auto"]
+(
+	Pad[0 6400 0 6400 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[0 -6400 0 -6400 6600 2000 6600 "2" "2" "onsolder,square"]
+
+	)
+
+Element["onsolder" "1206_2" "C15" "0.01uF" 184000 41400 6250 13750 0 100 "auto"]
+(
+	Pad[0 -6400 0 -6400 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[0 6400 0 6400 6600 2000 6600 "2" "2" "onsolder,square"]
+
+	)
+
+Element["" "rect_100" "C11" "unknown" 41000 34000 -4500 4500 0 100 ""]
+(
+	Pin[10000 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" "edge2,thermal(5+)"]
+	ElementLine [-3300 -3600 13600 -3600 1000]
+	ElementLine [-3300 3600 13600 3600 1000]
+	ElementLine [13600 -3600 13600 3600 1000]
+	ElementLine [-3300 -3600 -3300 3600 1000]
+
+	)
+
+Element["onsolder" "1206_2" "C20" "10nF" 110500 16600 5950 3250 0 100 "auto"]
+(
+	Pad[0 6400 0 6400 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[0 -6400 0 -6400 6600 2000 6600 "2" "2" "onsolder,square"]
+
+	)
+
+Element["" "rect_200" "C2" "4.7uF" 214000 24500 -31500 -7500 0 100 ""]
+(
+	Pin[-20000 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" "edge2,thermal(5+)"]
+	ElementLine [-23200 3600 3300 3600 1000]
+	ElementLine [-23200 -3600 3300 -3600 1000]
+	ElementLine [-23200 -3600 -23200 3600 1000]
+	ElementLine [3300 -3600 3300 3600 1000]
+
+	)
+
+Element["" "res_vert" "R1" "10" 166000 80500 1500 -10500 0 100 ""]
+(
+	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [3600 0 6400 0 1000]
+	ElementArc [0 0 3600 3600 0 360 1000]
+
+	)
+
 Element["" "transformer_6" "T1" "unknown" 192000 70000 12500 -17500 0 100 ""]
 (
 	Pin[6600 10000 5400 2000 5400 3000 "1" "1" ""]
@@ -931,40 +1249,65 @@
 
 	)
 
-Element["hidename" "SIP3" "AUD" "unknown" 7000 63000 -1000 3000 3 100 ""]
-(
-	Pin[0 0 6000 2000 6600 2800 "1" "1" ""]
-	Pin[0 10000 6000 2000 6600 2800 "2" "2" ""]
-	Pin[0 20000 6000 2000 6600 2800 "3" "3" ""]
-
-	)
-
-Element["" "SIP2" "ANT" "unknown" 247500 73000 -1000 -6500 1 100 ""]
-(
-	Pin[0 0 6000 2000 6600 2800 "1" "1" ""]
-	Pin[0 10000 6000 2000 6600 2800 "2" "2" ""]
-
-	)
-
-Element["" "ind_180" "L1" "unknown" 224000 69000 -6500 -20500 0 100 ""]
-(
-	Pin[-5000 9000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[5000 -9000 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [5000 -3700 5000 14000 1000]
-	ElementLine [-5000 -14000 -5000 3700 1000]
-	ElementLine [-5000 14000 5000 14000 1000]
-	ElementLine [-5000 -14000 5000 -14000 1000]
-
-	)
-
-Element["onsolder" "1206_2" "C14" "0.01uF" 206400 61000 8550 11650 0 100 "auto"]
-(
-	Pad[6400 0 6400 0 6600 2000 6600 "1" "1" "onsolder,square,edge2"]
-	Pad[-6400 0 -6400 0 6600 2000 6600 "2" "2" "onsolder,square"]
-
-	)
-
-Element["" "rect_100" "C3" "unknown" 237500 67500 -2500 -9500 0 100 ""]
+Element["" "rect_200" "C1" "4.7uF" 224500 42000 5500 -11500 0 100 ""]
+(
+	Pin[0 -20000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" "thermal(5+)"]
+	ElementLine [-3600 -23200 -3600 3300 1000]
+	ElementLine [3600 -23200 3600 3300 1000]
+	ElementLine [-3600 -23200 3600 -23200 1000]
+	ElementLine [-3600 3300 3600 3300 1000]
+
+	)
+
+Element["onsolder" "1206_2" "C19" "0.1uF" 31600 55500 -9150 -5350 0 100 "auto"]
+(
+	Pad[-6400 0 -6400 0 6600 2000 6600 "1" "1" "onsolder,square"]
+	Pad[6400 0 6400 0 6600 2000 6600 "2" "2" "onsolder,square,edge2"]
+
+	)
+
+Element["" "res_vert_150mil" "R6" "unknown" 119500 47000 -11000 2000 0 100 ""]
+(
+	Pin[-15000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [-12000 0 -3600 0 1000]
+	ElementArc [0 0 3600 3600 180 360 1000]
+
+	)
+
+Element["" "res_vert" "R8" "4.99k" 56000 55000 -10500 -9500 0 100 ""]
+(
+	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	ElementLine [-6400 0 -3600 0 1000]
+	ElementArc [0 0 3600 3600 180 360 1000]
+
+	)
+
+Element["" "rect_100" "C9" "390pF" 66000 47000 10000 6000 0 100 ""]
+(
+	Pin[10000 0 5400 2000 5400 3000 "2" "2" "edge2"]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" "edge2"]
+	ElementLine [-3300 -3600 13600 -3600 1000]
+	ElementLine [-3300 3600 13600 3600 1000]
+	ElementLine [13600 -3600 13600 3600 1000]
+	ElementLine [-3300 -3600 -3300 3600 1000]
+
+	)
+
+Element["" "rect_200" "C7" "4.7uF" 99500 60500 -13000 4000 0 100 ""]
+(
+	Pin[0 20000 5400 2000 5400 3000 "2" "2" ""]
+	Pin[0 0 5400 2000 5400 3000 "1" "1" "thermal(0+,5+)"]
+	ElementLine [3600 -3300 3600 23200 1000]
+	ElementLine [-3600 -3300 -3600 23200 1000]
+	ElementLine [-3600 23200 3600 23200 1000]
+	ElementLine [-3600 -3300 3600 -3300 1000]
+
+	)
+
+Element["" "rect_100" "C8" "390pF" 48000 70500 6500 -8700 0 100 ""]
 (
 	Pin[0 10000 5400 2000 5400 3000 "2" "2" ""]
 	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
@@ -975,34 +1318,24 @@
 
 	)
 
-Element["" "rect_100" "C4" "unknown" 209000 83000 -3000 -20500 0 100 ""]
-(
-	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [-3600 -13600 -3600 3300 1000]
-	ElementLine [3600 -13600 3600 3300 1000]
-	ElementLine [-3600 -13600 3600 -13600 1000]
-	ElementLine [-3600 3300 3600 3300 1000]
-
-	)
-
-Element["" "SIP2" "PWR" "unknown" 248000 19500 -16000 2000 0 100 ""]
+Element["" "res_vert_180mil" "R7" "4.99k" 38000 83500 -9500 -16500 0 100 ""]
+(
+	Pin[0 -18000 5400 2000 5400 3000 "1" "1" ""]
+	Pin[0 0 5400 2000 5400 3000 "2" "2" ""]
+	ElementLine [0 -14500 0 -3600 1000]
+	ElementArc [0 0 3600 3600 90 360 1000]
+
+	)
+
+Element["hidename" "SIP3" "AUD" "unknown" 7000 63000 -1000 3000 3 100 ""]
 (
 	Pin[0 0 6000 2000 6600 2800 "1" "1" ""]
-	Pin[0 -10000 6000 2000 6600 2800 "2" "2" ""]
-
-	)
-
-Element["" "res_vert_150mil" "R6" "unknown" 119500 47000 -11000 2000 0 100 ""]
-(
-	Pin[-15000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [-12000 0 -3600 0 1000]
-	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "res_vert" "R5" "unknown" 119000 73000 -4500 -10500 0 100 ""]
+	Pin[0 10000 6000 2000 6600 2800 "2" "2" "thermal(0+,5+)"]
+	Pin[0 20000 6000 2000 6600 2800 "3" "3" ""]
+
+	)
+
+Element["" "res_vert" "R9" "100" 25000 83500 -2500 -10500 0 100 ""]
 (
 	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
 	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
@@ -1011,345 +1344,12 @@
 
 	)
 
-Element["onsolder" "1206_2" "C16" "0.1uF" 89000 64900 -250 -11250 0 100 "auto"]
-(
-	Pad[0 -6400 0 -6400 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[0 6400 0 6400 6600 2000 6600 "2" "2" "onsolder,square"]
-
-	)
-
-Element["" "rect_200" "C7" "4.7uF" 99500 60500 -13000 4000 0 100 ""]
-(
-	Pin[0 20000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [3600 -3300 3600 23200 1000]
-	ElementLine [-3600 -3300 -3600 23200 1000]
-	ElementLine [-3600 23200 3600 23200 1000]
-	ElementLine [-3600 -3300 3600 -3300 1000]
-
-	)
-
-Element["" "res_vert_180mil" "R7" "4.99k" 38000 83500 -9500 -16500 0 100 ""]
-(
-	Pin[0 -18000 5400 2000 5400 3000 "1" "1" ""]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" ""]
-	ElementLine [0 -14500 0 -3600 1000]
-	ElementArc [0 0 3600 3600 90 360 1000]
-
-	)
-
-Element["" "res_vert" "R8" "4.99k" 56000 55000 -10500 -9500 0 100 ""]
+Element["" "res_vert" "R10" "100" 25000 63000 -4500 -10500 0 100 ""]
 (
 	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
 	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
 	ElementLine [-6400 0 -3600 0 1000]
 	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "rect_100" "C9" "390pF" 66000 47000 10000 6000 0 100 ""]
-(
-	Pin[10000 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	ElementLine [-3300 -3600 13600 -3600 1000]
-	ElementLine [-3300 3600 13600 3600 1000]
-	ElementLine [13600 -3600 13600 3600 1000]
-	ElementLine [-3300 -3600 -3300 3600 1000]
-
-	)
-
-Element["" "res_vert" "R2" "10" 145500 80500 3500 -10500 0 100 ""]
-(
-	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [3600 0 6400 0 1000]
-	ElementArc [0 0 3600 3600 0 360 1000]
-
-	)
-
-Element["" "res_vert" "R1" "10" 166000 80500 1500 -10500 0 100 ""]
-(
-	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [3600 0 6400 0 1000]
-	ElementArc [0 0 3600 3600 0 360 1000]
-
-	)
-
-Element["" "res_vert" "R4" "1k" 204500 37500 -13000 -3000 0 100 ""]
-(
-	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [3600 0 6400 0 1000]
-	ElementArc [0 0 3600 3600 0 360 1000]
-
-	)
-
-Element["" "res_vert" "R3" "1k" 194000 47500 -13000 -3000 0 100 ""]
-(
-	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [3600 0 6400 0 1000]
-	ElementArc [0 0 3600 3600 0 360 1000]
-
-	)
-
-Element["" "rect_200" "C2" "4.7uF" 214000 24500 -31500 -7500 0 100 ""]
-(
-	Pin[-20000 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	ElementLine [-23200 3600 3300 3600 1000]
-	ElementLine [-23200 -3600 3300 -3600 1000]
-	ElementLine [-23200 -3600 -23200 3600 1000]
-	ElementLine [3300 -3600 3300 3600 1000]
-
-	)
-
-Element["onsolder" "1206_2" "C13" "0.1uF" 234500 26100 -14050 9250 0 100 "auto"]
-(
-	Pad[0 6400 0 6400 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[0 -6400 0 -6400 6600 2000 6600 "2" "2" "onsolder,square"]
-
-	)
-
-Element["" "TO92_tri" "U1" "unknown" 199000 11500 -17800 -7400 0 100 ""]
-(
-	Pin[-5000 0 4400 2000 5000 3000 "3" "3" "edge2"]
-	Pin[0 -2400 4400 2000 5000 3000 "2" "2" "edge2"]
-	Pin[5000 0 4400 2000 5000 3000 "1" "1" "edge2"]
-	ElementLine [-10000 4200 10000 4200 1000]
-	ElementLine [10000 -2800 10000 4200 1000]
-	ElementLine [-10000 -2800 -10000 4200 1000]
-	ElementLine [-10000 -2800 -5200 -7600 1000]
-	ElementLine [10000 -2800 5200 -7600 1000]
-	ElementLine [-5200 -7600 5200 -7600 1000]
-
-	)
-
-Element["" "rect_200" "C1" "4.7uF" 224500 42000 5500 -11500 0 100 ""]
-(
-	Pin[0 -20000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [-3600 -23200 -3600 3300 1000]
-	ElementLine [3600 -23200 3600 3300 1000]
-	ElementLine [-3600 -23200 3600 -23200 1000]
-	ElementLine [-3600 3300 3600 3300 1000]
-
-	)
-
-Element["" "diode_100" "D1" "unknown" 230000 9500 -17000 -7000 0 100 ""]
-(
-	Pin[5000 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	Pin[-5000 0 5400 2000 5400 3000 "1" "1" "square,edge2"]
-	ElementLine [-3000 4000 -1000 4000 1000]
-	ElementLine [2000 4000 5000 4000 1000]
-	ElementLine [-1000 1000 -1000 7000 1000]
-	ElementLine [2000 1000 2000 7000 1000]
-	ElementLine [-1000 4000 2000 1000 1000]
-	ElementLine [-1000 4000 2000 7000 1000]
-
-	)
-
-Element["" "TO92_tri" "Q2" "unknown" 99500 14000 8000 -12500 0 100 ""]
-(
-	Pin[0 -5000 4400 2000 5000 3000 "3" "3" ""]
-	Pin[2400 0 4400 2000 5000 3000 "2" "2" ""]
-	Pin[0 5000 4400 2000 5000 3000 "1" "1" ""]
-	ElementLine [-4200 -10000 -4200 10000 1000]
-	ElementLine [-4200 10000 2800 10000 1000]
-	ElementLine [-4200 -10000 2800 -10000 1000]
-	ElementLine [2800 -10000 7600 -5200 1000]
-	ElementLine [2800 10000 7600 5200 1000]
-	ElementLine [7600 -5200 7600 5200 1000]
-
-	)
-
-Element["" "res_vert" "R11" "10" 122500 9000 4000 4000 0 100 ""]
-(
-	Pin[10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [3600 0 6400 0 1000]
-	ElementArc [0 0 3600 3600 0 360 1000]
-
-	)
-
-Element["" "res_vert" "R17" "475" 109500 32000 7500 -4000 0 100 ""]
-(
-	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [-6400 0 -3600 0 1000]
-	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "rect_100" "C12" "22pF" 76000 27500 -14500 -2000 0 100 ""]
-(
-	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [-3600 -13600 -3600 3300 1000]
-	ElementLine [3600 -13600 3600 3300 1000]
-	ElementLine [-3600 -13600 3600 -13600 1000]
-	ElementLine [-3600 3300 3600 3300 1000]
-
-	)
-
-Element["" "res_vert" "R14" "475" 76500 36500 -17500 1500 0 100 ""]
-(
-	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [-6400 0 -3600 0 1000]
-	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "rect_100" "C10" "unknown" 50500 17000 -1500 4000 0 100 ""]
-(
-	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [-3600 -13600 -3600 3300 1000]
-	ElementLine [3600 -13600 3600 3300 1000]
-	ElementLine [-3600 -13600 3600 -13600 1000]
-	ElementLine [-3600 3300 3600 3300 1000]
-
-	)
-
-Element["" "res_vert" "R13" "10k" 20000 24500 -10000 4500 0 100 ""]
-(
-	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [-6400 0 -3600 0 1000]
-	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "res_vert" "R12" "10k" 40000 24500 -14500 3500 0 100 ""]
-(
-	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [-6400 0 -3600 0 1000]
-	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "res_vert" "R15" "1k" 86500 9000 -13000 -8000 0 100 ""]
-(
-	Pin[0 10000 5400 2000 5400 3000 "1" "1" ""]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" ""]
-	ElementLine [0 3600 0 6400 1000]
-	ElementArc [0 0 3600 3600 270 360 1000]
-
-	)
-
-Element["" "res_vert" "R16" "22.1k" 86500 27000 4000 12000 0 100 ""]
-(
-	Pin[0 10000 5400 2000 5400 3000 "1" "1" ""]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" ""]
-	ElementLine [0 3600 0 6400 1000]
-	ElementArc [0 0 3600 3600 270 360 1000]
-
-	)
-
-Element["" "res_vert" "R9" "100" 25000 83500 -2500 -10500 0 100 ""]
-(
-	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [-6400 0 -3600 0 1000]
-	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "res_vert" "R10" "100" 25000 63000 -4500 -10500 0 100 ""]
-(
-	Pin[-10000 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	ElementLine [-6400 0 -3600 0 1000]
-	ElementArc [0 0 3600 3600 180 360 1000]
-
-	)
-
-Element["" "rect_100" "C5" "47nF" 129500 78500 5500 -11500 0 100 ""]
-(
-	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [-3600 -13600 -3600 3300 1000]
-	ElementLine [3600 -13600 3600 3300 1000]
-	ElementLine [-3600 -13600 3600 -13600 1000]
-	ElementLine [-3600 3300 3600 3300 1000]
-
-	)
-
-Element["" "rect_100" "C6" "47nF" 129500 58000 6500 -13500 0 100 ""]
-(
-	Pin[0 -10000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [-3600 -13600 -3600 3300 1000]
-	ElementLine [3600 -13600 3600 3300 1000]
-	ElementLine [-3600 -13600 3600 -13600 1000]
-	ElementLine [-3600 3300 3600 3300 1000]
-
-	)
-
-Element["onsolder" "1206_2" "C17" "0.1uF" 57500 74400 -6550 -9950 0 100 "auto"]
-(
-	Pad[0 -6400 0 -6400 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[0 6400 0 6400 6600 2000 6600 "2" "2" "onsolder,square"]
-
-	)
-
-Element["onsolder" "1206_2" "C19" "0.1uF" 31600 55500 -9150 -5350 0 100 "auto"]
-(
-	Pad[-6400 0 -6400 0 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[6400 0 6400 0 6600 2000 6600 "2" "2" "onsolder,square,edge2"]
-
-	)
-
-Element["onsolder" "1206_2" "C18" "0.1uF" 31600 75000 -19150 3150 0 100 "auto"]
-(
-	Pad[-6400 0 -6400 0 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[6400 0 6400 0 6600 2000 6600 "2" "2" "onsolder,square,edge2"]
-
-	)
-
-Element["onsolder" "1206_2" "C21" "0.01uF" 132500 23600 -4750 16550 0 100 "auto"]
-(
-	Pad[0 6400 0 6400 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[0 -6400 0 -6400 6600 2000 6600 "2" "2" "onsolder,square"]
-
-	)
-
-Element["onsolder" "1206_2" "C15" "0.01uF" 184000 41400 6250 13750 0 100 "auto"]
-(
-	Pad[0 -6400 0 -6400 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[0 6400 0 6400 6600 2000 6600 "2" "2" "onsolder,square"]
-
-	)
-
-Element["" "rect_100" "C11" "unknown" 41000 34000 -4500 4500 0 100 ""]
-(
-	Pin[10000 0 5400 2000 5400 3000 "2" "2" "edge2"]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" "edge2"]
-	ElementLine [-3300 -3600 13600 -3600 1000]
-	ElementLine [-3300 3600 13600 3600 1000]
-	ElementLine [13600 -3600 13600 3600 1000]
-	ElementLine [-3300 -3600 -3300 3600 1000]
-
-	)
-
-Element["" "rect_100" "C8" "390pF" 48000 70500 6500 -8700 0 100 ""]
-(
-	Pin[0 10000 5400 2000 5400 3000 "2" "2" ""]
-	Pin[0 0 5400 2000 5400 3000 "1" "1" ""]
-	ElementLine [3600 -3300 3600 13600 1000]
-	ElementLine [-3600 -3300 -3600 13600 1000]
-	ElementLine [-3600 13600 3600 13600 1000]
-	ElementLine [-3600 -3300 3600 -3300 1000]
-
-	)
-
-Element["onsolder" "1206_2" "C20" "10nF" 110500 16600 5950 3250 0 100 "auto"]
-(
-	Pad[0 6400 0 6400 6600 2000 6600 "1" "1" "onsolder,square"]
-	Pad[0 -6400 0 -6400 6600 2000 6600 "2" "2" "onsolder,square"]
 
 	)
 Layer(1 "top")
@@ -1384,8 +1384,6 @@
 	Line[122500 25000 122500 31500 2500 2000 "clearline"]
 	Line[122500 31500 112000 42500 2500 2000 "clearline"]
 	Line[112000 42500 112000 57500 2500 2000 "clearline"]
-	Line[112000 57500 103500 67000 2500 2000 "clearline"]
-	Line[103500 67000 65500 67000 2500 2000 "clearline"]
 	Line[198600 70000 191000 75000 1500 2000 "clearline"]
 	Line[191000 75000 180500 75000 1500 2000 "clearline"]
 	Line[180500 75000 176000 80500 1500 2000 "clearline"]
@@ -1401,13 +1399,6 @@
 	Line[165500 55000 155000 37000 1500 2000 "clearline"]
 	Line[162344 31656 171500 50000 1500 2000 "clearline"]
 	Line[171500 50000 171000 60500 1500 2000 "clearline"]
-	Line[56000 55000 66500 55000 1500 2000 "clearline"]
-	Line[66500 55000 76000 47000 1500 2000 "clearline"]
-	Line[75406 47500 104500 47000 1500 2000 "clearline"]
-	Line[7000 63000 15000 63000 1500 2000 "clearline"]
-	Line[7000 83000 15000 83500 1500 2000 "clearline"]
-	Line[70500 71500 48000 70500 1500 2000 "clearline"]
-	Line[48000 80500 58500 80500 1500 2000 "clearline"]
 	Line[58500 80500 76000 74000 1500 2000 "clearline"]
 	Line[76000 74000 109000 73000 1500 2000 "clearline"]
 	Line[99500 80500 88500 80500 2500 2000 "clearline"]
@@ -1416,7 +1407,6 @@
 	Line[129500 48000 119500 47000 1500 2000 "clearline"]
 	Line[185400 70000 198600 60000 2500 2000 "clearline"]
 	Line[219000 78000 209000 73000 1500 2000 "clearline"]
-	Line[48000 80500 38000 83500 1500 2000 "clearline"]
 	Line[208630 82870 200500 86500 2500 2000 "clearline"]
 	Line[200500 86500 196500 86500 2500 2000 "clearline"]
 	Line[196500 86500 185400 80000 2500 2000 "clearline"]
@@ -1432,31 +1422,21 @@
 	Line[61000 9000 66000 9000 1500 2000 "clearline"]
 	Line[66000 19000 76000 17500 1500 2000 "clearline"]
 	Line[155500 16500 162500 32000 1500 2000 "clearline"]
-	Line[7000 73000 7000 68500 1500 2000 ""]
-	Line[7000 72500 7000 77500 1500 2000 ""]
-	Line[13000 73000 2500 73000 1500 2000 ""]
-	Line[2500 66000 2500 80000 1500 2000 ""]
-	Line[48000 62500 56500 62500 1500 2000 ""]
-	Line[51000 58500 51000 65000 1500 2000 ""]
-	Line[51000 65000 51500 65500 1500 2000 ""]
-	Line[52000 64500 53000 65500 1500 2000 ""]
-	Line[53000 64000 54000 65000 1500 2000 ""]
-	Line[53500 63500 55000 63500 1500 2000 ""]
-	Line[53500 61500 55000 61500 1500 2000 ""]
-	Line[52000 60500 54000 60500 1500 2000 ""]
-	Line[51500 60000 53000 60000 1500 2000 ""]
-	Line[50000 60000 50000 61500 1500 2000 ""]
-	Line[49000 61000 49000 63500 1500 2000 ""]
-	Line[49000 63500 49500 64000 1500 2000 ""]
-	Line[50000 63500 50000 64000 1500 2000 ""]
-	Line[50000 64000 50500 64500 1500 2000 ""]
+	Line[48000 80500 58500 80500 1500 2000 "clearline"]
+	Line[7000 63000 15000 63000 1500 2000 "clearline"]
+	Line[56000 55000 66500 55000 1500 2000 "clearline"]
+	Line[66500 55000 76000 47000 1500 2000 "clearline"]
+	Line[75406 47500 104500 47000 1500 2000 "clearline"]
+	Line[112000 57500 103500 67000 2500 2000 "clearline"]
+	Line[103500 67000 65500 67000 2500 2000 "clearline"]
+	Line[70500 71500 48000 70500 1500 2000 "clearline"]
+	Line[48000 80500 38000 83500 1500 2000 "clearline"]
+	Line[7000 83000 15000 83500 1500 2000 "clearline"]
 	Polygon("clearpoly")
 	(
-		[2500 65500] [2500 80500] [46000 80500] [46000 68000] [104500 68000] 
-		[104500 50000] [75500 50000] [73000 50000] [67500 55500] [45500 55500] 
-		[43500 57500] [25500 57500] [21000 62000] [3000 62000] [3000 65500] 
-		[3000 62000] [3000 63500] [3000 65500] [2000 65500] [2000 66500] 
-		[2000 68000] [2000 66500] [3000 65500] 
+		[2500 65000] [2500 82000] [46000 82000] [46000 67500] [103000 67500] 
+		[104000 66500] [104000 49000] [74000 49000] [67500 55500] [57500 55500] 
+		[56000 57000] [19500 57000] [11500 65000] 
 	)
 )
 Layer(2 "ground")
@@ -1481,14 +1461,11 @@
 	Line[139000 48000 140000 49000 1500 2000 "clearline"]
 	Line[66000 59000 66000 47000 1500 2000 "clearline"]
 	Line[71000 59000 71000 53500 1500 2000 "clearline"]
-	Line[71000 53500 76000 47000 1500 2000 "clearline"]
 	Line[70500 71500 71000 79500 1500 2000 "clearline"]
 	Line[76000 79500 76000 74000 1500 2000 "clearline"]
 	Line[66000 79500 65500 67000 1500 2000 "clearline"]
 	Line[38000 65500 38000 75000 1500 2000 "clearline"]
 	Line[38000 75000 44000 75000 1500 2000 "clearline"]
-	Line[44000 75000 48000 70500 1500 2000 "clearline"]
-	Line[25000 83500 25200 75000 1500 2000 "clearline"]
 	Line[25000 63000 25200 55500 1500 2000 "clearline"]
 	Line[89000 71300 88500 80500 2500 2000 "clearline"]
 	Line[224500 22000 230500 19500 2500 2000 "clearline"]
@@ -1519,7 +1496,6 @@
 	Line[155000 56000 165500 63000 1500 2000 "clearline"]
 	Line[170000 69500 171000 60500 1500 2000 "clearline"]
 	Line[165000 56000 165000 49000 1500 2000 "clearline"]
-	Line[184024 49000 185262 47762 1500 2000 "clearline"]
 	Line[165500 63000 165000 69500 1500 2000 "clearline"]
 	Line[165000 69500 166000 80500 1500 2000 "clearline"]
 	Line[150000 76500 150000 49000 1500 2000 "clearline"]
@@ -1541,76 +1517,13 @@
 	Line[169000 32500 163000 32000 1500 2000 "clearline"]
 	Line[132500 9000 132500 17200 2500 2000 "clearline"]
 	Line[148000 22500 141000 22000 1500 2000 "clearline"]
-	Line[71500 32000 72000 32000 1500 2000 ""]
-	Line[18000 33500 40500 33500 1500 2000 ""]
 	Line[40500 33500 41000 34000 1500 2000 ""]
-	Line[41000 34000 41000 38500 1500 2000 ""]
-	Line[41000 38500 43000 40500 1500 2000 ""]
-	Line[43000 40500 59500 40500 1500 2000 ""]
-	Line[59500 40500 61500 42500 1500 2000 ""]
-	Line[61500 42500 70500 42500 1500 2000 ""]
-	Line[70500 42500 76500 36500 1500 2000 ""]
-	Line[76500 36500 86000 36500 1500 2000 ""]
 	Line[86000 36500 86500 37000 1500 2000 ""]
-	Line[81000 59000 81000 37000 1500 2000 ""]
-	Line[81000 37000 81500 36500 1500 2000 ""]
-	Line[87000 37500 104000 37500 1500 2000 ""]
-	Line[104000 37500 109500 32000 1500 2000 ""]
-	Line[81000 59000 88500 59000 1500 2000 ""]
-	Line[88500 59000 89000 58500 1500 2000 ""]
-	Line[89000 58500 97500 58500 1500 2000 ""]
-	Line[97500 58500 99500 60500 1500 2000 ""]
-	Line[57500 68000 51000 61500 1500 2000 ""]
-	Line[51000 61500 51000 40500 1500 2000 ""]
-	Line[110500 23000 110500 31000 1500 2000 ""]
-	Line[110500 31000 109750 31750 1500 2000 ""]
-	Line[109750 31750 130750 31750 1500 2000 ""]
-	Line[130750 31750 132500 30000 1500 2000 ""]
 	Line[129500 58000 128500 58000 1500 2000 ""]
 	Line[128500 58000 124500 54000 1500 2000 ""]
 	Line[124500 54000 124500 31750 1500 2000 ""]
-	Line[129500 78500 131000 78500 1500 2000 ""]
-	Line[131000 78500 140000 69500 1500 2000 ""]
 	Line[130000 58000 133500 58000 1500 2000 ""]
-	Line[133500 58000 140000 64500 1500 2000 ""]
-	Line[140000 64500 140000 69500 1500 2000 ""]
-	Line[140000 69500 139750 69750 1500 2000 ""]
-	Line[212800 53700 224500 42000 1500 2000 ""]
-	Line[214000 24500 214000 37000 1500 2000 ""]
 	Line[214000 37000 214500 37500 1500 2000 ""]
-	Line[214500 37500 219000 37500 1500 2000 ""]
-	Line[219000 37500 224000 42500 1500 2000 ""]
-	Line[248000 19500 248000 23000 1500 2000 ""]
-	Line[248000 23000 244500 26500 1500 2000 ""]
-	Line[244500 26500 228500 26500 1500 2000 ""]
-	Line[228500 26500 226500 28500 1500 2000 ""]
-	Line[226500 28500 214000 28500 1500 2000 ""]
-	Line[214000 25500 207500 25500 1500 2000 ""]
-	Line[207500 25500 199000 17000 1500 2000 ""]
-	Line[199000 17000 199000 9100 1500 2000 ""]
-	Line[184000 35000 193000 35000 1500 2000 ""]
-	Line[193000 35000 205000 23000 1500 2000 ""]
-	Line[234500 26100 234500 32500 1500 2000 ""]
-	Line[169000 37500 181500 37500 1500 2000 ""]
-	Line[181500 37500 184000 35000 1500 2000 ""]
-	Line[130000 78500 130000 83000 1500 2000 ""]
-	Line[130000 83000 134000 87000 1500 2000 ""]
-	Line[134000 87000 168000 87000 1500 2000 ""]
-	Line[168000 87000 171000 84000 1500 2000 ""]
-	Line[171000 84000 171000 78500 1500 2000 ""]
-	Line[171000 78500 175000 74500 1500 2000 ""]
-	Line[175000 74500 175000 61000 1500 2000 ""]
-	Line[175000 61000 181500 54500 1500 2000 ""]
-	Line[181500 54500 212300 54500 1500 2000 ""]
-	Line[212300 54500 212800 54000 1500 2000 ""]
-	Line[170000 49000 170000 38000 1500 2000 ""]
-	Line[170000 38000 170500 37500 1500 2000 ""]
-	Line[7000 73000 15000 73000 1500 2000 ""]
-	Line[15000 73000 18500 69500 1500 2000 ""]
-	Line[18500 69500 30000 69500 1500 2000 ""]
-	Line[30000 69500 31500 68000 1500 2000 ""]
-	Line[31500 68000 31500 34000 1500 2000 ""]
-	Line[31500 34000 31000 33500 1500 2000 ""]
 	Line[148500 22500 157000 22500 1500 2000 "clearline"]
 	Line[157000 22500 162000 17500 1500 2000 "clearline"]
 	Line[162000 17500 169000 17500 1500 2000 "clearline"]
@@ -1618,61 +1531,31 @@
 	Line[157500 27500 162500 22500 1500 2000 "clearline"]
 	Line[176500 22500 162500 22500 1500 2000 "clearline"]
 	Line[99500 9000 109300 9000 1500 2000 "clearline"]
-	Line[109300 9000 110500 10200 1500 2000 "clearline"]
+	Line[229500 32500 240000 32500 1500 2000 ""]
+	Line[234500 26100 234500 37000 1500 2000 ""]
+	Line[132500 25000 132500 35500 1500 2000 ""]
+	Line[132500 35500 132000 36000 1500 2000 ""]
+	Line[126500 30000 137500 30000 1500 2000 ""]
+	Line[110500 17500 110500 27500 1500 2000 ""]
+	Line[105500 23000 115500 23000 1500 2000 ""]
+	Line[162500 37500 175500 37500 1500 2000 ""]
+	Line[170000 54000 170000 43000 1500 2000 ""]
+	Line[81000 52500 81000 64500 1500 2000 ""]
+	Line[89000 63500 89000 54000 1500 2000 ""]
+	Line[84000 58500 94000 58500 1500 2000 ""]
+	Line[140000 64500 140000 75000 1500 2000 ""]
+	Line[220500 65000 220500 55000 1500 2000 ""]
+	Line[224500 60000 215500 60000 1500 2000 ""]
+	Line[198500 60000 207500 60000 1500 2000 "clearline"]
+	Line[57500 73000 57500 62500 1500 2000 ""]
+	Line[52500 68000 61500 68000 1500 2000 ""]
+	Line[184000 40000 184000 30000 1500 2000 ""]
+	Line[179000 35000 188500 35000 1500 2000 ""]
+	Line[175000 64000 175000 74500 1500 2000 ""]
 	Line[122500 9000 111300 9000 1500 2000 "clearline"]
-	Line[111300 9000 110300 10000 1500 2000 "clearline"]
-	Line[49000 62000 51000 60000 1500 2000 ""]
-	Line[51000 60000 51000 61000 1500 2000 ""]
-	Line[51000 61000 49000 63000 1500 2000 ""]
-	Line[49000 63000 50000 64000 1500 2000 ""]
-	Line[50000 64000 50500 64000 1500 2000 ""]
-	Line[50500 64000 51000 64500 1500 2000 ""]
-	Line[51000 64500 50500 65000 1500 2000 ""]
-	Line[50500 65000 53500 65000 1500 2000 ""]
-	Line[53500 65000 54000 64500 1500 2000 ""]
-	Line[54000 64500 54000 64000 1500 2000 ""]
-	Line[54000 64000 54500 63500 1500 2000 ""]
-	Line[54500 63500 54500 61000 1500 2000 ""]
-	Line[54500 61000 54000 60500 1500 2000 ""]
-	Line[54000 60500 53500 60500 1500 2000 ""]
-	Line[53500 60500 53000 60000 1500 2000 ""]
-	Line[53000 60000 52000 60000 1500 2000 ""]
-	Line[106500 83000 109000 83000 1500 2000 ""]
-	Line[109000 83000 110500 84500 1500 2000 ""]
-	Line[110500 84500 110500 87000 1500 2000 ""]
-	Line[110500 87000 109500 88000 1500 2000 ""]
-	Line[109500 88000 107000 88000 1500 2000 ""]
-	Line[107000 88000 105500 86500 1500 2000 ""]
-	Line[105500 86500 105500 84500 1500 2000 ""]
-	Line[105500 84500 106500 83500 1500 2000 ""]
-	Line[12000 3000 12000 15500 1500 2000 ""]
-	Line[5500 9000 18500 9000 1500 2000 ""]
-	Line[10000 24500 10000 18500 1500 2000 ""]
-	Line[10000 24500 4000 24500 1500 2000 ""]
-	Line[10000 25000 10000 31000 1500 2000 ""]
-	Line[2000 18500 2500 18500 1500 2000 ""]
-	Line[2500 18500 3000 18000 1500 2000 ""]
-	Line[3000 18000 5000 18000 1500 2000 ""]
-	Line[5000 18000 6500 19500 1500 2000 ""]
-	Line[6500 19500 6500 21000 1500 2000 ""]
-	Line[6500 21000 6000 21500 1500 2000 ""]
-	Line[6000 21500 5500 21500 1500 2000 ""]
-	Line[5500 21500 4500 22500 1500 2000 ""]
-	Line[4500 22500 4500 23500 1500 2000 ""]
-	Line[4500 23500 3500 23500 1500 2000 ""]
-	Line[3500 23500 3000 23000 1500 2000 ""]
-	Line[3000 23000 3500 22500 1500 2000 ""]
-	Line[3500 22500 2000 22500 1500 2000 ""]
-	Line[2000 22500 2000 22000 1500 2000 ""]
-	Line[2000 22000 1500 21500 1500 2000 ""]
-	Line[1500 21500 1500 19500 1500 2000 ""]
-	Line[1500 19500 2000 19000 1500 2000 ""]
-	Line[213000 61000 213000 66500 1500 2000 ""]
-	Line[213000 61500 213000 56000 1500 2000 ""]
-	Line[207500 61000 217500 61000 1500 2000 ""]
-	Line[6500 21500 6000 22000 1500 2000 ""]
-	Line[6000 22000 6000 22500 1500 2000 ""]
-	Line[6000 22500 5500 23000 1500 2000 ""]
+	Line[71000 53500 76000 47000 1500 2000 "clearline"]
+	Line[44000 75000 48000 70500 1500 2000 "clearline"]
+	Line[25000 83500 25200 75000 1500 2000 "clearline"]
 	Polygon("clearpoly")
 	(
 		[0 90000] [256000 90000] [256000 0] [0 0] 
@@ -1693,22 +1576,21 @@
 )
 Layer(10 "silk")
 (
-	Arc[163000 32000 3500 3500 1500 2000 0 90 ""]
-	Arc[163000 32000 3500 3500 1500 2000 90 90 ""]
-	Arc[163000 32000 3500 3500 1500 2000 180 90 ""]
-	Arc[163000 32000 3500 3500 1500 2000 -90 90 ""]
-	Arc[155000 37500 3000 3000 1500 2000 0 90 ""]
-	Arc[155000 37500 3000 3000 1500 2000 90 90 ""]
-	Arc[155000 37500 3000 3000 1500 2000 180 90 ""]
-	Arc[155000 37500 3000 3000 1500 2000 -90 90 ""]
-	Arc[108000 85500 3000 3000 1500 2000 0 -90 ""]
-	Arc[108000 85500 3000 3000 1500 2000 -90 -90 ""]
-	Arc[108000 85500 3000 3000 1500 2000 180 -90 ""]
-	Arc[108000 85500 3000 3000 1500 2000 90 -90 ""]
-	Text[12000 64000 0 100 "Ring" "clearline"]
-	Text[11000 74000 0 100 "Tip" "clearline"]
-	Text[241000 3000 0 100 "+" "clearline"]
-	Text[241500 13000 0 100 "-" "clearline"]
+	Line[136000 7000 141000 5000 1000 2000 ""]
+	Arc[108000 85500 3000 3000 600 1200 -90 -90 ""]
+	Arc[108000 85500 3000 3000 600 1200 180 -90 ""]
+	Arc[108000 85500 3000 3000 600 1200 90 -90 ""]
+	Arc[155000 37500 3000 3000 600 1200 -90 -90 ""]
+	Arc[155000 37500 3000 3000 600 1200 180 -90 ""]
+	Arc[155000 37500 3000 3000 600 1200 90 -90 ""]
+	Arc[155000 37500 3000 3000 600 1200 0 -90 ""]
+	Arc[163000 32000 3000 3000 600 1200 0 -90 ""]
+	Arc[163000 32000 3000 3000 600 1200 -90 -90 ""]
+	Arc[163000 32000 3000 3000 600 1200 180 -90 ""]
+	Arc[163000 32000 3000 3000 600 1200 90 -90 ""]
+	Arc[108000 85500 3000 3000 600 1200 0 -90 ""]
+	Text[241000 3000 0 130 "+" "clearline"]
+	Text[241000 13000 0 130 "-" "clearline"]
 	Text[56500 75500 0 100 "SoftRock" "clearline"]
 	Text[57500 82000 0 100 "Lite II" "clearline"]
 	Text[136500 29000 0 100 "QSD" "clearline"]
@@ -1716,6 +1598,9 @@
 	Text[137000 34500 0 100 "clk_0" "clearline"]
 	Text[168000 28000 0 100 "clk_1" "clearline"]
 	Text[114000 82500 0 100 "GND" "clearline"]
+	Text[12000 64000 0 100 "Ring" "clearline"]
+	Text[11000 74000 0 100 "Tip" "clearline"]
+	Text[143000 2500 0 100 "5 VDC" "clearline"]
 )
 NetList()
 (

--- /dev/null
+++ b/src/data/pcb/ThermalTest.pcb
@@ -1,1 +1,851 @@
+# release: pcb 20110918
 
+# To read pcb files, the pcb version (or the git source date) must be >= the file version
+FileVersion[20070407]
+
+PCB["" 50000 50000]
+
+Grid[1000.0 0 0 0]
+Cursor[4000 43000 0.000000]
+PolyArea[3100.006200]
+Thermal[0.500000]
+DRC[1000 1000 1000 1000 1500 1000]
+Flags("nameonpcb,snappin")
+Groups("1,c:2:3:4:5:6,s:7:8")
+Styles["Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000:Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600"]
+
+Symbol[' ' 1800]
+(
+)
+Symbol['!' 1200]
+(
+	SymbolLine[0 4500 0 5000 800]
+	SymbolLine[0 1000 0 3500 800]
+)
+Symbol['"' 1200]
+(
+	SymbolLine[0 1000 0 2000 800]
+	SymbolLine[1000 1000 1000 2000 800]
+)
+Symbol['#' 1200]
+(
+	SymbolLine[0 3500 2000 3500 800]
+	SymbolLine[0 2500 2000 2500 800]
+	SymbolLine[1500 2000 1500 4000 800]
+	SymbolLine[500 2000 500 4000 800]
+)
+Symbol['$' 1200]
+(
+	SymbolLine[1500 1500 2000 2000 800]
+	SymbolLine[500 1500 1500 1500 800]
+	SymbolLine[0 2000 500 1500 800]
+	SymbolLine[0 2000 0 2500 800]
+	SymbolLine[0 2500 500 3000 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[2000 3500 2000 4000 800]
+	SymbolLine[1500 4500 2000 4000 800]
+	SymbolLine[500 4500 1500 4500 800]
+	SymbolLine[0 4000 500 4500 800]
+	SymbolLine[1000 1000 1000 5000 800]
+)
+Symbol['%' 1200]
+(
+	SymbolLine[0 1500 0 2000 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1000 1000 800]
+	SymbolLine[1000 1000 1500 1500 800]
+	SymbolLine[1500 1500 1500 2000 800]
+	SymbolLine[1000 2500 1500 2000 800]
+	SymbolLine[500 2500 1000 2500 800]
+	SymbolLine[0 2000 500 2500 800]
+	SymbolLine[0 5000 4000 1000 800]
+	SymbolLine[3500 5000 4000 4500 800]
+	SymbolLine[4000 4000 4000 4500 800]
+	SymbolLine[3500 3500 4000 4000 800]
+	SymbolLine[3000 3500 3500 3500 800]
+	SymbolLine[2500 4000 3000 3500 800]
+	SymbolLine[2500 4000 2500 4500 800]
+	SymbolLine[2500 4500 3000 5000 800]
+	SymbolLine[3000 5000 3500 5000 800]
+)
+Symbol['&' 1200]
+(
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[0 1500 0 2500 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[0 3500 1500 2000 800]
+	SymbolLine[500 5000 1000 5000 800]
+	SymbolLine[1000 5000 2000 4000 800]
+	SymbolLine[0 2500 2500 5000 800]
+	SymbolLine[500 1000 1000 1000 800]
+	SymbolLine[1000 1000 1500 1500 800]
+	SymbolLine[1500 1500 1500 2000 800]
+	SymbolLine[0 3500 0 4500 800]
+)
+Symbol[''' 1200]
+(
+	SymbolLine[0 2000 1000 1000 800]
+)
+Symbol['(' 1200]
+(
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[0 1500 0 4500 800]
+)
+Symbol[')' 1200]
+(
+	SymbolLine[0 1000 500 1500 800]
+	SymbolLine[500 1500 500 4500 800]
+	SymbolLine[0 5000 500 4500 800]
+)
+Symbol['*' 1200]
+(
+	SymbolLine[0 2000 2000 4000 800]
+	SymbolLine[0 4000 2000 2000 800]
+	SymbolLine[0 3000 2000 3000 800]
+	SymbolLine[1000 2000 1000 4000 800]
+)
+Symbol['+' 1200]
+(
+	SymbolLine[0 3000 2000 3000 800]
+	SymbolLine[1000 2000 1000 4000 800]
+)
+Symbol[',' 1200]
+(
+	SymbolLine[0 6000 1000 5000 800]
+)
+Symbol['-' 1200]
+(
+	SymbolLine[0 3000 2000 3000 800]
+)
+Symbol['.' 1200]
+(
+	SymbolLine[0 5000 500 5000 800]
+)
+Symbol['/' 1200]
+(
+	SymbolLine[0 4500 3000 1500 800]
+)
+Symbol['0' 1200]
+(
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[0 1500 0 4500 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[2000 1500 2000 4500 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[0 4000 2000 2000 800]
+)
+Symbol['1' 1200]
+(
+	SymbolLine[0 1800 800 1000 800]
+	SymbolLine[800 1000 800 5000 800]
+	SymbolLine[0 5000 1500 5000 800]
+)
+Symbol['2' 1200]
+(
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 2000 1000 800]
+	SymbolLine[2000 1000 2500 1500 800]
+	SymbolLine[2500 1500 2500 2500 800]
+	SymbolLine[0 5000 2500 2500 800]
+	SymbolLine[0 5000 2500 5000 800]
+)
+Symbol['3' 1200]
+(
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 2800 1500 2800 800]
+	SymbolLine[2000 1500 2000 2300 800]
+	SymbolLine[2000 3300 2000 4500 800]
+	SymbolLine[2000 3300 1500 2800 800]
+	SymbolLine[2000 2300 1500 2800 800]
+)
+Symbol['4' 1200]
+(
+	SymbolLine[0 3500 2000 1000 800]
+	SymbolLine[0 3500 2500 3500 800]
+	SymbolLine[2000 1000 2000 5000 800]
+)
+Symbol['5' 1200]
+(
+	SymbolLine[0 1000 2000 1000 800]
+	SymbolLine[0 1000 0 3000 800]
+	SymbolLine[0 3000 500 2500 800]
+	SymbolLine[500 2500 1500 2500 800]
+	SymbolLine[1500 2500 2000 3000 800]
+	SymbolLine[2000 3000 2000 4500 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+)
+Symbol['6' 1200]
+(
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[0 1500 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[1500 2800 2000 3300 800]
+	SymbolLine[0 2800 1500 2800 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[2000 3300 2000 4500 800]
+)
+Symbol['7' 1200]
+(
+	SymbolLine[500 5000 2500 1000 800]
+	SymbolLine[0 1000 2500 1000 800]
+)
+Symbol['8' 1200]
+(
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[0 3700 0 4500 800]
+	SymbolLine[0 3700 700 3000 800]
+	SymbolLine[700 3000 1300 3000 800]
+	SymbolLine[1300 3000 2000 3700 800]
+	SymbolLine[2000 3700 2000 4500 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[0 2300 700 3000 800]
+	SymbolLine[0 1500 0 2300 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[2000 1500 2000 2300 800]
+	SymbolLine[1300 3000 2000 2300 800]
+)
+Symbol['9' 1200]
+(
+	SymbolLine[500 5000 2000 3000 800]
+	SymbolLine[2000 1500 2000 3000 800]
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[0 1500 0 2500 800]
+	SymbolLine[0 2500 500 3000 800]
+	SymbolLine[500 3000 2000 3000 800]
+)
+Symbol[':' 1200]
+(
+	SymbolLine[0 2500 500 2500 800]
+	SymbolLine[0 3500 500 3500 800]
+)
+Symbol[';' 1200]
+(
+	SymbolLine[0 5000 1000 4000 800]
+	SymbolLine[1000 2500 1000 3000 800]
+)
+Symbol['<' 1200]
+(
+	SymbolLine[0 3000 1000 2000 800]
+	SymbolLine[0 3000 1000 4000 800]
+)
+Symbol['=' 1200]
+(
+	SymbolLine[0 2500 2000 2500 800]
+	SymbolLine[0 3500 2000 3500 800]
+)
+Symbol['>' 1200]
+(
+	SymbolLine[0 2000 1000 3000 800]
+	SymbolLine[0 4000 1000 3000 800]
+)
+Symbol['?' 1200]
+(
+	SymbolLine[1000 3000 1000 3500 800]
+	SymbolLine[1000 4500 1000 5000 800]
+	SymbolLine[0 1500 0 2000 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[2000 1500 2000 2000 800]
+	SymbolLine[1000 3000 2000 2000 800]
+)
+Symbol['@' 1200]
+(
+	SymbolLine[0 1000 0 4000 800]
+	SymbolLine[0 4000 1000 5000 800]
+	SymbolLine[1000 5000 4000 5000 800]
+	SymbolLine[5000 3500 5000 1000 800]
+	SymbolLine[5000 1000 4000 0 800]
+	SymbolLine[4000 0 1000 0 800]
+	SymbolLine[1000 0 0 1000 800]
+	SymbolLine[1500 2000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[2000 3500 3000 3500 800]
+	SymbolLine[3000 3500 3500 3000 800]
+	SymbolLine[3500 3000 4000 3500 800]
+	SymbolLine[3500 3000 3500 1500 800]
+	SymbolLine[3500 2000 3000 1500 800]
+	SymbolLine[2000 1500 3000 1500 800]
+	SymbolLine[2000 1500 1500 2000 800]
+	SymbolLine[4000 3500 5000 3500 800]
+)
+Symbol['A' 1200]
+(
+	SymbolLine[0 2000 0 5000 800]
+	SymbolLine[0 2000 700 1000 800]
+	SymbolLine[700 1000 1800 1000 800]
+	SymbolLine[1800 1000 2500 2000 800]
+	SymbolLine[2500 2000 2500 5000 800]
+	SymbolLine[0 3000 2500 3000 800]
+)
+Symbol['B' 1200]
+(
+	SymbolLine[0 5000 2000 5000 800]
+	SymbolLine[2000 5000 2500 4500 800]
+	SymbolLine[2500 3300 2500 4500 800]
+	SymbolLine[2000 2800 2500 3300 800]
+	SymbolLine[500 2800 2000 2800 800]
+	SymbolLine[500 1000 500 5000 800]
+	SymbolLine[0 1000 2000 1000 800]
+	SymbolLine[2000 1000 2500 1500 800]
+	SymbolLine[2500 1500 2500 2300 800]
+	SymbolLine[2000 2800 2500 2300 800]
+)
+Symbol['C' 1200]
+(
+	SymbolLine[700 5000 2000 5000 800]
+	SymbolLine[0 4300 700 5000 800]
+	SymbolLine[0 1700 0 4300 800]
+	SymbolLine[0 1700 700 1000 800]
+	SymbolLine[700 1000 2000 1000 800]
+)
+Symbol['D' 1200]
+(
+	SymbolLine[500 1000 500 5000 800]
+	SymbolLine[1800 1000 2500 1700 800]
+	SymbolLine[2500 1700 2500 4300 800]
+	SymbolLine[1800 5000 2500 4300 800]
+	SymbolLine[0 5000 1800 5000 800]
+	SymbolLine[0 1000 1800 1000 800]
+)
+Symbol['E' 1200]
+(
+	SymbolLine[0 2800 1500 2800 800]
+	SymbolLine[0 5000 2000 5000 800]
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 1000 2000 1000 800]
+)
+Symbol['F' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 1000 2000 1000 800]
+	SymbolLine[0 2800 1500 2800 800]
+)
+Symbol['G' 1200]
+(
+	SymbolLine[2000 1000 2500 1500 800]
+	SymbolLine[500 1000 2000 1000 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[0 1500 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 2000 5000 800]
+	SymbolLine[2000 5000 2500 4500 800]
+	SymbolLine[2500 3500 2500 4500 800]
+	SymbolLine[2000 3000 2500 3500 800]
+	SymbolLine[1000 3000 2000 3000 800]
+)
+Symbol['H' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[2500 1000 2500 5000 800]
+	SymbolLine[0 3000 2500 3000 800]
+)
+Symbol['I' 1200]
+(
+	SymbolLine[0 1000 1000 1000 800]
+	SymbolLine[500 1000 500 5000 800]
+	SymbolLine[0 5000 1000 5000 800]
+)
+Symbol['J' 1200]
+(
+	SymbolLine[700 1000 1500 1000 800]
+	SymbolLine[1500 1000 1500 4500 800]
+	SymbolLine[1000 5000 1500 4500 800]
+	SymbolLine[500 5000 1000 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[0 4500 0 4000 800]
+)
+Symbol['K' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 3000 2000 1000 800]
+	SymbolLine[0 3000 2000 5000 800]
+)
+Symbol['L' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 5000 2000 5000 800]
+)
+Symbol['M' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 1000 1500 3000 800]
+	SymbolLine[1500 3000 3000 1000 800]
+	SymbolLine[3000 1000 3000 5000 800]
+)
+Symbol['N' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 1000 2500 5000 800]
+	SymbolLine[2500 1000 2500 5000 800]
+)
+Symbol['O' 1200]
+(
+	SymbolLine[0 1500 0 4500 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[2000 1500 2000 4500 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+)
+Symbol['P' 1200]
+(
+	SymbolLine[500 1000 500 5000 800]
+	SymbolLine[0 1000 2000 1000 800]
+	SymbolLine[2000 1000 2500 1500 800]
+	SymbolLine[2500 1500 2500 2500 800]
+	SymbolLine[2000 3000 2500 2500 800]
+	SymbolLine[500 3000 2000 3000 800]
+)
+Symbol['Q' 1200]
+(
+	SymbolLine[0 1500 0 4500 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1500 1000 800]
+	SymbolLine[1500 1000 2000 1500 800]
+	SymbolLine[2000 1500 2000 4000 800]
+	SymbolLine[1000 5000 2000 4000 800]
+	SymbolLine[500 5000 1000 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[1000 3500 2000 5000 800]
+)
+Symbol['R' 1200]
+(
+	SymbolLine[0 1000 2000 1000 800]
+	SymbolLine[2000 1000 2500 1500 800]
+	SymbolLine[2500 1500 2500 2500 800]
+	SymbolLine[2000 3000 2500 2500 800]
+	SymbolLine[500 3000 2000 3000 800]
+	SymbolLine[500 1000 500 5000 800]
+	SymbolLine[1300 3000 2500 5000 800]
+)
+Symbol['S' 1200]
+(
+	SymbolLine[2000 1000 2500 1500 800]
+	SymbolLine[500 1000 2000 1000 800]
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[0 1500 0 2500 800]
+	SymbolLine[0 2500 500 3000 800]
+	SymbolLine[500 3000 2000 3000 800]
+	SymbolLine[2000 3000 2500 3500 800]
+	SymbolLine[2500 3500 2500 4500 800]
+	SymbolLine[2000 5000 2500 4500 800]
+	SymbolLine[500 5000 2000 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+)
+Symbol['T' 1200]
+(
+	SymbolLine[0 1000 2000 1000 800]
+	SymbolLine[1000 1000 1000 5000 800]
+)
+Symbol['U' 1200]
+(
+	SymbolLine[0 1000 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[2000 1000 2000 4500 800]
+)
+Symbol['V' 1200]
+(
+	SymbolLine[0 1000 1000 5000 800]
+	SymbolLine[1000 5000 2000 1000 800]
+)
+Symbol['W' 1200]
+(
+	SymbolLine[0 1000 0 3000 800]
+	SymbolLine[0 3000 500 5000 800]
+	SymbolLine[500 5000 1500 3000 800]
+	SymbolLine[1500 3000 2500 5000 800]
+	SymbolLine[2500 5000 3000 3000 800]
+	SymbolLine[3000 3000 3000 1000 800]
+)
+Symbol['X' 1200]
+(
+	SymbolLine[0 5000 2500 1000 800]
+	SymbolLine[0 1000 2500 5000 800]
+)
+Symbol['Y' 1200]
+(
+	SymbolLine[0 1000 1000 3000 800]
+	SymbolLine[1000 3000 2000 1000 800]
+	SymbolLine[1000 3000 1000 5000 800]
+)
+Symbol['Z' 1200]
+(
+	SymbolLine[0 1000 2500 1000 800]
+	SymbolLine[0 5000 2500 1000 800]
+	SymbolLine[0 5000 2500 5000 800]
+)
+Symbol['[' 1200]
+(
+	SymbolLine[0 1000 500 1000 800]
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 5000 500 5000 800]
+)
+Symbol['\' 1200]
+(
+	SymbolLine[0 1500 3000 4500 800]
+)
+Symbol[']' 1200]
+(
+	SymbolLine[0 1000 500 1000 800]
+	SymbolLine[500 1000 500 5000 800]
+	SymbolLine[0 5000 500 5000 800]
+)
+Symbol['^' 1200]
+(
+	SymbolLine[0 1500 500 1000 800]
+	SymbolLine[500 1000 1000 1500 800]
+)
+Symbol['_' 1200]
+(
+	SymbolLine[0 5000 2000 5000 800]
+)
+Symbol['a' 1200]
+(
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[0 3500 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[2000 3000 2000 4500 800]
+	SymbolLine[2000 4500 2500 5000 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+)
+Symbol['b' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[2000 3500 2000 4500 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[0 3500 500 3000 800]
+)
+Symbol['c' 1200]
+(
+	SymbolLine[500 3000 2000 3000 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[0 3500 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 2000 5000 800]
+)
+Symbol['d' 1200]
+(
+	SymbolLine[2000 1000 2000 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[0 3500 0 4500 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+)
+Symbol['e' 1200]
+(
+	SymbolLine[500 5000 2000 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[0 3500 0 4500 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[0 4000 2000 4000 800]
+	SymbolLine[2000 4000 2000 3500 800]
+)
+Symbol['f' 1000]
+(
+	SymbolLine[500 1500 500 5000 800]
+	SymbolLine[500 1500 1000 1000 800]
+	SymbolLine[1000 1000 1500 1000 800]
+	SymbolLine[0 3000 1000 3000 800]
+)
+Symbol['g' 1200]
+(
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[0 3500 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[0 6000 500 6500 800]
+	SymbolLine[500 6500 1500 6500 800]
+	SymbolLine[1500 6500 2000 6000 800]
+	SymbolLine[2000 3000 2000 6000 800]
+)
+Symbol['h' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[2000 3500 2000 5000 800]
+)
+Symbol['i' 1000]
+(
+	SymbolLine[0 2000 0 2100 1000]
+	SymbolLine[0 3500 0 5000 800]
+)
+Symbol['j' 1000]
+(
+	SymbolLine[500 2000 500 2100 1000]
+	SymbolLine[500 3500 500 6000 800]
+	SymbolLine[0 6500 500 6000 800]
+)
+Symbol['k' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+	SymbolLine[0 3500 1500 5000 800]
+	SymbolLine[0 3500 1000 2500 800]
+)
+Symbol['l' 1000]
+(
+	SymbolLine[0 1000 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+)
+Symbol['m' 1200]
+(
+	SymbolLine[500 3500 500 5000 800]
+	SymbolLine[500 3500 1000 3000 800]
+	SymbolLine[1000 3000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[2000 3500 2000 5000 800]
+	SymbolLine[2000 3500 2500 3000 800]
+	SymbolLine[2500 3000 3000 3000 800]
+	SymbolLine[3000 3000 3500 3500 800]
+	SymbolLine[3500 3500 3500 5000 800]
+	SymbolLine[0 3000 500 3500 800]
+)
+Symbol['n' 1200]
+(
+	SymbolLine[500 3500 500 5000 800]
+	SymbolLine[500 3500 1000 3000 800]
+	SymbolLine[1000 3000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[2000 3500 2000 5000 800]
+	SymbolLine[0 3000 500 3500 800]
+)
+Symbol['o' 1200]
+(
+	SymbolLine[0 3500 0 4500 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[2000 3500 2000 4500 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[0 4500 500 5000 800]
+)
+Symbol['p' 1200]
+(
+	SymbolLine[500 3500 500 6500 800]
+	SymbolLine[0 3000 500 3500 800]
+	SymbolLine[500 3500 1000 3000 800]
+	SymbolLine[1000 3000 2000 3000 800]
+	SymbolLine[2000 3000 2500 3500 800]
+	SymbolLine[2500 3500 2500 4500 800]
+	SymbolLine[2000 5000 2500 4500 800]
+	SymbolLine[1000 5000 2000 5000 800]
+	SymbolLine[500 4500 1000 5000 800]
+)
+Symbol['q' 1200]
+(
+	SymbolLine[2000 3500 2000 6500 800]
+	SymbolLine[1500 3000 2000 3500 800]
+	SymbolLine[500 3000 1500 3000 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[0 3500 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+)
+Symbol['r' 1200]
+(
+	SymbolLine[500 3500 500 5000 800]
+	SymbolLine[500 3500 1000 3000 800]
+	SymbolLine[1000 3000 2000 3000 800]
+	SymbolLine[0 3000 500 3500 800]
+)
+Symbol['s' 1200]
+(
+	SymbolLine[500 5000 2000 5000 800]
+	SymbolLine[2000 5000 2500 4500 800]
+	SymbolLine[2000 4000 2500 4500 800]
+	SymbolLine[500 4000 2000 4000 800]
+	SymbolLine[0 3500 500 4000 800]
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[500 3000 2000 3000 800]
+	SymbolLine[2000 3000 2500 3500 800]
+	SymbolLine[0 4500 500 5000 800]
+)
+Symbol['t' 1000]
+(
+	SymbolLine[500 1000 500 4500 800]
+	SymbolLine[500 4500 1000 5000 800]
+	SymbolLine[0 2500 1000 2500 800]
+)
+Symbol['u' 1200]
+(
+	SymbolLine[0 3000 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+	SymbolLine[2000 3000 2000 4500 800]
+)
+Symbol['v' 1200]
+(
+	SymbolLine[0 3000 1000 5000 800]
+	SymbolLine[2000 3000 1000 5000 800]
+)
+Symbol['w' 1200]
+(
+	SymbolLine[0 3000 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[500 5000 1000 5000 800]
+	SymbolLine[1000 5000 1500 4500 800]
+	SymbolLine[1500 3000 1500 4500 800]
+	SymbolLine[1500 4500 2000 5000 800]
+	SymbolLine[2000 5000 2500 5000 800]
+	SymbolLine[2500 5000 3000 4500 800]
+	SymbolLine[3000 3000 3000 4500 800]
+)
+Symbol['x' 1200]
+(
+	SymbolLine[0 3000 2000 5000 800]
+	SymbolLine[0 5000 2000 3000 800]
+)
+Symbol['y' 1200]
+(
+	SymbolLine[0 3000 0 4500 800]
+	SymbolLine[0 4500 500 5000 800]
+	SymbolLine[2000 3000 2000 6000 800]
+	SymbolLine[1500 6500 2000 6000 800]
+	SymbolLine[500 6500 1500 6500 800]
+	SymbolLine[0 6000 500 6500 800]
+	SymbolLine[500 5000 1500 5000 800]
+	SymbolLine[1500 5000 2000 4500 800]
+)
+Symbol['z' 1200]
+(
+	SymbolLine[0 3000 2000 3000 800]
+	SymbolLine[0 5000 2000 3000 800]
+	SymbolLine[0 5000 2000 5000 800]
+)
+Symbol['{' 1200]
+(
+	SymbolLine[500 1500 1000 1000 800]
+	SymbolLine[500 1500 500 2500 800]
+	SymbolLine[0 3000 500 2500 800]
+	SymbolLine[0 3000 500 3500 800]
+	SymbolLine[500 3500 500 4500 800]
+	SymbolLine[500 4500 1000 5000 800]
+)
+Symbol['|' 1200]
+(
+	SymbolLine[0 1000 0 5000 800]
+)
+Symbol['}' 1200]
+(
+	SymbolLine[0 1000 500 1500 800]
+	SymbolLine[500 1500 500 2500 800]
+	SymbolLine[500 2500 1000 3000 800]
+	SymbolLine[500 3500 1000 3000 800]
+	SymbolLine[500 3500 500 4500 800]
+	SymbolLine[0 5000 500 4500 800]
+)
+Symbol['~' 1200]
+(
+	SymbolLine[0 3500 500 3000 800]
+	SymbolLine[500 3000 1000 3000 800]
+	SymbolLine[1000 3000 1500 3500 800]
+	SymbolLine[1500 3500 2000 3500 800]
+	SymbolLine[2000 3500 2500 3000 800]
+)
+Attribute("PCB::grid::unit" "mil")
+Via[11000 14000 3600 2000 0 2000 "" "thermal(0)"]
+Via[18000 14000 3600 2000 0 2000 "" "thermal(0+)"]
+Via[25000 14000 3600 2000 0 2000 "" "thermal(0S)"]
+Via[32000 14000 3600 2000 0 2000 "" "thermal(0X)"]
+Via[39000 14000 3600 2000 0 2000 "" "thermal(0t)"]
+Via[11000 36000 3600 2000 0 2000 "" "thermal(0-2,5)"]
+Via[18000 36000 3600 2000 0 2000 "" "thermal(0X,5+)"]
+Via[25000 36000 3600 2000 0 2000 "" "thermal(5S)"]
+Via[32000 36000 3600 2000 0 2000 "" "thermal(0+,5X)"]
+Via[39000 36000 3600 2000 0 2000 "" "thermal(0,5t)"]
+Via[8000 24000 3600 2000 0 2000 "" ""]
+Layer(1 "top")
+(
+	Polygon("clearpoly")
+	(
+		[1000 1000] [49000 1000] [49000 48000] [1000 48000] 
+	)
+	Polygon("")
+	(
+		[4000 27000] [13000 27000] [13000 21000] [4000 21000] 
+	)
+)
+Layer(2 "ground")
+(
+	Polygon("clearpoly")
+	(
+		[3000 44000] [15000 44000] [15000 29000] [3000 29000] 
+	)
+)
+Layer(3 "signal2")
+(
+	Polygon("clearpoly")
+	(
+		[7000 40000] [15000 40000] [15000 29000] [7000 29000] 
+	)
+)
+Layer(4 "signal3")
+(
+)
+Layer(5 "power")
+(
+)
+Layer(6 "bottom")
+(
+	Polygon("clearpoly")
+	(
+		[1000 24000] [49000 24000] [49000 48000] [1000 48000] 
+	)
+)
+Layer(7 "outline")
+(
+)
+Layer(8 "spare")
+(
+)
+Layer(9 "silk")
+(
+)
+Layer(10 "silk")
+(
+)
+

--- a/src/data/shaders/2D.fs
+++ b/src/data/shaders/2D.fs
@@ -7,10 +7,12 @@
 uniform float innerRadius;
 uniform float startAngle;
 uniform float sweep;
+uniform float shaveInside;
 
 uniform bool arcEnabled;
 uniform bool roundPoints;
 uniform bool inverted;
+uniform bool shaveFF;
 
 void main(void) {
 	if(roundPoints){
@@ -20,9 +22,22 @@
     		discard;
 
 		if(arcEnabled){
+
+			float sx = gl_PointCoord.x - 0.5;
+			float sy = gl_PointCoord.y - 0.5;
+			if(shaveFF){
+				float sx2 = (sx + sy)/1.41421356237;
+				float sy2 = (sy - sx)/1.41421356237;
+				sx = sx2;
+				sy = sy2;
+			}
+			if(abs(sx) < shaveInside || abs(sy) < shaveInside)
+				discard;
+
 			float y_dif = gl_PointCoord.y - 0.5;
 			if(inverted)
 				y_dif = y_dif * -1.0;
+
 			float ang = atan(y_dif, gl_PointCoord.x - 0.5);
 			if(startAngle + sweep > M_PI){
 				if(ang < startAngle && ang > startAngle + sweep - M_PI * 2.0)

--- a/src/index.html
+++ b/src/index.html
@@ -7,11 +7,19 @@
 	</head>
 	<body>
 		<div style="text-align:center;">
-			PCB:
-			<select id="samplePCBs"></select>
-			<button id="load">Load</button>
-			<br>
-			<canvas id="pcbcan" width="800" height="600" tabindex="1"></canvas>
+			<div style="text-align:center;display:inline;">
+				PCB:
+				<select id="samplePCBs"></select>
+				Mode: 
+				<input type="radio" name="mode" id="Normal" value="Normal">Canvas2D
+				<input type="radio" name="mode" id="Accelerated" value="Accelerated" checked>WebGL
+				<button id="load">Load</button>
+			</div>
+			<div id="Status" style="display:inline;float:right;">
+			</div>
+			<div id="PCB-canvas-container">
+				<canvas id="pcbcan" width="800" height="600" tabindex="1"></canvas>
+			</div>
 		</div>
 	</body>
 </html>

--- /dev/null
+++ b/src/js/Util/DOM.js
@@ -1,1 +1,59 @@
+define(function(){
 
+	var dom = {};
+
+	dom.id = function(id){
+		return document.getElementById(id);
+	};
+
+	dom.create = function(tag){
+		return document.createElement(tag);
+	};
+
+	dom.offset = function(elem){
+
+		var doc = elem && elem.ownerDocument,
+		docElem = doc.documentElement,
+		box = elem.getBoundingClientRect();
+
+		return {x: box.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0), y: box.top  + (window.pageYOffset || docElem.scrollTop)  - (docElem.clientTop  || 0)};
+
+	};
+	
+	dom.multiple_callback = function(){
+
+		function callbacks(e){
+
+			for(var i = 0; i < callbacks.cb.length; i++)
+				callbacks.cb[i](e);
+
+		};
+
+		callbacks.cb = [];
+
+		return callbacks;
+
+	};
+
+	dom.add_callback = function(multi, callback){
+
+		multi.cb.push(callback);
+
+	};
+
+	dom.remove_callback = function(multi, callback){
+
+		for(var i = 0; i < multi.cb.length;){
+
+			if(multi.cb[i] == callback)
+				multi.cb.splice(i,1);
+			else
+				i++;
+				
+		}
+
+	};
+
+	return dom;
+
+});

--- /dev/null
+++ b/src/js/Util/Touch/Touch.js
@@ -1,1 +1,59 @@
+/**
+ * @author	Michael Marques <dryerzinia@gmail.com>
+ */
 
+/**
+ * @module Util
+ */
+
+define(
+	function(){
+
+		/**
+		 * Holds information about touches on the screen
+		 * @class Touch
+		 */
+
+		/**
+		 * @constructor
+		 */
+		var Touch = function(id, x, y){
+
+			/**
+			 * Unique ID of the touch
+			 * @property id
+			 * @type int
+			 */
+			this.id = id;
+			/**
+			 * X coordinate of the touch on the screen
+			 * @property x
+			 * @type int
+			 */
+			this.x = x;
+			/**
+			 * Y coordinate of the touch on the screen
+			 * @property y
+			 * @type int
+			 */
+			this.y = y;
+
+		};
+
+		/**
+		 * Creates a Touch from a browser native touch object
+		 * @method from_touch
+		 * @static
+		 * @param {touch} touch A Browser Native touch boject
+		 * @return A new touch object contstructed from a browser native touch object
+		 */
+		Touch.from_touch = function(touch){
+
+			return new Touch(touch.identifier, touch.pageX, touch.pageY);
+
+		};
+
+		return Touch;
+
+	}
+);

--- a/src/js/circuit/PCB/AccelerationManager.js
+++ /dev/null
@@ -1,11 +1,1 @@
-define(
-	function(){
 
-		var AccelerationManager = function(){
-			//
-		}
-
-		return AccelerationManager;
-
-	}
-);

--- a/src/js/circuit/PCB/Element.js
+++ b/src/js/circuit/PCB/Element.js
@@ -14,7 +14,6 @@
 				tx, ty, txtdir, txtscl, txtflg) {
 	
 			this.pcbv = pcbv;
-			this.flags = flags;
 			this.desc = desc;
 			this.refdes = refdes;
 			this.mx = mx;
@@ -26,75 +25,70 @@
 			this.txtflg = txtflg;
 			this.parts = [];
 	
+			this.flags = {
+				hidename: false,
+				onsolder: false
+			};
+
+			var split = flags.split(','), i;
+
+			for(i = 0; i < split.length; i++)
+				this.flags[split[i]] = true;
+
 		};
 	
 		Element.prototype.onsolder = function() {
 	
-			var splt = this.flags.split(',');
-	
-			for (var i = 0; i < splt.length; i++)
-				if (splt[i] == 'onsolder')
-					return true;
-			return false;
+			return this.flags.onsolder;
 	
 		};
 	
 		Element.prototype.render = function(ctx, color, mirror,	pins_only) {
-	
+
 			var i, sym, rot = 0;
 	
 			ctx.save();
 	
 			ctx.translate(this.mx, this.my);
-	
-			for (i = 0; i < this.parts.length; i++) {
-				if (pins_only) {
-					if (this.parts[i] instanceof Pin)
-						this.parts[i].render(ctx, color);
-				} else {
-					this.parts[i].render(ctx, color);
+
+			if(!this.flags.hidename){
+
+				switch(this.txtdir) {
+					case 0:
+						rot = 0;
+						break;
+					case 1:
+						rot = -0.5 * Math.PI;
+						break;
+					case 2:
+						rot = Math.PI;
+						break;
+					case 3:
+						rot = 0.5 * Math.PI;
+						break;
 				}
-			}
-	
-			if (pins_only) {
+		
+				ctx.save();
+				ctx.translate(this.tx, this.ty);
+		
+				if (mirror)
+					ctx.scale(1, -1);
+		
+				ctx.rotate(rot);
+		
+				for (i = 0; i < this.refdes.length; i++) {
+					sym = this.pcbv.symbols[this.refdes[i]];
+					sym.render(ctx, color);
+					ctx.translate(sym.width + 1000, 0);
+				}
+		
 				ctx.restore();
-				return;
-			}
-	
-			switch(this.txtdir) {
-				case 0:
-					rot = 0;
-					break;
-				case 1:
-					rot = -0.5 * Math.PI;
-					break;
-				case 2:
-					rot = Math.PI;
-					break;
-				case 3:
-					rot = 0.5 * Math.PI;
-					break;
-			}
-	
-			ctx.save();
-			ctx.translate(this.tx, this.ty);
-	
-			if (mirror)
-				ctx.scale(1, -1);
-	
-			ctx.rotate(rot);
-	
-			for (i = 0; i < this.refdes.length; i++) {
-				sym = this.pcbv.symbols[this.refdes[i]];
-				sym.render(ctx, color);
-				ctx.translate(sym.width + 1000, 0);
 			}
 	
 			ctx.restore();
-	
-			ctx.restore();
-	
 		};
+
+		Element.prototype.clear = function(ctx){};
 
 		Element.prototype.renderText = function(gl, shaderProgram){
 
@@ -144,13 +138,16 @@
 
 		Element.prototype.renderGL = function(gl, shaderProgram){
 
-			this.renderText(gl, shaderProgram);
+			if(!this.flags.hidename)
+				this.renderText(gl, shaderProgram);
 
 			//var i;
 			//for(i = 0; i < this.parts.length; i++)
 				//this.parts[i].renderGL(gl, shaderProgram);
 
 		}
+
+		Element.prototype.clearGL = function(gl, shaderProgram){};
 
 		Element.prototype.cleanupGL = function(gl){
 

--- a/src/js/circuit/PCB/ElementArc.js
+++ b/src/js/circuit/PCB/ElementArc.js
@@ -20,11 +20,21 @@
 		};
 	
 		ElementArc.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;
+				}
+			}
+
 			ctx.beginPath();
 			ctx.arc(
-				this.x,
-				this.y,
+				this._cache.x,
+				this._cache.y,
 				this.r1,
 				(Math.PI * 2) - (Math.PI * this.start / 180.0),
 				(Math.PI * 2) - (Math.PI * (this.start + this.sweep) / 180.0),
@@ -37,7 +47,9 @@
 			ctx.closePath();
 	
 		};
-	
+
+		ElementArc.prototype.clear = function(ctx){};
+
 		ElementArc.prototype.renderGL = function(gl, shaderProgram){
 	
 			var outerRadius, innerRadius, radiusRatio;
@@ -54,7 +66,7 @@
 				gl.uniform1f(shaderProgram.invertedUniform, false);
 			gl.uniform1f(shaderProgram.startAngleUniform, (this.start / 180.0 * Math.PI) - Math.PI);
 			gl.uniform1f(shaderProgram.sweepUniform, (this.sweep / 180.0 * Math.PI));
-		
+
 			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
 			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
 	
@@ -68,6 +80,8 @@
 			gl.uniform1f(shaderProgram.roundPointsUniform, false);
 	
 		}
+
+		ElementArc.prototype.clearGL = function(gl, shaderProgram){};
 
 		ElementArc.prototype.cleanupGL = function(gl){
 

--- a/src/js/circuit/PCB/ElementLine.js
+++ b/src/js/circuit/PCB/ElementLine.js
@@ -10,31 +10,55 @@
 
 	};
 
+	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) {
 
-		ctx.beginPath();
-		ctx.moveTo(this.x1, this.y1);
-		ctx.lineTo(this.x2, this.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){
 
 		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);
 
 		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);
@@ -44,6 +68,8 @@
 		gl.uniform1f(shaderProgram.roundPointsUniform, false);
 
 	};
+
+	ElementLine.prototype.clearGL = function(gl, shaderProgram){};
 
 	ElementLine.prototype.cleanupGL = function(gl){
 
@@ -63,7 +89,7 @@
 
 	};
 
-	ElementLine.prototype.setup3DArrayBuffer = function(gl, x, y){
+	ElementLine.prototype.generateLineBuffer = function(gl, thickness){
 
 		var vBuffer, ox1, oy1, ox2, oy2, x1, x2, x3, x4, y1, y2, y3, y4;
 
@@ -73,14 +99,15 @@
 		oy2 = this.y2;
 
 		vBuffer = gl.createBuffer();
+
 		gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
 
 		var rise = oy2 - oy1;
 		var run = ox2 - ox1;
 		var magnitude = Math.sqrt(rise * rise + run * run);
 
-		var xshift = rise / magnitude * (this.thick / 2);
-		var yshift = run / magnitude * (this.thick / 2);
+		var xshift = rise / magnitude * (thickness / 2);
+		var yshift = run / magnitude * (thickness / 2);
 
 		if(this.parent){
 			ox1 += this.parent.mx;
@@ -110,9 +137,30 @@
 		vBuffer.itemSize = 3;
 		vBuffer.numItems = 4;
 
-		this.vertexBuffer = vBuffer;
+		return vBuffer;
+
+	}
+
+	ElementLine.prototype.setup3DArrayBuffer = function(gl, x, y){
+
+		var vBuffer, ox1, oy1, ox2, oy2;
+
+		ox1 = this.x1;
+		oy1 = this.y1;
+		ox2 = this.x2;
+		oy2 = this.y2;
+
+		if(this.parent){
+			ox1 += this.parent.mx;
+			oy1 += this.parent.my;
+			ox2 += this.parent.mx;
+			oy2 += this.parent.my;
+		}
+
+		this.vertexBuffer = this.generateLineBuffer(gl, this.thick);
 
 		vBuffer = gl.createBuffer();
+
 		gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
 		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ox1,oy1,0.0,ox2,oy2,0.0]), gl.STATIC_DRAW);
 		vBuffer.itemSize = 3;

--- a/src/js/circuit/PCB/Layer.js
+++ b/src/js/circuit/PCB/Layer.js
@@ -1,101 +1,222 @@
-define(function(){
-
-	var Layer = function(pcbv, number, name, parts){
-
-		this.pcbv = pcbv;
-
-		this.number = number;
-		this.name = name;
-
-		this.visible = true;
-
-		if(parts) this.parts = parts;
-		else this.parts = [];
-
-	};
-
-	Layer.SOLDER = 0;
-	Layer.TOP = 1;
-
-	Layer.prototype.addPart = function(part){
-
-		this.parts.push(part);
-
-	};
-
-	Layer.prototype.render = function(ctx, color){
-
-		if(!color) color = this.pcbv.getLayerColors()[this.number-1];
-
-		for(var p = 0; p < this.parts.length; p++)
-			this.parts[p].render(ctx, color);
-
-	};
-
-	Layer.prototype.renderGL = function(gl, shaderProgram, oMatrix, mvMatrix, color){
-
-		gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
-
-		gl.viewport(0, 0, this.framebuffer.width, this.framebuffer.height);
-		gl.clearColor(0.0, 0.0, 0.0, 0.0);
-		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-		gl.uniform4f(shaderProgram.vColorUniform, color.r, color.g, color.b, 1.0);
-
-		var i;
-		for(i = 0; i < this.parts.length; i++)
-			this.parts[i].renderGL(gl, shaderProgram);
+define(
+	[
+	 	"./Polygon"
+	],
+	function(
+		Polygon
+	){
+
+		var Layer = function(pcbv, number, name, parts){
+	
+			this.pcbv = pcbv;
+	
+			this.number = number;
+			this.name = name;
+	
+			this.visible = true;
+	
+			if(parts) this.parts = parts;
+			else this.parts = [];
+
+			this.polygons = [];
+	
+		};
+	
+		Layer.SOLDER = 0;
+		Layer.TOP = 1;
+
+		Layer.prototype._renderPolygons = function(ctx, color, pins, elements){
+
+			var clearing = false;
+
+			// render clear polygons first
+			for(i = 0; i < this.polygons.length; i++)
+				if(this.polygons[i].isClear()){
+					this.polygons[i].render(ctx, color);
+					clearing = true;
+				}
+
+			// clear pins, same layer pads, and other clearing objects
+			if(clearing){
+				ctx.globalCompositeOperation = "destination-out";
+				ctx.strokeStyle = 'rgba(0,0,0,1)';
+				ctx.fillStyle = 'rgba(0,0,0,1)';
+				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, this.number);
+				ctx.globalCompositeOperation = "source-over";
+
+			}
+
+			// Render non clearing polygons
+			for(i = 0; i < this.polygons.length; i++)
+				if(!this.polygons[i].isClear())
+					this.polygons[i].render(ctx, color);
+
+			// Clear centers
+			ctx.globalCompositeOperation = "destination-out";
+			ctx.strokeStyle = 'rgba(0,0,0,1)';
+			ctx.fillStyle = 'rgba(0,0,0,1)';
+			if(pins)
+				for(i = 0; i < pins.parts.length; i++)
+					pins.parts[i].clearInner(ctx);
+			ctx.globalCompositeOperation = "source-over";
+
+		}
+
+		Layer.prototype._renderPolygonsGL = function(gl, shaderProgram, color, pins, elements){
+
+			var clearing = false;
+
+			// render clear polygons first
+			gl.uniform4f(shaderProgram.vColorUniform, color.r, color.g, color.b, 1.0);
+			for(i = 0; i < this.polygons.length; i++)
+				if(this.polygons[i].isClear()){
+					this.polygons[i].renderGL(gl, shaderProgram);
+					clearing = true;
+				}
+
+			// render alpha of pins, same layer pads, and other clearing objects
+			// Pins and vias clear specially if they have thermals
+			if(clearing){
+				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(elements)
+					for(i = 0; i < elements.parts.length; i++)
+						elements.parts[i].clearGL(gl, shaderProgram);
+				if(pins)
+					for(i = 0; i < pins.parts.length; i++)
+						pins.parts[i].clearGL(gl, shaderProgram, this.number);
+			}
+
+			// render non clear polygons
+			gl.uniform4f(shaderProgram.vColorUniform, color.r, color.g, color.b, 1.0);
+			for(i = 0; i < this.polygons.length; i++)
+				if(!this.polygons[i].isClear())
+					this.polygons[i].renderGL(gl, shaderProgram);
+
+			// Clear centers
+			gl.uniform4f(shaderProgram.vColorUniform, 0.0, 0.0, 0.0, 0.0);
+			if(pins)
+				for(i = 0; i < pins.parts.length; i++)
+					pins.parts[i].clearInnerGL(gl, shaderProgram);
+
+		}
+
+		Layer.prototype.isEmpty = function(){
+			return this.parts.length == 0 && this.polygons.length == 0;
+		}
+
+		Layer.prototype.hasPolygons = function(){
+			return this.polygons.length != 0;
+		};
+
+		Layer.prototype.addPart = function(part){
+			this.parts.push(part);
+		};
+
+		Layer.prototype.seperatePolygons = function(){
+			for(var i = 0; i < this.parts.length;)
+				if(this.parts[i] instanceof Polygon)
+					this.polygons.push(this.parts.splice(i, 1)[0]);
+				else i++;
+
+		};
+
+		Layer.prototype.render = function(ctx, color, pins, elements){
+
+			if(!color) color = this.pcbv.getLayerColors()[this.number-1];
+
+			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, color, pins, elements){
+	
+			gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
+
+			gl.viewport(0, 0, this.framebuffer.width, this.framebuffer.height);
+			gl.clearColor(0.0, 0.0, 0.0, 0.0);
+			gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+	
+			if(this.hasPolygons()) this._renderPolygonsGL(gl, shaderProgram, color, pins, elements);
+			gl.uniform4f(shaderProgram.vColorUniform, color.r, color.g, color.b, 1.0);
+			for(var i = 0; i < this.parts.length; i++)
+				this.parts[i].renderGL(gl, shaderProgram);
+
+		}
+	
+		Layer.prototype.cleanupGL = function(gl){
+	
+			var i;
+			for(i = 0; i < this.parts.length; i++)
+				this.parts[i].cleanupGL(gl);
+	
+			gl.deleteTexture(this.texture);
+			gl.deleteRenderbuffer(this.renderbuffer);
+			gl.deleteFramebuffer(this.framebuffer);
+	
+		}
+	
+		Layer.prototype.init3DArrays = function(gl){
+	
+			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){
+	
+	        this.framebuffer.width = gl.viewportWidth;
+	        this.framebuffer.height = gl.viewportHeight;
+	
+	        gl.bindTexture(gl.TEXTURE_2D, this.texture);
+	        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.framebuffer.width, this.framebuffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+	        gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderbuffer);
+	        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.framebuffer.width, this.framebuffer.height);
+	
+		}
+	
+		Layer.prototype.setupFramebuffer = function(gl){
+	
+	        this.framebuffer = gl.createFramebuffer();
+	        gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
+	        this.framebuffer.width = gl.viewportWidth;
+	        this.framebuffer.height = gl.viewportHeight;
+	
+	        this.texture = gl.createTexture();
+	        gl.bindTexture(gl.TEXTURE_2D, this.texture);
+	        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+	        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+	        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+	
+	        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.framebuffer.width, this.framebuffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+	
+	        this.renderbuffer = gl.createRenderbuffer();
+	        gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderbuffer);
+	        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.framebuffer.width, this.framebuffer.height);
+	
+	        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
+	        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderbuffer);
+	
+	        gl.bindTexture(gl.TEXTURE_2D, null);
+	        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+	        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+	
+		}
+	
+		return Layer;
 
 	}
-
-	Layer.prototype.cleanupGL = function(gl){
-
-		var i;
-		for(i = 0; i < this.parts.length; i++)
-			this.parts[i].cleanupGL(gl);
-
-		gl.deleteTexture(this.texture);
-		gl.deleteRenderbuffer(this.renderbuffer);
-		gl.deleteFramebuffer(this.framebuffer);
-
-	}
-
-	Layer.prototype.init3DArrays = function(gl){
-
-		var i;
-		for(i = 0; i < this.parts.length; i++)
-			this.parts[i].setup3DArrayBuffer(gl, 0, 0);
-
-	}
-
-	Layer.prototype.setupFramebuffer = function(gl, width, height){
-
-        this.framebuffer = gl.createFramebuffer();
-        gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
-        this.framebuffer.width = width;
-        this.framebuffer.height = height;
-
-        this.texture = gl.createTexture();
-        gl.bindTexture(gl.TEXTURE_2D, this.texture);
-        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
-        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
-        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
-
-        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.framebuffer.width, this.framebuffer.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
-
-        this.renderbuffer = gl.createRenderbuffer();
-        gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderbuffer);
-        gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.framebuffer.width, this.framebuffer.height);
-
-        gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);
-        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderbuffer);
-
-        gl.bindTexture(gl.TEXTURE_2D, null);
-        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
-        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
-
-	}
-
-	return Layer;
-
-});
+);

--- a/src/js/circuit/PCB/LayerManager.js
+++ /dev/null
@@ -1,269 +1,1 @@
-define(
-	[
-	 	"./Layer",
-	 	"Graphics/glMatrix"
-	],
-	function(
-		Layer,
-		glMatrix
-	){
 
-		var LayerManager = function(layers){
-
-			var l, layer;
-
-			this.layers = layers;
-
-			this.topSilk = null;
-			this.bottomSkil = null;
-
-			this.top = null;
-			this.solder = null;
-			this.pins = null;
-
-			this.otherLayers = [];
-
-			for(l = 0; l < layers.length; l++){
-
-				layer = layers[l];
-
-				if(layer.name == "silk"){
-					if(!this.topSilk) this.topSilk = layer;
-					else this.bottomSilk = layer;
-				}
-				else {
-					this.otherLayers.push(layer);
-				}
-
-			}
-
-		}
-
-		LayerManager.prototype.setupGL = function(gl, width, height){
-
-			this.height = height;
-
-			this.boardVertexBuffer = gl.createBuffer();
-			gl.bindBuffer(gl.ARRAY_BUFFER, this.boardVertexBuffer);
-			vertices = [
-			 width, height,  -1.0,
-			  -1.0, height,  -1.0,
-			 width,   -1.0,  -1.0,
-			  -1.0,   -1.0,  -1.0
-			];
-			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
-			this.boardVertexBuffer.itemSize = 3;
-			this.boardVertexBuffer.numItems = 4;
-			
-			this.layerVertexPositionBuffer = gl.createBuffer();
-		    gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexPositionBuffer);
-		    vertices = [
-		     -1.0, -1.0,  1.0,
-		      1.0, -1.0,  1.0,
-		      1.0,  1.0,  1.0,
-		     -1.0,  1.0,  1.0,
-		    ];
-		    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
-		    this.layerVertexPositionBuffer.itemSize = 3;
-		    this.layerVertexPositionBuffer.numItems = 4;
-
-		    this.layerVertexTextureCoordBuffer = gl.createBuffer();
-		    gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexTextureCoordBuffer);
-		    var textureCoords = [
-		      0.0, 0.0,
-		      1.0, 0.0,
-		      1.0, 1.0,
-		      0.0, 1.0,
-		    ];
-		    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
-		    this.layerVertexTextureCoordBuffer.itemSize = 2;
-		    this.layerVertexTextureCoordBuffer.numItems = 4;
-
-		    this.layerVertexIndexBuffer = gl.createBuffer();
-	        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.layerVertexIndexBuffer);
-	        var cubeVertexIndices = [
-	            0, 1, 2,      0, 2, 3
-	        ];
-	        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
-	        this.layerVertexIndexBuffer.itemSize = 1;
-	        this.layerVertexIndexBuffer.numItems = 6;
-
-		}
-
-		LayerManager.prototype.renderGL = function(gl, shaderProgram, textureShaderProgram, side, offsetX, offsetY, scaleFactor){
-			
-			var oMatrix, mvMatrix, i, r, g, b, l, color;
-
-			oMatrix = glMatrix.mat4.create();
-			mvMatrix = glMatrix.mat4.create();
-
-			gl.scaleFactor = scaleFactor;
-			gl.oMatrix = oMatrix;
-			gl.mvMatrix = mvMatrix;
-			gl.side = side;
-
-			glMatrix.mat4.ortho(0, gl.viewportWidth, gl.viewportHeight, 0, -10, 10, oMatrix);
-
-			glMatrix.mat4.identity(mvMatrix);
-
-			if(side == Layer.TOP){
-				glMatrix.mat4.scale(mvMatrix, [1.0, -1.0, 1.0]);
-				glMatrix.mat4.translate(mvMatrix, [0.0, -gl.viewportHeight, 0.0]);
-			}
-
-			glMatrix.mat4.scale(mvMatrix, [scaleFactor, scaleFactor, 1.0]);
-			glMatrix.mat4.translate(mvMatrix, [-offsetX, -offsetY, 0.0]);
-
-	        gl.disableVertexAttribArray(textureShaderProgram.textureCoordAttribute);
-	        gl.disable(gl.BLEND);
-
-	        gl.useProgram(shaderProgram);
-
-			gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, oMatrix);
-	        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
-
-			if(side == Layer.TOP){
-
-				this.topSilk.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0});
-				this.bottomSilk.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0});
-
-				this.top.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0});
-				this.solder.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0});
-
-			} else {
-
-				this.topSilk.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0});
-				this.bottomSilk.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0});
-
-				this.top.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 0.0, g: 0.0, b: 0.0});
-				this.solder.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0});
-
-			}
-
-			this.pins.renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: 1.0, g: 1.0, b: 1.0});
-
-			for(l = 0; l < this.otherLayers.length; l++){
-
-				color = this.otherLayers[l].pcbv.getLayerColors()[l];
-
-				r = parseInt(color.substring(1, 3), 16) / 256;
-				g = parseInt(color.substring(3, 5), 16) / 256;
-				b = parseInt(color.substring(5, 7), 16) / 256;
-
-				this.otherLayers[l].renderGL(gl, shaderProgram, oMatrix, mvMatrix, {r: r, g: g, b: b});
-
-			}
-
-			gl.bindFramebuffer(gl.FRAMEBUFFER, null);
-
-			// Draw Board
-			gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
-			gl.clearColor(0.79, 0.79, 0.79, 1.0);
-			gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-			gl.uniform4f(shaderProgram.vColorUniform, 0.89, 0.89, 0.89, 1.0);
-
-			gl.bindBuffer(gl.ARRAY_BUFFER, this.boardVertexBuffer);
-			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.boardVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
-			gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.boardVertexBuffer.numItems);
-
-			// Setup texture program
-	        gl.useProgram(textureShaderProgram);
-
-			glMatrix.mat4.ortho(-1, 1, -1, 1, -1, 1, oMatrix);
-			glMatrix.mat4.identity(mvMatrix);
-
-			gl.uniformMatrix4fv(textureShaderProgram.pMatrixUniform, false, oMatrix);
-	        gl.uniformMatrix4fv(textureShaderProgram.mvMatrixUniform, false, mvMatrix);
-
-	        gl.enableVertexAttribArray(textureShaderProgram.textureCoordAttribute);
-
-	        gl.enable(gl.BLEND);
-
-	        // Draw Layer
-	        gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexPositionBuffer);
-	        gl.vertexAttribPointer(textureShaderProgram.vertexPositionAttribute, this.layerVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
-
-	        gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexTextureCoordBuffer);
-	        gl.vertexAttribPointer(textureShaderProgram.textureCoordAttribute, this.layerVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
-
-	        gl.activeTexture(gl.TEXTURE0);
-	        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.layerVertexIndexBuffer);
-
-	        if(side != Layer.TOP){
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.topSilk.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.solder.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        	for(l = this.otherLayers.length - 1; l >= 0; l--){
-
-					if(this.otherLayers[l].parts.length != 0){
-						gl.bindTexture(gl.TEXTURE_2D, this.otherLayers[l].texture);
-						gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-					}
-
-				}
-
-				gl.bindTexture(gl.TEXTURE_2D, this.top.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.pins.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.bottomSilk.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        } else {
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.bottomSilk.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-				gl.bindTexture(gl.TEXTURE_2D, this.top.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        	for(l = 0; l < this.otherLayers.length; l++){
-
-					if(this.otherLayers[l].parts.length != 0){
-						gl.bindTexture(gl.TEXTURE_2D, this.otherLayers[l].texture);
-						gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-					}
-
-				}
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.solder.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.pins.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        	gl.bindTexture(gl.TEXTURE_2D, this.topSilk.texture);
-	        	gl.drawElements(gl.TRIANGLES, this.layerVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
-
-	        }
-
-
-		}
-
-		LayerManager.prototype.init3DArrays = function(gl){
-
-			var l;
-			for(l in this.layers)
-				this.layers[l].init3DArrays(gl);
-
-		}
-
-		LayerManager.prototype.setupFramebuffers = function(gl, width, height){
-
-			var l;
-			for(l in this.layers)
-				this.layers[l].setupFramebuffer(gl, width, height);
-
-		}
-
-		return LayerManager;
-
-	}
-);

--- a/src/js/circuit/PCB/Line.js
+++ b/src/js/circuit/PCB/Line.js
@@ -8,14 +8,87 @@
 		Class
 	){
 
-		var Line = function(x1, y1, x2, y2, thick, notsure, notsure2){
+		var Line = function(x1, y1, x2, y2, thick, clearance, flags){
 	
 			ElementLine.call(this, x1, y1, x2, y2, thick);
-			
+
+			this.clearance = clearance;
+			this.flags = 
+			{
+				clearline: false
+			};
+
+			if(flags){
+				var split = flags.split(','), i;
+
+				for(i = 0; i < split.length; i++){
+					this.flags[split[i]] = true;
+				}
+			}
+
 		};
 	
 		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){
+
+			if(this.flags.clearline){
+
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.clearBuffer);
+				gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.clearBuffer.itemSize, gl.FLOAT, false, 0, 0);
+				gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.clearBuffer.numItems);
 	
+				gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+	
+				gl.uniform1f(shaderProgram.pointsizeUniform, (this.thick + this.clearance) * gl.scaleFactor);
+				gl.uniform1f(shaderProgram.roundPointsUniform, true);
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+				gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+				gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+				gl.uniform1f(shaderProgram.roundPointsUniform, false);
+
+			}
+
+		};
+
+		Line.prototype.setup3DArrayBuffer = function(gl, x, y){
+
+			var vBuffer, ox1, oy1, ox2, oy2;
+
+			ox1 = this.x1;
+			oy1 = this.y1;
+			ox2 = this.x2;
+			oy2 = this.y2;
+
+			if(this.parent){
+				ox1 += this.parent.mx;
+				oy1 += this.parent.my;
+				ox2 += this.parent.mx;
+				oy2 += this.parent.my;
+			}
+
+			this.vertexBuffer = this.generateLineBuffer(gl, this.thick);
+			this.clearBuffer = this.generateLineBuffer(gl, (this.thick + this.clearance));
+
+			vBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ox1,oy1,0.0,ox2,oy2,0.0]), gl.STATIC_DRAW);
+			vBuffer.itemSize = 3;
+			vBuffer.numItems = 2;
+			this.pointBuffer = vBuffer;
+
+		};
+		
 		return Line;
 
 	}

--- a/src/js/circuit/PCB/PCBViewer.js
+++ b/src/js/circuit/PCB/PCBViewer.js
@@ -18,14 +18,12 @@
 	 	"./Element",
 	 	"./ElementLine",
 	 	"./ElementArc",
+	 	"./Polygon",
 	 	"./Symbol",
-	 	"./LayerManager",
-	 	"Graphics/glMatrix",
-	 	"Graphics/GLHelper",
-	 	"text!../../../data/shaders/2D.fs",
-	 	"text!../../../data/shaders/2D.vs",
-	 	"text!../../../data/shaders/Texture.fs",
-	 	"text!../../../data/shaders/Texture.vs"
+	 	"./Renderers/TwoDRenderer",
+	 	"./Renderers/GLRenderer",
+	 	"Util/DOM",
+	 	"Util/Touch/Touch"
 	],
 	function(
 		Line,
@@ -37,19 +35,15 @@
 		Element,
 		ElementLine,
 		ElementArc,
+		Polygon,
 		Symbol,
-		LayerManager,
-		glMatrix,
-		GLHelper,
-		FragmentShader2Dtxt,
-		VertexShader2Dtxt,
-		FragmentShaderTextxt,
-		VertexShaderTextxt
+		TwoDRenderer,
+		GLRenderer,
+		DOM,
+		Touch
 	){
 
-		function PCBV(canvas, attach) {
-
-			var gl;
+		function PCBV(canvas, attach, mode) {
 
 			this._layerColors = PCBV._defaultLayerColors;
 
@@ -63,7 +57,11 @@
 
 			if(attach){
 
-				this.ctx = false;//PCBV._getWebGL(canvas);
+				if(mode == "Normal")
+					this.ctx = false;
+				else
+					this.ctx = PCBV._getWebGL(canvas);
+
 				if(this.ctx == false){
 
 					this.mode = "Normal";
@@ -72,126 +70,23 @@
 				} else {
 
 					this.mode = "Accelerated";
-
-					gl = this.ctx;
-
-					gl.viewportWidth = canvas.width;
-					gl.viewportHeight = canvas.height;
-
-					// 2D Shader
-
-					this.shaderProgram = GLHelper.createProgram(gl, 
-							GLHelper.createShader(gl, gl.VERTEX_SHADER, VertexShader2Dtxt),
-							GLHelper.createShader(gl, gl.FRAGMENT_SHADER, FragmentShader2Dtxt));
-
-					this.shaderProgram.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
-			        gl.enableVertexAttribArray(this.shaderProgram.vertexPositionAttribute);
-
-			        this.shaderProgram.pMatrixUniform = gl.getUniformLocation(this.shaderProgram, "uPMatrix");
-			        this.shaderProgram.mvMatrixUniform = gl.getUniformLocation(this.shaderProgram, "uMVMatrix");
-			        this.shaderProgram.vColorUniform = gl.getUniformLocation(this.shaderProgram, "vColor");
-
-			        this.shaderProgram.pointsizeUniform = gl.getUniformLocation(this.shaderProgram, "pointsize");
-			        this.shaderProgram.innerRadiusUniform = gl.getUniformLocation(this.shaderProgram, "innerRadius");
-			        this.shaderProgram.roundPointsUniform = gl.getUniformLocation(this.shaderProgram, "roundPoints");
-			        this.shaderProgram.startAngleUniform = gl.getUniformLocation(this.shaderProgram, "startAngle");
-			        this.shaderProgram.sweepUniform = gl.getUniformLocation(this.shaderProgram, "sweep");
-			        this.shaderProgram.arcEnabledUniform = gl.getUniformLocation(this.shaderProgram, "arcEnabled");
-			        this.shaderProgram.invertedUniform = gl.getUniformLocation(this.shaderProgram, "inverted");
-
-			        // Texture Shader
-
-					this.texShaderProgram = GLHelper.createProgram(gl, 
-							GLHelper.createShader(gl, gl.VERTEX_SHADER, VertexShaderTextxt),
-							GLHelper.createShader(gl, gl.FRAGMENT_SHADER, FragmentShaderTextxt));
-
-			        this.texShaderProgram.vertexPositionAttribute = gl.getAttribLocation(this.texShaderProgram, "aVertexPosition");
-			        gl.enableVertexAttribArray(this.texShaderProgram.vertexPositionAttribute);
-
-			        this.texShaderProgram.textureCoordAttribute = gl.getAttribLocation(this.texShaderProgram, "aTextureCoord");
-			        gl.enableVertexAttribArray(this.texShaderProgram.textureCoordAttribute);
-
-			        this.texShaderProgram.pMatrixUniform = gl.getUniformLocation(this.texShaderProgram, "uPMatrix");
-			        this.texShaderProgram.mvMatrixUniform = gl.getUniformLocation(this.texShaderProgram, "uMVMatrix");
-			        this.texShaderProgram.samplerUniform = gl.getUniformLocation(this.texShaderProgram, "uSampler");
-
-			        // Viewport setup
-			        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
 
 				}
 
 				this.last_time = 0;
 				this.end_time = 0;
 		
-				this.clicking = false;
-			
-				this.mouse_x = canvas.width/2;
-				this.mouse_y = canvas.height/2;
+				this._setupEventHandlers();
+
+			};
+
+			console.log("Mode: " + this.mode);
 		
-				this.mouseUpFunction = function(t){return function(e){if(e.which == 1) t.clicking = false;};}(this);
-				this.mouseDownFunction = function(t){return function(e){if(e.which == 1) t.clicking = true;};}(this)
-				this.keyDownFunction = function(t){return function(e){t.update_key(e);};}(this);
-				this.mouseMoveFunction = function(t){return function(e){
-					if(t.clicking)
-						t.update_mouse_drag(t.mouse_x-e.pageX, t.mouse_y-e.pageY);		
-					t.mouse_x = e.pageX;
-					t.mouse_y = e.pageY;
-				};}(this);
-				this.mouseWheelFunction = function(t){return function(e){t.wheel(e);};}(this);
-
-				if(window.addEventListener){
-					document.addEventListener("mouseup", this.mouseUpFunction, false);
-					this.canvas.addEventListener("mousewheel", this.mouseWheelFunction, false);
-					this.canvas.addEventListener('DOMMouseScroll', this.mouseWheelFunction, false);
-				} else {
-					document.attachEvent("mouseup", this.mouseUpFunction);
-					this.canvas.attachEvent("onmousewheel", this.mouseWheelFunction);
-				}
-				canvas.onmousedown = this.mouseDownFunction;
-				canvas.onkeydown = this.keyDownFunction;
-				canvas.onmousemove = this.mouseMoveFunction;
-
-			};
-		
 		};
 
 		PCBV.prototype.destroy = function(){
 
-			var i;
-
-			if(this.mode == "Accelerated"){
-
-				var gl = this.ctx;
-
-				for(i = 0; i < this.vias.length; i++)
-					this.vias[i].cleanupGL(gl);
-				for(i = 0; i < this.layers.length; i++)
-					this.layers[i].cleanupGL(gl);
-				for(i = 0; i < this.elements.length; i++)
-					this.elements[i].cleanupGL(gl);
-				for(i in this.symbols)
-					this.symbols[i].cleanupGL(gl);
-
-				// Restore GL Defaults
-				gl.disable(gl.BLEND);
-				gl.useProgram(null);
-				gl.blendFunc(gl.ONE, gl.ZERO);
-				gl.clearColor(0, 0, 0, 0);
-
-				// Unbind all buffers
-				gl.bindTexture(gl.TEXTURE_2D, null);
-				gl.bindBuffer(gl.ARRAY_BUFFER, null);
-				gl.bindRenderbuffer(gl.RENDERBUFFER, null);
-				gl.bindFramebuffer(gl.FRAMEBUFFER, null);
-
-				// Clear viewport
-				gl.viewport(0, 0, gl.viewportWidth, gl.viewportheight);
-				gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-				// Clear errors
-				while(gl.getError());
-
-			}
+			this.renderer.destroy();
 
 			if(window.addEventListener){
 				document.removeEventListener("mouseup", this.mouseUpFunction, false);
@@ -204,8 +99,13 @@
 			this.canvas.onmousedown = null;
 			this.canvas.onkeydown = null;
 			this.canvas.onmousemove = null;
-
-		}
+			this.canvas.ontouchstart = null;
+			this.canvas.ontouchmove = null;
+			this.canvas.ontouchend = null;
+			this.canvas.ontouchcancel = null;
+			this.canvas.ontouchleave = null;
+
+		};
 
 		// TODO: maybe make this layer named based!
 		PCBV._defaultLayerColors = ['#8B2323', '#3A5FCD', '#104E8B', '#CD3700',
@@ -233,265 +133,199 @@
 			return false;
 		}
 
-		PCBV.prototype.getLayerColors = function(){
-			return this._layerColors;
+		PCBV.prototype._buildLayers = function(){
+
+			var top = [], solder = [], pins = [];
+
+			var i, j;
+			for(i = 0; i < this.elements.length; i++){
+
+				if(!this.elements[i].onsolder()){
+					this.renderer.bottomSilk.parts.push(this.elements[i]);
+				} else {
+					this.renderer.topSilk.parts.push(this.elements[i]);
+				}
+
+				for(j = 0; j < this.elements[i].parts.length; j++){
+					if(this.elements[i].parts[j] instanceof Pin)
+						pins.push(this.elements[i].parts[j]);
+					else if(
+					  this.elements[i].parts[j] instanceof ElementLine ||
+					  this.elements[i].parts[j] instanceof ElementArc ||
+					  this.elements[i].parts[j] instanceof Text
+					 ){
+						if(!this.elements[i].onsolder())
+							this.renderer.bottomSilk.parts.push(this.elements[i].parts[j]);
+						else
+							this.renderer.topSilk.parts.push(this.elements[i].parts[j]);
+					} else if(this.elements[i].onsolder())
+						solder.push(this.elements[i].parts[j]);
+					else
+						top.push(this.elements[i].parts[j]);
+				}
+			}
+
+			for(i = 0; i < this.vias.length; i++)
+				pins.push(this.vias[i]);
+
+			this.renderer.addLayer(new Layer(this, -1, "top_component", top));
+			this.renderer.addLayer(new Layer(this, -2, "solder_component", solder));
+			this.renderer.addLayer(new Layer(this, -3, "pins", pins));
+
+		};
+
+		PCBV.prototype._setupEventHandlers = function(){
+
+			this.clicking = false;
+			
+			this.mouseX = this.canvas.width / 2;
+			this.mouseY = this.canvas.height/ 2;
+	
+			this.mouseUpFunction = function(t){return function(e){if(e.which == 1) t.clicking = false;};}(this);
+			this.mouseDownFunction = function(t){return function(e){if(e.which == 1) t.clicking = true;};}(this)
+			this.keyDownFunction = function(t){return function(e){t._updateKey(e);};}(this);
+			this.mouseMoveFunction = function(t){return function(e){
+				if(t.clicking)
+					t._updateMouseDrag(t.mouseX-e.pageX, t.mouseY-e.pageY);		
+				t.mouseX = e.pageX;
+				t.mouseY = e.pageY;
+			};}(this);
+			this.mouseWheelFunction = function(t){return function(e){t._wheel(e);};}(this);
+			this.onTouchStartFunction = function(t){return function(e){t._touchStart(e);};}(this);
+			this.onTouchMoveFunction = function(t){return function(e){t._touchMove(e);};}(this);
+			this.onTouchEndFunction = function(t){return function(e){t._touchEnd(e);};}(this);
+			this.onTouchCancelFunction = function(t){return function(e){e.preventDefault();};}(this);
+			
+			if(window.addEventListener){
+				document.addEventListener("mouseup", this.mouseUpFunction, false);
+				this.canvas.addEventListener("mousewheel", this.mouseWheelFunction, false);
+				this.canvas.addEventListener('DOMMouseScroll', this.mouseWheelFunction, false);
+			} else {
+				document.attachEvent("mouseup", this.mouseUpFunction);
+				this.canvas.attachEvent("onmousewheel", this.mouseWheelFunction);
+			}
+			this.canvas.onmousedown = this.mouseDownFunction;
+			this.canvas.onkeydown = this.keyDownFunction;
+			this.canvas.onmousemove = this.mouseMoveFunction;
+			this.canvas.ontouchstart = this.onTouchStartFunction;
+			this.canvas.ontouchmove = this.onTouchMoveFunction;
+			this.canvas.ontouchend = this.onTouchEndFunction;
+			this.canvas.ontouchcancel = this.onTouchCancelFunction;
+			this.canvas.ontouchleave = this.onTouchEndFunction;
+
+			this.touches = [];
+
 		}
 
-		PCBV.prototype.resize = function(){
-		
-			this.buffer_layer.width = this.canvas.width;
-			this.buffer_layer.height = this.canvas.height;
-		
-		};
-	
-		PCBV.prototype.parse_data = function(data){
-	
-			var lines, l, splt, new_obj, sub_obj, xmi, xma;
-	
-			lines = data.split('\n');
-	
-			l = 0;
-			while(l < lines.length){
-				line = lines[l];
-	
-				if(line.substr(0,3) == "PCB"){
-	
-					line = line.substr(4, line.length-2);
-					splt = line.split(' ');
-	
-					this.name = splt[0].split('"')[1];
-					this.width = parseInt(splt[1]);
-					this.height = parseInt(splt[2]);
-	
-				} else if(line.substr(0,3) == "Via"){
-	
-					line = line.substr(4, line.length-2);
-					splt = line.split(' ');
-	
-					new_obj = new Via(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), splt[6].split('"')[1], splt[7].split('"')[1]);
-	
-					this.vias.push(new_obj);
-	
-				} else if(line.substr(0, 7) == "Element"){
-	
-					line = line.substr(8,line.length-2);
-					splt = line.match(/[^\s"]+|"([^"]*)"/gi); // TODO: change all space splits with text to this regex
-	
-					new_obj = new Element(this, splt[0].split('"')[1], splt[1].split('"')[1], splt[2].split('"')[1], splt[3].split('"')[1], parseInt(splt[4]), parseInt(splt[5]), parseInt(splt[6]), parseInt(splt[7]), parseInt(splt[8]), parseInt(splt[9]), splt[7].split('"')[10]);
-	
-					while(line[0] != ')'){
-						l++;
-						line = lines[l];
-						line = line.trim();
-	
-						if(line.substr(0, 3) == 'Pad'){
-	
-							line = line.substr(4, line.length-2);
-							splt = line.split(' ');
-	
-							sub_obj = new Pad(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), parseInt(splt[6]), splt[7].split('"')[1], splt[8].split('"')[1], splt[9].split('"')[1]);	
-							sub_obj.parent = new_obj;
-
-							new_obj.parts.push(sub_obj);
-	
-						} else if(line.substr(0, 3) == 'Pin'){
-	
-							line = line.substr(4, line.length-2);
-							splt = line.match(/[^\s"]+|"([^"]*)"/gi);
-	
-							sub_obj = new Pin(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), splt[6].split('"')[1], splt[7].split('"')[1], splt[8].split('"')[1]);
-							sub_obj.parent = new_obj;
-
-							new_obj.parts.push(sub_obj);
-	
-						} else if(line.substr(0, 11) == 'ElementLine'){
-	
-							line = line.substr(13, line.length-2);
-							splt = line.split(' ');
-	
-							sub_obj = new ElementLine(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]));
-							sub_obj.parent = new_obj;
-
-							new_obj.parts.push(sub_obj);
-	
-						} else if(line.substr(0, 10) == 'ElementArc'){
-	
-							line = line.substr(12, line.length-2);
-							splt = line.split(' ');
-	
-							sub_obj = new ElementArc(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), parseInt(splt[6]));
-							sub_obj.parent = new_obj;
-
-							new_obj.parts.push(sub_obj);
-	
-						};
-	
-					}
-	
-					this.elements.push(new_obj);
-	
-				} else if(line.substr(0, 5) == "Layer"){
-	
-					line = line.substr(6,line.length-2);
-					splt = line.split(' ');
-	
-					new_obj = new Layer(this, parseInt(splt[0]), splt[1].split('"')[1]);
-	
-					while(line[0] != ')'){
-						l++;
-						line = lines[l];
-						line = line.trim();
-	
-						if(line.substr(0, 4) == 'Line'){
-	
-							line = line.substr(5, line.length-2);
-							splt = line.split(' ');
-	
-							sub_obj = new Line(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), splt[6].split('"')[1]);
-	
-							new_obj.parts.push(sub_obj);
-	
-						} else if(line.substr(0, 4) == 'Text'){
-	
-							line = line.substr(5, line.length-2);
-							splt = line.match(/[^\s"]+|"([^"]*)"/gi);
-	
-							sub_obj = new Text(this, parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), splt[4].split('"')[1], splt[5].split('"')[1]);
-	
-							new_obj.parts.push(sub_obj);
-	
-						};
-	
-					}
-	
-					this.layers.push(new_obj);
-	
-				} else if(line.substr(0, 6) == "Symbol"){
-	
-					line = line.substr(7, line.length-2);
-	
-					new_obj = new Symbol(line.substr(1,1), parseInt(line.substr(4,line.length-2).replace(']', '')));
-
-					xmi = undefined;
-					xma = undefined;
-	
-					while(line[0] != ')'){
-						l++;
-						line = lines[l];
-						line = line.trim();
-	
-						if(line.substr(0, 10) == 'SymbolLine'){
-	
-							line = line.substr(11, line.length-2);
-							splt = line.split(' ');
-	
-							sub_obj = new Line(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]));
-	
-							if(xmi == undefined) xmi = sub_obj.x1;					
-							else if(xmi > sub_obj.x1) xmi = sub_obj.x1;
-							if(xmi > sub_obj.x2) xmi = sub_obj.x2;
-							if(xma == undefined) xma = sub_obj.x1;
-							else if(xma < sub_obj.x1) xma = sub_obj.x1;
-							if(xma < sub_obj.x2) xma = sub_obj.x2;
-
-							new_obj.lines.push(sub_obj);
-
-						};
-	
-					}
-	
-					if(new_obj.name == ' ') new_obj.width = 1800;
-					else new_obj.width = Math.abs(xma-xmi);
-	
-					this.symbols[new_obj.name] = new_obj;
-	
-				} else if(line.substr(0, 7) == "Polygon"){
-	
-					//
-	
-				}
-	
-				l++;
-	
-			}
-	
-			this.offset = {};	// Board offset to render at
-			this.offset.x = 0;
-			this.offset.y = 0;
-	
-			this.side = Layer.SOLDER;
-	
-			this.scale = 1.0;
-
-			if(this.mode == "Accelerated"){
-
-				var top = [], solder = [], pins = [];
-
-				this.layerManager = new LayerManager(this.layers);
-
-				var i, j;
-				for(i = 0; i < this.elements.length; i++){
-
-					if(!this.elements[i].onsolder()){
-						this.layerManager.bottomSilk.parts.push(this.elements[i]);
-					} else {
-						this.layerManager.topSilk.parts.push(this.elements[i]);
-					}
-
-					for(j = 0; j < this.elements[i].parts.length; j++){
-						if(this.elements[i].parts[j] instanceof Pin)
-							pins.push(this.elements[i].parts[j]);
-						else if(
-						  this.elements[i].parts[j] instanceof ElementLine ||
-						  this.elements[i].parts[j] instanceof ElementArc ||
-						  this.elements[i].parts[j] instanceof Text
-						 ){
-							if(!this.elements[i].onsolder())
-								this.layerManager.bottomSilk.parts.push(this.elements[i].parts[j]);
-							else
-								this.layerManager.topSilk.parts.push(this.elements[i].parts[j]);
-						} else if(this.elements[i].onsolder())
-							solder.push(this.elements[i].parts[j]);
-						else
-							top.push(this.elements[i].parts[j]);
+		PCBV.prototype._touchStart = function(e){
+
+			e.preventDefault();
+			var tch = e.changedTouches;
+
+			for(var i = 0; i < tch.length; i++){
+				this.touches.push(Touch.from_touch(tch[i]));
+			}
+
+			if(this.touches.length == 1){
+
+				this.mouse_down_x = this.touches[0].x;
+				this.mouse_down_y = this.touches[0].y;
+
+				this.touch_clicking = true;
+
+			}
+
+			// If 2 fingers we are zooming in/out
+			else if(this.touches.length == 2){
+
+				this.scale_distance_last = Math.sqrt( Math.pow(this.touches[0].x - this.touches[1].x, 2) + Math.pow(this.touches[0].y - this.touches[1].y, 2) );
+				this.scale_delta = 0;
+
+				this.touch_clicking = false;
+
+			}
+
+		};
+
+		PCBV.prototype._touchMove = function(e){
+
+			e.preventDefault();
+			var tch = e.changedTouches;
+
+			// If 1 finger we are dragging
+			if(this.touches.length == 1){
+
+				var ot = this.touches[0];
+					nt = Touch.from_touch(tch[0]),
+					dx = ot.x - nt.x,
+					dy = ot.y - nt.y;
+
+				this._updateMouseDrag(dx, dy);
+
+			}
+
+			// update the touches
+			for(var i = 0; i < tch.length; i++){
+				for(var j = 0; j < this.touches.length; j++){
+					if(this.touches[j].id == tch[i].identifier){
+						this.touches[j].x = tch[i].pageX;
+						this.touches[j].y = tch[i].pageY;
+						break;
 					}
 				}
-
-				for(i in this.symbols){
-					this.symbols[i].init3DArrays(this.ctx);
+			}
+
+			// If 2 fingers we are zooming in/out
+			if(this.touches.length == 2){
+
+				var touch_distance = Math.sqrt( Math.pow(this.touches[0].x - this.touches[1].x, 2) + Math.pow(this.touches[0].y - this.touches[1].y, 2) );
+
+				var center = {x: 0, y: 0};
+				center.x = (this.touches[0].x + this.touches[1].x)/2;
+				center.y = (this.touches[0].y + this.touches[1].y)/2;
+
+				var off = DOM.offset(this.canvas),
+					px = center.x - off.x,
+					py = center.y - off.y;
+
+				// Set partial scale
+				var change = this.scale_distance_last - touch_distance;
+				var scaled = Math.floor(change/40);
+				if(scaled != this.scale_delta){
+
+					if(scaled > this.scale_delta){
+						this._updateMouseScroll(px, py, -1);
+					} else {
+						this._updateMouseScroll(px, py, 1);
+					}
+					this.scale_delta = scaled;
 				}
-
-				for(i = 0; i < this.vias.length; i++){
-					pins.push(this.vias[i]);
+			}
+
+		};
+		PCBV.prototype._touchEnd = function(e){
+
+			e.preventDefault();
+
+			var tch = e.changedTouches;
+
+			// remove the touch
+			for(var i = 0; i < tch.length; i++){
+				for(var j = 0; j < this.touches.length; j++){
+					if(this.touches[j].id == tch[i].identifier){
+						this.touches.splice(j, 1);
+							break;
+					}
 				}
-
-				this.layerManager.top = new Layer(this, -1, "top_component", top);
-				this.layerManager.solder = new Layer(this, -2, "solder_component", solder);
-				this.layerManager.pins = new Layer(this, -3, "pins", pins);
-				this.layerManager.layers.push(this.layerManager.top);
-				this.layerManager.layers.push(this.layerManager.solder);
-				this.layerManager.layers.push(this.layerManager.pins);
-
-				this.layerManager.setupFramebuffers(this.ctx, this.canvas.width, this.canvas.height);
-				this.layerManager.init3DArrays(this.ctx);
-				this.layerManager.setupGL(this.ctx, this.width, this.height);
-
-			}
+			}
+
+		};
+
+		PCBV.prototype._wheel = function(e) {
 			
-		};
-		
-		PCBV.prototype.wheel = function(e) {
-	
 			var	ev = window.event || e,
 				d,
-				elem = this.canvas,
-				doc = elem && elem.ownerDocument,
-				docElem = doc.documentElement,
-				box = elem.getBoundingClientRect(),
-				off = {
-					top: box.top  + (window.pageYOffset || docElem.scrollTop)  - (docElem.clientTop  || 0),
-					left: box.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
-				};
+				off = DOM.offset(this.canvas);
 	
 			if(ev.stopPropagation) ev.stopPropagation();
 			if(ev.preventDefault) ev.preventDefault();
@@ -499,12 +333,12 @@
 	
 			d = Math.max(-1, Math.min(1, (ev.wheelDelta || -ev.detail)));
 	
-			this.update_mouse_scroll(this.mouse_x-off.left, this.mouse_y-off.top, d);
+			this._updateMouseScroll(this.mouseX - off.x, this.mouseY - off.y, d);
 	
 		};
 	
 		// Key event handler
-		PCBV.prototype.update_key = function(e){
+		PCBV.prototype._updateKey = function(e){
 	
 			var which = e.which, prevent = true;
 	
@@ -553,14 +387,14 @@
 		};
 	
 		// Drag event handler
-		PCBV.prototype.update_mouse_drag = function(x, y){
+		PCBV.prototype._updateMouseDrag = function(x, y){
 
 			var dx, dy, min;
 
-				min = Math.min(this.canvas.width/this.width, this.canvas.height/this.height)*this.scale;
-
-				dy = y / min;
-	            dx = x / min;
+			min = Math.min(this.canvas.width/this.width, this.canvas.height/this.height)*this.scale;
+
+			dy = y / min;
+            dx = x / min;
 
 			if(this.side) this.offset.y -= dy;
 			else this.offset.y += dy;
@@ -571,7 +405,7 @@
 		};
 	
 		// Scroll event handler
-		PCBV.prototype.update_mouse_scroll = function(x, y, s){
+		PCBV.prototype._updateMouseScroll = function(x, y, s){
 
 			if(s > 0){ // Zoom in
 				if(this.side) this.offset.y += (((this.canvas.height-(this.canvas.height/1.1))/2)*((this.canvas.height-y)/this.canvas.height*2))/(Math.min(this.canvas.width/this.width, this.canvas.height/this.height)*this.scale);
@@ -587,100 +421,249 @@
 			this.render();
 		};
 
-		PCBV.prototype.render_layers = function(){
-	
-			this.buffer_ctx.clearRect(0, 0, this.buffer_layer.width, this.buffer_layer.height);
-		
-			var bot_silk = null, top_silk = null,
-				i;
-	
-			for(i = 0; i < this.layers.length; i++){
-				if(this.layers[i].name == 'silk'){
-					if(top_silk) bot_silk = this.layers[i];
-					else top_silk = this.layers[i];
-				};
-			}
-		
-			if(this.side) bot_silk.render(this.buffer_ctx, '#FFFFFF');
-			else top_silk.render(this.buffer_ctx, '#FFFFFF');
-		
-			if(this.side){
-				for(i = 0; i < this.layers.length; i++)
-					if(this.layers[i].name != 'silk') this.layers[i].render(this.buffer_ctx);
-			} else {
-				for(i = this.layers.length-1; i >= 0; i--)
-					if(this.layers[i].name != 'silk') this.layers[i].render(this.buffer_ctx);
-			}
-		
-			if(this.side) top_silk.render(this.buffer_ctx);
-			else bot_silk.render(this.buffer_ctx);
-		
-			this.ctx.drawImage(this.buffer_layer, 0, 0);
-		
-		};
-
-		PCBV.prototype._do_render = function(){
+		PCBV.prototype._doRender = function(){
 
 			// Calculate how much we need to scale based on size of the
 			// pcb vs canvas size and how zoomed in we are
 			scalef = Math.min(this.canvas.width/this.width, this.canvas.height/this.height)*this.scale;
 
-			if(this.mode == "Accelerated"){
-
-				this.layerManager.renderGL(this.ctx, this.shaderProgram, this.texShaderProgram, this.side, this.offset.x, this.offset.y, scalef);
-
-			} else {
-
-				// Fill canvas background Dark Grey
-				this.buffer_ctx.fillStyle = '#CCCCCC';
-				this.buffer_ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
-			
-				// Save default tranform
-				this.buffer_ctx.save();
-			
-				// Flip canvas if solder side
-				if(this.side){
-					this.buffer_ctx.scale(1, -1);
-					this.buffer_ctx.translate(0, -this.canvas.height);
-				}
-			
-				// Scale and shift
-				this.buffer_ctx.scale(scalef, scalef);
-				this.buffer_ctx.translate(-this.offset.x, -this.offset.y);	
-
-				// Fill board space Grey
-				this.buffer_ctx.fillStyle = '#E5E5E5';
-				this.buffer_ctx.fillRect(0, 0, this.width, this.height);
-
-				this.ctx.globalAlpha = 1.0;
-			
-				this.ctx.drawImage(this.buffer_layer, 0, 0);
-			
-				this.ctx.globalAlpha = 0.5;
-			
-				this.buffer_ctx.clearRect(0, 0, this.buffer_layer.width, this.buffer_layer.height);
-				for(i = 0; i < this.elements.length; i++) if(!this.elements[i].onsolder() != !this.side) this.elements[i].render(this.buffer_ctx, '#FFFFFF', !this.side);
-				this.ctx.drawImage(this.buffer_layer, 0, 0);
-			
-				this.render_layers();
-			
-				this.buffer_ctx.clearRect(0, 0, this.buffer_layer.width, this.buffer_layer.height);
-				for(i = 0; i < this.elements.length; i++) if(this.elements[i].onsolder() == this.side) this.elements[i].render(this.buffer_ctx, '#000000', this.side);
-				for(i = 0; i < this.elements.length; i++) if(!this.elements[i].onsolder() != !this.side) this.elements[i].render(this.buffer_ctx, '#000000', this.side, true);
-				this.ctx.drawImage(this.buffer_layer, 0, 0);
-			
-				this.buffer_ctx.clearRect(0, 0, this.buffer_layer.width, this.buffer_layer.height);
-				for(i = 0; i < this.vias.length; i++) this.vias[i].render(this.buffer_ctx);
-				this.ctx.drawImage(this.buffer_layer, 0, 0);
-			
-				// Restore default tranform
-				this.buffer_ctx.restore();
-
-			}
+			if(this.resized){
+				this.renderer.resize();
+				this.resized = false;
+			}
+
+			this.renderer.render(this.side, this.offset.x, this.offset.y, scalef);
 
 			this.end_time = (new Date()).getTime();
 
-		}
+		};
+
+		PCBV.prototype.getLayerColors = function(){
+			return this._layerColors;
+		};
+
+		PCBV.prototype.resize = function(){
+			this.resized = true;
+		};
+
+		PCBV.prototype.setup = function(){
+
+			this.offset = {};	// Board offset to render at
+			this.offset.x = 0;
+			this.offset.y = 0;
+	
+			this.side = Layer.SOLDER;
+	
+			this.scale = 1.0;
+
+			if(this.mode == "Accelerated")
+				this.renderer = new GLRenderer(this.ctx, this.canvas, this.symbols, this.layers, this.width, this.height);
+			else
+				this.renderer = new TwoDRenderer(this.ctx, this.canvas, this.symbols, this.layers, this.width, this.height);
+
+			this._buildLayers();
+			this.renderer.setup();
+
+		};
+
+		PCBV.prototype.parse = function(data){
+	
+			var lines, l, splt, new_obj, sub_obj, xmi, xma;
+	
+			lines = data.split('\n');
+	
+			l = 0;
+			while(l < lines.length){
+				line = lines[l];
+	
+				if(line.substr(0,3) == "PCB"){
+	
+					line = line.substr(4, line.length-2);
+					splt = line.split(' ');
+	
+					this.name = splt[0].split('"')[1];
+					this.width = parseInt(splt[1]);
+					this.height = parseInt(splt[2]);
+	
+				} else if(line.substr(0,3) == "Via"){
+	
+					line = line.substr(4, line.length-2);
+					splt = line.split(' ');
+	
+					new_obj = new Via(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), splt[6].split('"')[1], splt[7].split('"')[1]);
+	
+					this.vias.push(new_obj);
+	
+				} else if(line.substr(0, 7) == "Element"){
+	
+					line = line.substr(8,line.length-2);
+					splt = line.match(/[^\s"]+|"([^"]*)"/gi); // TODO: change all space splits with text to this regex
+	
+					new_obj = new Element(this, splt[0].split('"')[1], splt[1].split('"')[1], splt[2].split('"')[1], splt[3].split('"')[1], parseInt(splt[4]), parseInt(splt[5]), parseInt(splt[6]), parseInt(splt[7]), parseInt(splt[8]), parseInt(splt[9]), splt[7].split('"')[10]);
+	
+					while(line[0] != ')'){
+						l++;
+						line = lines[l];
+						line = line.trim();
+	
+						if(line.substr(0, 3) == 'Pad'){
+	
+							line = line.substr(4, line.length-2);
+							splt = line.split(' ');
+	
+							sub_obj = new Pad(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), parseInt(splt[6]), splt[7].split('"')[1], splt[8].split('"')[1], splt[9].split('"')[1]);	
+							sub_obj.parent = new_obj;
+
+							new_obj.parts.push(sub_obj);
+	
+						} else if(line.substr(0, 3) == 'Pin'){
+	
+							line = line.substr(4, line.length-2);
+							splt = line.match(/[^\s"]+|"([^"]*)"/gi);
+	
+							sub_obj = new Pin(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), splt[6].split('"')[1], splt[7].split('"')[1], splt[8].split('"')[1]);
+							sub_obj.parent = new_obj;
+
+							new_obj.parts.push(sub_obj);
+	
+						} else if(line.substr(0, 11) == 'ElementLine'){
+	
+							line = line.substr(13, line.length-2);
+							splt = line.split(' ');
+	
+							sub_obj = new ElementLine(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]));
+							sub_obj.parent = new_obj;
+
+							new_obj.parts.push(sub_obj);
+	
+						} else if(line.substr(0, 10) == 'ElementArc'){
+	
+							line = line.substr(12, line.length-2);
+							splt = line.split(' ');
+	
+							sub_obj = new ElementArc(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), parseInt(splt[6]));
+							sub_obj.parent = new_obj;
+
+							new_obj.parts.push(sub_obj);
+	
+						};
+	
+					}
+	
+					this.elements.push(new_obj);
+	
+				} else if(line.substr(0, 5) == "Layer"){
+	
+					line = line.substr(6,line.length-2);
+					splt = line.split(' ');
+	
+					new_obj = new Layer(this, parseInt(splt[0]), splt[1].split('"')[1]);
+	
+					while(line[0] != ')'){
+						l++;
+						line = lines[l];
+						line = line.trim();
+	
+						if(line.substr(0, 4) == 'Line'){
+	
+							line = line.substr(5, line.length-2);
+							splt = line.split(' ');
+	
+							sub_obj = new Line(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]), splt[6].split('"')[1]);
+	
+							new_obj.parts.push(sub_obj);
+	
+						} else if(line.substr(0, 4) == 'Text'){
+	
+							line = line.substr(5, line.length-2);
+							splt = line.match(/[^\s"]+|"([^"]*)"/gi);
+	
+							sub_obj = new Text(this, parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), splt[4].split('"')[1], splt[5].split('"')[1]);
+	
+							new_obj.parts.push(sub_obj);
+	
+						} else if(line.substr(0, 7) == "Polygon"){
+
+							var flags = line.substr(9,line.length-11), points = [];
+
+							line = '';
+							while(line.indexOf(')') == -1){
+
+								l++;
+								line = lines[l];
+
+								var bracket_idx = line.indexOf('[');
+								while(bracket_idx != -1){
+
+									var space_idx = line.indexOf(' ', bracket_idx);
+
+									var newPoint = {
+										x: parseFloat(line.substring(bracket_idx + 1, space_idx)),
+										y: parseFloat(line.substring(space_idx + 1, line.indexOf(']', space_idx))),
+									};
+									points.push(newPoint);
+									bracket_idx++;
+									bracket_idx = line.indexOf('[', bracket_idx);
+
+								}
+
+							}
+
+							sub_obj = new Polygon(flags, points);
+							new_obj.parts.push(sub_obj);
+
+						}
+
+					}
+	
+					this.layers.push(new_obj);
+	
+				} else if(line.substr(0, 6) == "Symbol"){
+	
+					line = line.substr(7, line.length-2);
+	
+					new_obj = new Symbol(line.substr(1,1), parseInt(line.substr(4,line.length-2).replace(']', '')));
+
+					xmi = undefined;
+					xma = undefined;
+	
+					while(line[0] != ')'){
+						l++;
+						line = lines[l];
+						line = line.trim();
+	
+						if(line.substr(0, 10) == 'SymbolLine'){
+	
+							line = line.substr(11, line.length-2);
+							splt = line.split(' ');
+	
+							sub_obj = new Line(parseInt(splt[0]), parseInt(splt[1]), parseInt(splt[2]), parseInt(splt[3]), parseInt(splt[4]), parseInt(splt[5]));
+	
+							if(xmi == undefined) xmi = sub_obj.x1;					
+							else if(xmi > sub_obj.x1) xmi = sub_obj.x1;
+							if(xmi > sub_obj.x2) xmi = sub_obj.x2;
+							if(xma == undefined) xma = sub_obj.x1;
+							else if(xma < sub_obj.x1) xma = sub_obj.x1;
+							if(xma < sub_obj.x2) xma = sub_obj.x2;
+
+							new_obj.lines.push(sub_obj);
+
+						};
+	
+					}
+	
+					if(new_obj.name == ' ') new_obj.width = 1800;
+					else new_obj.width = Math.abs(xma-xmi);
+	
+					this.symbols[new_obj.name] = new_obj;
+	
+				} else {}
+	
+				l++;
+	
+			}
+
+		};
 
 		PCBV.prototype.render = function(force, timeout){
 		
@@ -696,7 +679,7 @@
 			}
 
 			// Using requestAnimFrame prevents Screen Tearing
-			window.requestAnimFrame(function(){t._do_render();});
+			window.requestAnimFrame(function(){t._doRender();});
 
 		};
 

--- 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,7 +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) this._createCache();
 
 		if (color == '#FFFFFF')
 			ctx.fillStyle = color;
@@ -24,21 +57,40 @@
 			ctx.fillStyle = '#4D4D4D'; // TODO: global color
 
 		ctx.fillRect(
-			this.x1 - (this.thick / 2),
-			this.y1 - (this.thick / 2),
-			this.x2 - this.x1 + (this.thick),
-			this.y2 - this.y1 + (this.thick));
+			this._cache.rx1,
+			this._cache.ry1,
+			this._cache.rx2,
+			this._cache.ry2);
+
+	};
+
+	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){
+
+		gl.bindBuffer(gl.ARRAY_BUFFER, this.clearBuffer);
+		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.clearBuffer.itemSize, gl.FLOAT, false, 0, 0);
+		gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.clearBuffer.numItems);
+
+	};
 
 	Pad.prototype.cleanupGL = function(gl){
 
@@ -51,17 +103,17 @@
 
 	}
 
-	Pad.prototype.setup3DArrayBuffer = function(gl, x, y){
+	Pad.prototype.generatePadBuffer = function(gl, thick){
 
-		var vBuffer, x1, x2, y1, y2;
+		var vBuffer, vertices, x1, x2, y1, y2;
 
 		vBuffer = gl.createBuffer();
 		gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
 
-		x1 = this.parent.mx + this.x1 - (this.thick / 2);
-		y1 = this.parent.my + this.y1 - (this.thick / 2);
-		x2 = x1 + this.x2 - this.x1 + this.thick;
-		y2 = y1 + this.y2 - this.y1 + this.thick;
+		x1 = this.parent.mx + this.x1 - (thick / 2);
+		y1 = this.parent.my + this.y1 - (thick / 2);
+		x2 = x1 + this.x2 - this.x1 + thick;
+		y2 = y1 + this.y2 - this.y1 + thick;
 
 		vertices = [
 		 x2, y2,  0.0,
@@ -75,7 +127,14 @@
 		vBuffer.itemSize = 3;
 		vBuffer.numItems = 4;
 
-		this.vertexBuffer = vBuffer;
+		return vBuffer;
+
+	}
+
+	Pad.prototype.setup3DArrayBuffer = function(gl, x, y){
+
+		this.vertexBuffer = this.generatePadBuffer(gl, this.thick);
+		this.clearBuffer = this.generatePadBuffer(gl, this.thick + this.clearance);
 
 	};
 

--- a/src/js/circuit/PCB/Pin.js
+++ b/src/js/circuit/PCB/Pin.js
@@ -1,102 +1,191 @@
-define(function() {
+define(
+	[
+	 	"./Thermal",
+	 	"./parseFlags"
+	],
+	function(
+		Thermal,
+		parseFlags
+	){
+	
+		// Pin [x y thickness clearance mask drillholedia name number flags]
+		var Pin = function(x, y, thick, clearance, mask, drill, name, num, flags) {
+	
+			this.x = x;
+			this.y = y;
+			this.thick = thick;
+			this.clearance = clearance;
+			this.mask = mask;
+			this.drill = drill;
+			this.name = name;
+			this.num = num;
+			this.flags = parseFlags(Pin._defaultFlags, flags);
 
-	// Pin [x y thickness clearance mask drillholedia name number flags]
-	var Pin = function(x, y, thick, clear, mask, drill, name, num, flags) {
+		};
+	
+		Pin._defaultFlags = {
+			square: false
+		};
+	
+		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._createCache();
+	
+			if(color == '#FFFFFF')
+				return;
+	
+			ctx.beginPath();
+			if(this.flags.square)
+				ctx.rect(this._cache.rx, this._cache.ry, this.thick, this.thick);
+			else
+				ctx.arc(this._cache.x, this._cache.y, this.thick / 2, 0, Math.PI * 2, true);
+	
+			ctx.closePath();
+			ctx.fillStyle = '#4D4D4D'; // TODO: global color
+			ctx.fill();
+	
+			ctx.beginPath();
+			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();
+	
+		};
 
-		this.x = x;
-		this.y = y;
-		this.thick = thick;
-		this.clear = clear;
-		this.mask = mask;
-		this.drill = drill;
-		this.name = name;
-		this.num = num;
-		this.flags = flags;
+		Pin.prototype.clear = function(ctx, layerNumber){
+	
+			if(!this._cache) this._createCache();
 
-	};
+			var thrm, i;
 
-	Pin.prototype.render = function(ctx, color) {
+			thrm = this.flags.thermal;
+			if(thrm){
+				thrm = Thermal.findThermal(thrm, layerNumber);
+				if(thrm)
+					thrm.clear(ctx, this.pointBuffer, this.clearance, this.thick, this.drill);
+			}
 
-		if (color == '#FFFFFF')
-			return;
+			if(!thrm){
+				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();
+			}
 
-		var i, splt = this.flags.split(','), square = false;
+		};
 
-		for (i = 0; i < splt.length; i++)
-			if (splt[i] == 'square')
-				square = true;
+		Pin.prototype.clearInner = function(ctx){
 
-		ctx.beginPath();
-		if (square)
-			ctx.rect(this.x - this.thick / 2, this.y - this.thick / 2,
-					this.thick, this.thick);
-		else
-			ctx.arc(this.x, this.y, this.thick / 2, 0, Math.PI * 2, true);
+			if(!this._cache) this._createCache();
 
-		ctx.closePath();
-		ctx.fillStyle = '#4D4D4D'; // TODO: global color
-		ctx.fill();
+			ctx.beginPath();
+			ctx.arc(this._cache.x, this._cache.y, this.drill / 2.0, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fill();
 
-		ctx.beginPath();
-		ctx.arc(this.x, this.y, this.drill / 2, 0, Math.PI * 2, true);
-		ctx.closePath();
-		ctx.fillStyle = '#E5E5E5'; // TODO: set colors to global option
-		ctx.fill();
+		};
+	
+		Pin.prototype.renderGL = function(gl, shaderProgram){
+			
+			gl.uniform1f(shaderProgram.roundPointsUniform, !this.flags.square);
+	
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+	
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+	
+			gl.uniform4f(shaderProgram.vColorUniform, 0.35, 0.35, 0.35, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.thick * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+			gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.drill * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+	
+		}
+	
+		Pin.prototype.clearGL = function(gl, shaderProgram, layerNumber){
+	
+			if(!this._cache) this._createCache();
 
-	};
+			var thrm = this.flags.thermal;
+			if(thrm){
+				thrm = Thermal.findThermal(thrm, layerNumber);
+				if(thrm)
+					thrm.clearGL(gl, shaderProgram, this._cache.x, this._cache.y, this.pointBuffer, this.clearance, this.thick, this.drill);
+			}
 
-	Pin.prototype.renderGL = function(gl, shaderProgram){
+			if(!thrm){
+				gl.uniform1f(shaderProgram.roundPointsUniform, !this.flags.square);
+		
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+				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.clearance) * gl.scaleFactor);
+				gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+		
+				gl.uniform1f(shaderProgram.roundPointsUniform, false);
+			}
+	
+		};
+	
+		Pin.prototype.cleanupGL = function(gl){
+	
+			if(this.pointBuffer){
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+				gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
+				gl.deleteBuffer(this.pointBuffer);
+				this.pointBuffer = null;
+			}
+	
+		}
 
-		var splt = this.flags.split(','), square = true;
+		Pin.prototype.clearInnerGL = function(gl, shaderProgram){
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
 
-		for (i = 0; i < splt.length; i++)
-			if (splt[i] == 'square')
-				square = false;
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
-		
-		gl.uniform1f(shaderProgram.roundPointsUniform, square);
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
 
-		gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.id * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
 
-		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+		};
 
-		gl.uniform4f(shaderProgram.vColorUniform, 0.35, 0.35, 0.35, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.thick * gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, true);
-		gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.drill * gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
-
-		gl.uniform1f(shaderProgram.roundPointsUniform, false);
+		Pin.prototype.setup3DArrayBuffer = function(gl, x, y){
+	
+			var vBuffer;
+			vBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x + this.parent.mx,this.y + this.parent.my,0.0]), gl.STATIC_DRAW);
+			vBuffer.itemSize = 3;
+			vBuffer.numItems = 1;
+			this.pointBuffer = vBuffer;
+	
+		}
+	
+		return Pin;
 
 	}
-
-	Pin.prototype.cleanupGL = function(gl){
-
-		if(this.pointBuffer){
-			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-			gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
-			gl.deleteBuffer(this.pointBuffer);
-			this.pointBuffer = null;
-		}
-
-	}
-
-	Pin.prototype.setup3DArrayBuffer = function(gl, x, y){
-
-		var vBuffer;
-		vBuffer = gl.createBuffer();
-		gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
-		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x + this.parent.mx,this.y + this.parent.my,0.0]), gl.STATIC_DRAW);
-		vBuffer.itemSize = 3;
-		vBuffer.numItems = 1;
-		this.pointBuffer = vBuffer;
-
-	}
-
-	return Pin;
-
-});
+);

--- /dev/null
+++ b/src/js/circuit/PCB/Polygon.js
@@ -1,1 +1,148 @@
+define(
+	[],
+	function(){
 
+		var Polygon = function(flags, points){
+
+			this.flags = {
+				clearpoly: false
+			};
+			this.points = points;
+
+			var split, i;
+
+			split = flags.split(',');
+			for(i = 0; i < split.length; i++)
+				this.flags[split[i]] = true;
+
+			// Decompose into triangles
+			// turn into doubly linked list
+			var previous, head, next;
+			head = previous = {
+					previous: null,
+					next: null,
+					self: this.points[0]
+				}
+			for(i = 1; i < this.points.length; i++){
+				next = {
+					previous: previous,
+					next: null,
+					self: this.points[i]
+				}
+				previous.next = next;
+				previous = next;
+			}
+			previous.next = head;
+			head.previous = previous;
+
+			// look at sets of 3 nodes
+			var pointCount = this.points.length, currentNode = head, triangles = [];
+			while(pointCount > 3){
+
+				previous = currentNode.previous;
+				next = currentNode.next;
+
+				// if they are convex cut out current node and make a triangle
+				var dx1, dy1, dx2, dy2;
+
+				dx1 = currentNode.self.x - previous.self.x;
+				dy1 = currentNode.self.y - previous.self.y;
+				dx2 = next.self.x - currentNode.self.x;
+				dy2 = next.self.y - currentNode.self.y;
+
+				var ang = Math.atan2(dy2, dx2) - Math.atan2(dy1, dx1);
+
+				if(ang < 0){
+
+					triangles.push(
+						[
+						 	[previous.self.x, previous.self.y],
+						 	[currentNode.self.x, currentNode.self.y],
+						 	[next.self.x, next.self.y]
+						]
+					);
+
+					next.previous = previous;
+					previous.next = next;
+					currentNode = next;
+
+					pointCount--;
+
+				} else {
+					currentNode = currentNode.next;
+				}
+
+			}
+
+			triangles.push(
+					[
+					 	[currentNode.previous.self.x, currentNode.previous.self.y],
+					 	[currentNode.self.x, currentNode.self.y],
+					 	[currentNode.next.self.x, currentNode.next.self.y]
+					]
+				);
+
+			this.triangles = triangles;
+
+		};
+
+		Polygon.prototype.isClear = function(){
+			return this.flags.clearpoly;
+		};
+
+		Polygon.prototype.render = function(ctx, color){
+
+			ctx.beginPath();
+			ctx.moveTo(this.points[0].x, this.points[0].y);
+			for(var i = 1; i < this.points.length; i++)
+				ctx.lineTo(this.points[i].x, this.points[i].y);
+			ctx.closePath();
+			ctx.fillStyle = color;
+			ctx.fill();
+
+		};
+
+		Polygon.prototype.renderGL = function(gl, shaderProgram){
+
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
+			gl.drawArrays(gl.TRIANGLES, 0, this.vertexBuffer.numItems);
+
+		};
+
+		Polygon.prototype.cleanupGL = function(gl){
+
+			//
+
+		};
+
+		Polygon.prototype.setup3DArrayBuffer = function(gl, x, y){
+
+			var vBuffer, vertices = [], i;
+
+			var vBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
+
+			for(i = 0; i < this.triangles.length; i++){
+				vertices.push(this.triangles[i][0][0]);
+				vertices.push(this.triangles[i][0][1]);
+				vertices.push(0.0);
+				vertices.push(this.triangles[i][1][0]);
+				vertices.push(this.triangles[i][1][1]);
+				vertices.push(0.0);
+				vertices.push(this.triangles[i][2][0]);
+				vertices.push(this.triangles[i][2][1]);
+				vertices.push(0.0);
+			}
+
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
+			vBuffer.itemSize = 3;
+			vBuffer.numItems = this.triangles.length * 3;
+			this.vertexBuffer = vBuffer;
+
+		};
+
+		return Polygon;
+
+	}
+);

--- /dev/null
+++ b/src/js/circuit/PCB/Renderers/GLRenderer.js
@@ -1,1 +1,324 @@
-
+define(
+	[
+	 	"./Renderer",
+	 	"../Layer",
+	 	"Graphics/glMatrix",
+	 	"Graphics/GLHelper",
+	 	"Util/Class",
+	 	"text!shaders/2D.fs",
+	 	"text!shaders/2D.vs",
+	 	"text!shaders/Texture.fs",
+	 	"text!shaders/Texture.vs"
+	],
+	function(
+		Renderer,
+		Layer,
+		glMatrix,
+		GLHelper,
+		Class,
+		FragmentShader2Dtxt,
+		VertexShader2Dtxt,
+		FragmentShaderTextxt,
+		VertexShaderTextxt
+	){
+
+		var GLRenderer = function(ctx, canvas, symbols, layers, boardWidth, boardHeight){
+
+			Renderer.call(this, ctx, canvas, symbols, layers, boardWidth, boardHeight);
+
+		}
+
+		Class.extend(Renderer, GLRenderer);
+
+		GLRenderer.prototype._drawLayer = function(layer){
+			if(layer && !layer.isEmpty()){
+				this.ctx.bindTexture(this.ctx.TEXTURE_2D, layer.texture);
+				this.ctx.drawElements(this.ctx.TRIANGLES, this.layerVertexIndexBuffer.numItems, this.ctx.UNSIGNED_SHORT, 0);
+			}
+		};
+
+		GLRenderer.prototype.destroy = function(){
+
+			var gl = this.ctx;
+
+			for(i = 0; i < this.layers.length; i++)
+				this.layers[i].cleanupGL(gl);
+			for(i in this.symbols)
+				this.symbols[i].cleanupGL(this.ctx);
+
+			// Restore GL Defaults
+			gl.disable(gl.BLEND);
+			gl.useProgram(null);
+			gl.blendFunc(gl.ONE, gl.ZERO);
+			gl.clearColor(0, 0, 0, 0);
+
+			// Unbind all buffers
+			gl.bindTexture(gl.TEXTURE_2D, null);
+			gl.bindBuffer(gl.ARRAY_BUFFER, null);
+			gl.bindRenderbuffer(gl.RENDERBUFFER, null);
+			gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+			// Clear viewport
+			gl.viewport(0, 0, gl.viewportWidth, gl.viewportheight);
+			gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+			// Clear errors
+			while(gl.getError());
+
+		};
+
+		GLRenderer.prototype.setup = function(){
+
+			var i, gl = this.ctx;
+
+			// 2D Shader
+			this.shaderProgram = GLHelper.createProgram(gl, 
+					GLHelper.createShader(gl, gl.VERTEX_SHADER, VertexShader2Dtxt),
+					GLHelper.createShader(gl, gl.FRAGMENT_SHADER, FragmentShader2Dtxt));
+
+			this.shaderProgram.vertexPositionAttribute = gl.getAttribLocation(this.shaderProgram, "aVertexPosition");
+	        gl.enableVertexAttribArray(this.shaderProgram.vertexPositionAttribute);
+
+	        this.shaderProgram.pMatrixUniform = gl.getUniformLocation(this.shaderProgram, "uPMatrix");
+	        this.shaderProgram.mvMatrixUniform = gl.getUniformLocation(this.shaderProgram, "uMVMatrix");
+	        this.shaderProgram.vColorUniform = gl.getUniformLocation(this.shaderProgram, "vColor");
+
+	        this.shaderProgram.pointsizeUniform = gl.getUniformLocation(this.shaderProgram, "pointsize");
+	        this.shaderProgram.innerRadiusUniform = gl.getUniformLocation(this.shaderProgram, "innerRadius");
+	        this.shaderProgram.roundPointsUniform = gl.getUniformLocation(this.shaderProgram, "roundPoints");
+	        this.shaderProgram.startAngleUniform = gl.getUniformLocation(this.shaderProgram, "startAngle");
+	        this.shaderProgram.sweepUniform = gl.getUniformLocation(this.shaderProgram, "sweep");
+	        this.shaderProgram.arcEnabledUniform = gl.getUniformLocation(this.shaderProgram, "arcEnabled");
+	        this.shaderProgram.invertedUniform = gl.getUniformLocation(this.shaderProgram, "inverted");
+	        this.shaderProgram.shaveInsideUniform = gl.getUniformLocation(this.shaderProgram, "shaveInside");
+	        this.shaderProgram.shaveFFUniform = gl.getUniformLocation(this.shaderProgram, "shaveFF");
+
+	        // Texture Shader
+			this.texShaderProgram = GLHelper.createProgram(gl, 
+					GLHelper.createShader(gl, gl.VERTEX_SHADER, VertexShaderTextxt),
+					GLHelper.createShader(gl, gl.FRAGMENT_SHADER, FragmentShaderTextxt));
+
+	        this.texShaderProgram.vertexPositionAttribute = gl.getAttribLocation(this.texShaderProgram, "aVertexPosition");
+	        gl.enableVertexAttribArray(this.texShaderProgram.vertexPositionAttribute);
+
+	        this.texShaderProgram.textureCoordAttribute = gl.getAttribLocation(this.texShaderProgram, "aTextureCoord");
+	        gl.enableVertexAttribArray(this.texShaderProgram.textureCoordAttribute);
+
+	        this.texShaderProgram.pMatrixUniform = gl.getUniformLocation(this.texShaderProgram, "uPMatrix");
+	        this.texShaderProgram.mvMatrixUniform = gl.getUniformLocation(this.texShaderProgram, "uMVMatrix");
+	        this.texShaderProgram.samplerUniform = gl.getUniformLocation(this.texShaderProgram, "uSampler");
+
+	        // Board Polygon
+			this.boardVertexBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.boardVertexBuffer);
+			vertices = [
+			 this.boardWidth, this.boardHeight,  -1.0,
+			  -1.0, this.boardHeight,  -1.0,
+			  this.boardWidth,   -1.0,  -1.0,
+			  -1.0,   -1.0,  -1.0
+			];
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
+			this.boardVertexBuffer.itemSize = 3;
+			this.boardVertexBuffer.numItems = 4;
+
+			// Layer Polygon
+			this.layerVertexPositionBuffer = gl.createBuffer();
+		    gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexPositionBuffer);
+		    vertices = [
+		     -1.0, -1.0,  1.0,
+		      1.0, -1.0,  1.0,
+		      1.0,  1.0,  1.0,
+		     -1.0,  1.0,  1.0,
+		    ];
+		    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
+		    this.layerVertexPositionBuffer.itemSize = 3;
+		    this.layerVertexPositionBuffer.numItems = 4;
+
+		    // Layer Texture Coordinates
+		    this.layerVertexTextureCoordBuffer = gl.createBuffer();
+		    gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexTextureCoordBuffer);
+		    var textureCoords = [
+		      0.0, 0.0,
+		      1.0, 0.0,
+		      1.0, 1.0,
+		      0.0, 1.0,
+		    ];
+		    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
+		    this.layerVertexTextureCoordBuffer.itemSize = 2;
+		    this.layerVertexTextureCoordBuffer.numItems = 4;
+
+		    // Layer Vertex Indice Buffer
+		    this.layerVertexIndexBuffer = gl.createBuffer();
+		    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.layerVertexIndexBuffer);
+		    var cubeVertexIndices = [
+		        0, 1, 2,      0, 2, 3
+		    ];
+		    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
+		    this.layerVertexIndexBuffer.itemSize = 1;
+		    this.layerVertexIndexBuffer.numItems = 6;
+
+	        // Viewport setup
+			gl.viewportWidth = this.canvas.width;
+			gl.viewportHeight = this.canvas.height;
+
+			// GL Setup
+	        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+
+		    // Set-Up Frame Buffers
+			for(i = 0; i < this.layers.length; i++)
+				this.layers[i].setupFramebuffer(gl);
+
+			// Set-Up 3D Buffer Arrays
+			for(i = 0; i < this.layers.length; i++)
+				this.layers[i].init3DArrays(gl);
+			for(i in this.symbols)
+				this.symbols[i].init3DArrays(this.ctx);
+
+		};
+
+		GLRenderer.prototype.resize = function(){
+
+			this.ctx.viewportWidth = this.canvas.width;
+			this.ctx.viewportHeight = this.canvas.height;
+
+			for(var i = 0; i < this.layers.length; i++){
+				this.layers[i].resizeFrameBuffer(this.ctx);
+			}
+
+		}
+
+		GLRenderer.prototype.render = function(side, offsetX, offsetY, scaleFactor){
+			
+			var oMatrix, mvMatrix, i, r, g, b, l, color, gl = this.ctx;
+
+			oMatrix = glMatrix.mat4.create();
+			mvMatrix = glMatrix.mat4.create();
+
+			gl.scaleFactor = scaleFactor;
+			gl.oMatrix = oMatrix;
+			gl.mvMatrix = mvMatrix;
+			gl.side = side;
+
+			glMatrix.mat4.ortho(0, gl.viewportWidth, gl.viewportHeight, 0, -10, 10, oMatrix);
+
+			glMatrix.mat4.identity(mvMatrix);
+
+			if(side == Layer.TOP){
+				glMatrix.mat4.scale(mvMatrix, [1.0, -1.0, 1.0]);
+				glMatrix.mat4.translate(mvMatrix, [0.0, -gl.viewportHeight, 0.0]);
+			}
+
+			glMatrix.mat4.scale(mvMatrix, [scaleFactor, scaleFactor, 1.0]);
+			glMatrix.mat4.translate(mvMatrix, [-offsetX, -offsetY, 0.0]);
+
+	        gl.disableVertexAttribArray(this.texShaderProgram.vertexPositionAttribute);
+	        gl.disableVertexAttribArray(this.texShaderProgram.textureCoordAttribute);
+	        gl.enableVertexAttribArray(this.shaderProgram.vertexPositionAttribute);
+	        gl.disable(gl.BLEND);
+
+	        gl.useProgram(this.shaderProgram);
+
+			gl.uniformMatrix4fv(this.shaderProgram.pMatrixUniform, false, oMatrix);
+	        gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, mvMatrix);
+
+			if(side == Layer.TOP){
+
+				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, {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++){
+
+				color = this.otherLayers[l].pcbv.getLayerColors()[l];
+
+				r = parseInt(color.substring(1, 3), 16) / 256;
+				g = parseInt(color.substring(3, 5), 16) / 256;
+				b = parseInt(color.substring(5, 7), 16) / 256;
+
+				if(this.otherLayers[l].name == "bottom")
+					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, {r: r, g: g, b: b}, this.pins, this.top);
+				else
+					this.otherLayers[l].renderGL(gl, this.shaderProgram, {r: r, g: g, b: b}, this.pins, null);
+
+			}
+
+			gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+			// Draw Board
+			gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
+			gl.clearColor(0.79, 0.79, 0.79, 1.0);
+			gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+			gl.uniform4f(this.shaderProgram.vColorUniform, 0.89, 0.89, 0.89, 1.0);
+
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.boardVertexBuffer);
+			gl.vertexAttribPointer(this.shaderProgram.vertexPositionAttribute, this.boardVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
+			gl.drawArrays(gl.TRIANGLE_STRIP, 0, this.boardVertexBuffer.numItems);
+
+			// Setup texture program
+	        gl.useProgram(this.texShaderProgram);
+
+			glMatrix.mat4.ortho(-1, 1, -1, 1, -1, 1, oMatrix);
+			glMatrix.mat4.identity(mvMatrix);
+
+			gl.uniformMatrix4fv(this.texShaderProgram.pMatrixUniform, false, oMatrix);
+	        gl.uniformMatrix4fv(this.texShaderProgram.mvMatrixUniform, false, mvMatrix);
+
+	        gl.disableVertexAttribArray(this.shaderProgram.vertexPositionAttribute);
+	        gl.enableVertexAttribArray(this.texShaderProgram.vertexPositionAttribute);
+	        gl.enableVertexAttribArray(this.texShaderProgram.textureCoordAttribute);
+
+	        gl.enable(gl.BLEND);
+
+	        // Draw Layers
+	        gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexPositionBuffer);
+	        gl.vertexAttribPointer(this.texShaderProgram.vertexPositionAttribute, this.layerVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
+	        gl.bindBuffer(gl.ARRAY_BUFFER, this.layerVertexTextureCoordBuffer);
+	        gl.vertexAttribPointer(this.texShaderProgram.textureCoordAttribute, this.layerVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
+	        gl.activeTexture(gl.TEXTURE0);
+	        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.layerVertexIndexBuffer);
+
+	        if(side != Layer.TOP){
+
+	        	this._drawLayer(this.topSilk);
+	        	this._drawLayer(this.solder);
+	        	for(l = this.otherLayers.length - 1; l >= 0; l--)
+		        	this._drawLayer(this.otherLayers[l]);
+	        	this._drawLayer(this.top);
+	        	this._drawLayer(this.pins);
+	        	this._drawLayer(this.bottomSilk);
+
+	        } else {
+
+	        	this._drawLayer(this.bottomSilk);
+	        	this._drawLayer(this.top);
+	        	for(l = 0; l < this.otherLayers.length; l++)
+		        	this._drawLayer(this.otherLayers[l]);
+	        	this._drawLayer(this.solder);
+	        	this._drawLayer(this.pins);
+	        	this._drawLayer(this.topSilk);
+
+	        }
+
+		};
+
+		return GLRenderer;
+
+	}
+);

--- /dev/null
+++ b/src/js/circuit/PCB/Renderers/Renderer.js
@@ -1,1 +1,70 @@
+define(
+	[
+	 	"../Layer",
+	 	"Graphics/glMatrix",
+	 	"Util/Exception/NotImplementedException"
+	],
+	function(
+		Layer,
+		glMatrix,
+		NotImplementedException
+	){
 
+		var Renderer = function(ctx, canvas, symbols, layers, boardWidth, boardHeight){
+
+			if(!layers) return;
+
+			this.ctx = ctx;
+			this.canvas = canvas;
+
+			this.boardWidth = boardWidth;
+			this.boardHeight = boardHeight;
+
+			this.symbols = symbols;
+
+			this.layers = [];
+
+			this.topSilk = null;
+			this.bottomSkil = null;
+
+			this.top = null;
+			this.solder = null;
+			this.pins = null;
+
+			this.otherLayers = [];
+
+			for(var i = 0; i < layers.length; i++)
+				this.addLayer(layers[i]);
+
+		};
+
+		Renderer.prototype.addLayer = function(layer){
+
+			this.layers.push(layer);
+
+			if(layer.name == "silk"){
+				if(!this.topSilk) this.topSilk = layer;
+				else this.bottomSilk = layer;
+			}
+			else if(layer.name == "top_component")
+				this.top = layer;
+			else if(layer.name == "solder_component")
+				this.solder = layer;
+			else if(layer.name == "pins")
+				this.pins = layer;
+			else
+				this.otherLayers.push(layer);
+
+			layer.seperatePolygons();
+
+		};
+
+		Renderer.prototype.destroy = function(){throw new NotImplementedException("Renderer.destroy is virtual function");};
+		Renderer.prototype.setup = function(){throw new NotImplementedException("Renderer.setup is virtual function");};
+		Renderer.prototype.resize = function(){throw new NotImplementedException("Renderer.resize is virtual function");};
+		Renderer.prototype.render = function( side, offsetX, offsetY, scaleFactor){throw new NotImplementedException("Renderer.render is virtual function");};
+
+		return Renderer;
+
+	}
+);

--- /dev/null
+++ b/src/js/circuit/PCB/Renderers/TwoDRenderer.js
@@ -1,1 +1,120 @@
+define(
+	[
+	 	"./Renderer",
+	 	"../Layer",
+	 	"Util/Class"
+	],
+	function(
+		Renderer,
+		Layer,
+		Class
+	){
 
+		var TwoDRenderer = function(ctx, canvas, symbols, layers, boardWidth, boardHeight){
+
+			Renderer.call(this, ctx, canvas, symbols, layers, boardWidth, boardHeight);
+
+		};
+
+		Class.extend(Renderer, TwoDRenderer);
+
+		TwoDRenderer.prototype._renderLayer = function(layer, color){
+
+			var components = null;
+
+			if(layer && !layer.isEmpty()){
+
+				if(layer.name == "bottom") components = this.solder;
+				else if(layer.name == "top") components = this.top;
+
+				// Clear Buffer, have to reset transform for this
+				this.bufferCtx.save();
+				this.bufferCtx.setTransform(1,0,0,1,0,0);
+				this.bufferCtx.clearRect(0, 0, this.bufferCanvas.width, this.bufferCanvas.height);
+				this.bufferCtx.restore();
+
+				layer.render(this.bufferCtx, color, this.pins, components);
+
+				this.ctx.drawImage(this.bufferCanvas, 0, 0);
+
+			}
+
+		};
+
+		TwoDRenderer.prototype.destroy = function(){};
+
+		TwoDRenderer.prototype.setup = function(){
+
+			this.bufferCanvas = document.createElement('canvas');
+			this.bufferCanvas.width = this.canvas.width;
+			this.bufferCanvas.height = this.canvas.height;
+	
+			this.bufferCtx = this.bufferCanvas.getContext('2d');
+
+		};
+
+		TwoDRenderer.prototype.resize = function(){
+
+			this.bufferCanvas.width = this.canvas.width;
+			this.bufferCanvas.height = this.canvas.height;
+
+		}
+
+		TwoDRenderer.prototype.render = function(side, offsetX, offsetY, scaleFactor){
+
+			// Fill canvas background Dark Grey
+			this.bufferCtx.fillStyle = '#CCCCCC';
+			this.bufferCtx.fillRect(0, 0, this.bufferCanvas.width, this.bufferCanvas.height);
+
+			// Save default transform
+			this.bufferCtx.save();
+		
+			// Flip canvas if solder side
+			if(side){
+				this.bufferCtx.scale(1, -1);
+				this.bufferCtx.translate(0, -this.bufferCanvas.height);
+			}
+		
+			// Scale and shift
+			this.bufferCtx.scale(scalef, scalef);
+			this.bufferCtx.translate(-offsetX, -offsetY);	
+
+			// Fill board space Grey
+			this.bufferCtx.fillStyle = '#E5E5E5';
+			this.bufferCtx.fillRect(0, 0, this.boardWidth, this.boardHeight);
+			this.ctx.globalAlpha = 1.0;
+			this.ctx.drawImage(this.bufferCanvas, 0, 0);
+
+			// Draw Layers
+			this.ctx.globalAlpha = 0.5;
+			if(side != Layer.TOP){
+
+	        	this._renderLayer(this.topSilk, '#FFFFFF', null);
+	        	this._renderLayer(this.solder, '#FFFFFF', null);
+	        	for(l = this.otherLayers.length - 1; l >= 0; l--)
+	        		this._renderLayer(this.otherLayers[l], null, null);
+	        	this._renderLayer(this.top, '#000000', null);
+	        	this._renderLayer(this.pins, null, null);
+	        	this._renderLayer(this.bottomSilk, '#000000', null);
+
+	        } else {
+
+	        	this._renderLayer(this.bottomSilk, '#FFFFFF', null);
+	        	this._renderLayer(this.top, '#FFFFFF', null);
+	        	for(l = 0; l < this.otherLayers.length; l++)
+	        		this._renderLayer(this.otherLayers[l], null, null);
+	        	this._renderLayer(this.solder, '#000000', null);
+	        	this._renderLayer(this.pins, null, null);
+	        	this._renderLayer(this.topSilk, '#000000', null);
+
+	        }
+		
+			// Restore default transform
+			this.bufferCtx.restore();
+
+		};
+
+		return TwoDRenderer;
+
+	}
+);

--- a/src/js/circuit/PCB/Text.js
+++ b/src/js/circuit/PCB/Text.js
@@ -30,7 +30,7 @@
 			this.scaling = scaling;
 			this.str = str;
 			this.flags = flags;
-	
+
 		};
 	
 		Text.prototype.render = function(ctx, color){
@@ -53,7 +53,9 @@
 			ctx.restore();
 	
 		};
-	
+
+		Text.prototype.clear = function(ctx){};
+
 		Text.prototype.renderGL = function(gl, shaderProgram){
 
 			var sym, mvMatrix;
@@ -81,6 +83,8 @@
 	        gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
 
 		}
+
+		Text.prototype.clearGL = function(gl, shaderProgram){};
 	
 		Text.prototype.cleanupGL = function(gl){}
 

--- /dev/null
+++ b/src/js/circuit/PCB/Thermal.js
@@ -1,1 +1,231 @@
-
+define(
+	function(){
+
+		var Thermal = function(layerNumber, type){
+
+			this.layerNumber = layerNumber;
+			this.type = type;
+
+		};
+
+		Thermal.findThermal = function(list, layerNumber){
+			for(var i = 0; i < list.length; i++)
+				if(list[i].onLayer(layerNumber))
+					return list[i];
+			return null;
+		};
+
+		Thermal.prototype.onLayer = function(layerNumber){
+			return this.layerNumber == layerNumber - 1;
+		};
+
+		Thermal.prototype.clear = function(ctx, x, y, clearance, outerDiameter, innerDiameter){
+			switch(this.type){
+				case 'S':
+					break;
+				case 't':
+					var radius = ((clearance / 2) + outerDiameter) / 2;
+					var clearanceAngle = clearance / radius / 2;
+
+					ctx.lineCap = 'round';
+					ctx.lineWidth = clearance / 2;
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -clearanceAngle, -Math.PI * 0.5 + clearanceAngle, true);
+					ctx.stroke();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 0.5 - clearanceAngle, -Math.PI * 1.0 + clearanceAngle, true);
+					ctx.stroke();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.0 - clearanceAngle, -Math.PI * 1.5 + clearanceAngle, true);
+					ctx.stroke();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.5 - clearanceAngle, -Math.PI * 2.0 + clearanceAngle, true);
+					ctx.stroke();
+					break;
+				case 'X':
+					var radius = ((clearance / 2) + outerDiameter) / 2;
+					var clearanceAngle = clearance / radius / 2;
+
+					ctx.lineCap = 'round';
+					ctx.lineWidth = clearance / 2;
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 0.25 - clearanceAngle, -Math.PI * 0.75 + clearanceAngle, true);
+					ctx.stroke();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 0.75 - clearanceAngle, -Math.PI * 1.25 + clearanceAngle, true);
+					ctx.stroke();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.25 - clearanceAngle, -Math.PI * 1.75 + clearanceAngle, true);
+					ctx.stroke();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.75 - clearanceAngle, -Math.PI * 2.25 + clearanceAngle, true);
+					ctx.stroke();
+					break;
+				case '+':
+					var radius = (clearance + outerDiameter) / 2;
+					var clearanceAngle = clearance / radius / 4;
+					var clearanceAngle2 = clearance / outerDiameter / 2;
+					ctx.beginPath();
+					ctx.arc(x, y, radius, - clearanceAngle, -Math.PI * 0.5 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 0.5 + clearanceAngle2, - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 0.5 - clearanceAngle, -Math.PI * 1.0 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 1.0 + clearanceAngle2, -Math.PI * 0.5 - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.0 - clearanceAngle, -Math.PI * 1.5 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 1.5 + clearanceAngle2, -Math.PI * 1.0 - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.5 - clearanceAngle, -Math.PI * 2.0 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 2.0 + clearanceAngle2, -Math.PI * 1.5 - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					break;
+				case 'O':
+					var radius = (clearance + outerDiameter) / 2;
+					var clearanceAngle = clearance / radius / 4;
+					var clearanceAngle2 = clearance / outerDiameter / 2;
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 0.25 - clearanceAngle, -Math.PI * 0.75 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 0.75 + clearanceAngle2, -Math.PI * 0.25 - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 0.75 - clearanceAngle, -Math.PI * 1.25 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 1.25 + clearanceAngle2, -Math.PI * 0.75 - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.25 - clearanceAngle, -Math.PI * 1.75 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 1.75 + clearanceAngle2, -Math.PI * 1.25 - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					ctx.beginPath();
+					ctx.arc(x, y, radius, -Math.PI * 1.75 - clearanceAngle, -Math.PI * 2.25 + clearanceAngle, true);
+					ctx.arc(x, y, outerDiameter / 2, -Math.PI * 2.25 + clearanceAngle2, -Math.PI * 1.75 - clearanceAngle2, false);
+					ctx.closePath();
+					ctx.fill();
+					break;
+				default:
+					ctx.beginPath();
+					ctx.arc(x, y, (clearance + outerDiameter) / 2, 0, Math.PI * 2, true);
+					ctx.closePath();
+					ctx.fill();
+					break;
+			}
+
+		};
+
+		Thermal._clearArc = function(gl, shaderProgram, pointBuffer, ang1, ang2, shave, outerDiameter, innerDiameter, clearance){
+
+
+			gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+			gl.uniform1f(shaderProgram.arcEnabledUniform, true);
+			gl.uniform1f(shaderProgram.innerRadiusUniform, innerDiameter / outerDiameter / 2);
+			gl.uniform1f(shaderProgram.pointsizeUniform, outerDiameter * gl.scaleFactor);
+			gl.uniform1f(shaderProgram.startAngleUniform, ang1 + ang2);
+			gl.uniform1f(shaderProgram.sweepUniform, Math.PI / 2 - ang2 * 2);
+			if(shave)
+				gl.uniform1f(shaderProgram.shaveInsideUniform, clearance / outerDiameter / 4);
+
+			gl.drawArrays(gl.POINTS, 0, pointBuffer.numItems);
+
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+			gl.uniform1f(shaderProgram.arcEnabledUniform, false);
+			gl.uniform1f(shaderProgram.shaveInsideUniform, 0.0);
+
+		};
+
+		Thermal.prototype._buildCache = function(gl, x, y, angleOffset, angle, radius){
+
+			var pointBuffer, points, angle2;
+
+			angle2 = Math.PI * 0.5 + angle + angleOffset;
+			angle += angleOffset;
+			points = [
+			 x + radius * Math.cos(angle), y + radius * Math.sin(angle), 0,
+			 x - radius * Math.cos(angle), y + radius * Math.sin(angle), 0,
+			 x + radius * Math.cos(angle), y - radius * Math.sin(angle), 0,
+			 x - radius * Math.cos(angle), y - radius * Math.sin(angle), 0,
+			 x + radius * Math.cos(angle2), y + radius * Math.sin(angle2), 0,
+			 x - radius * Math.cos(angle2), y + radius * Math.sin(angle2), 0,
+			 x + radius * Math.cos(angle2), y - radius * Math.sin(angle2), 0,
+			 x - radius * Math.cos(angle2), y - radius * Math.sin(angle2), 0,
+		    ];
+
+			pointBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer);
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points), gl.STATIC_DRAW);
+			pointBuffer.itemSize = 3;
+			pointBuffer.numItems = 8;
+			this.pointBuffer = pointBuffer;
+
+		};
+
+		Thermal.prototype._clearPoints = function(gl, shaderProgram, clearance){
+
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, (clearance / 2) * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+
+		};
+
+		Thermal.prototype.clearGL = function(gl, shaderProgram, x, y, pointBuffer, clearance, outerDiameter, innerDiameter){
+			switch(this.type){
+				case 'S':
+					break;
+				case 't':
+					var clearanceAngle = clearance / ((clearance / 2 + outerDiameter) / 2) / 2;
+					if(!this.pointBuffer) this._buildCache(gl, x, y, 0, clearanceAngle, ((clearance / 2) + outerDiameter) / 2);
+					this._clearPoints(gl, shaderProgram, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, 0            , clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 0.5, clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer,-Math.PI * 0.5, clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer,-Math.PI     , clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					break;
+				case 'X':
+					var clearanceAngle = clearance / ((clearance / 2 + outerDiameter) / 2) / 2;
+					if(!this.pointBuffer) this._buildCache(gl, x, y, Math.PI * 0.25, clearanceAngle, ((clearance / 2) + outerDiameter) / 2);
+					this._clearPoints(gl, shaderProgram, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 0.25, clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer,-Math.PI * 0.25, clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 0.75, clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer,-Math.PI * 0.75, clearanceAngle, false, outerDiameter + clearance, outerDiameter, clearance);
+					break;
+				case '+':
+					var clearanceAngle = clearance / ((clearance + outerDiameter) / 2) / 4;
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, 0            , clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 0.5, clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI      , clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 1.5, clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					break;
+				case 'O':
+					var clearanceAngle = clearance / ((clearance + outerDiameter) / 2) / 4;
+					gl.uniform1f(shaderProgram.shaveFFUniform, true);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 0.25, clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 0.75, clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 1.25, clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					Thermal._clearArc(gl, shaderProgram, pointBuffer, Math.PI * 1.75, clearanceAngle, true, outerDiameter + clearance, outerDiameter, clearance);
+					gl.uniform1f(shaderProgram.shaveFFUniform, false);
+					break;
+				default:
+					break;
+			}
+		};
+
+		return Thermal;
+
+	}
+);

--- a/src/js/circuit/PCB/Via.js
+++ b/src/js/circuit/PCB/Via.js
@@ -1,73 +1,154 @@
-define(function() {
-	var Via = function(x, y, od, u1, u2, id, u3, u4) {
+define(
+	[
+	 	"./Thermal",
+	 	"./parseFlags"
+	],
+	function(
+		Thermal,
+		parseFlags
+	){
 
-		this.x = x;
-		this.y = y;
-		this.od = od;
-		this.id = id;
+		var Via = function(x, y, od, clearance, u2, id, u3, flags) {
 
-	};
+			this.x = x;
+			this.y = y;
+			this.od = od;
+			this.id = id;
+			this.clearance = clearance;
+			this.flags = parseFlags(Via._defaultFlags, flags);
 
-	Via.prototype.render = function(ctx) {
+		};
 
-		ctx.beginPath();
-		ctx.arc(this.x, this.y, this.od / 2, 0, Math.PI * 2, true);
-		ctx.closePath();
-		ctx.fillStyle = '#7F7F7F'; // TODO: set colors to global option
-		ctx.fill();
+		Via._defaultFlags = {
+		};
 
-		ctx.beginPath();
-		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.render = function(ctx) {
+	
+			ctx.beginPath();
+			ctx.arc(this.x, this.y, this.od / 2, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fillStyle = '#7F7F7F'; // TODO: set colors to global option
+			ctx.fill();
+	
+			ctx.beginPath();
+			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, layerNumber){
 
-	};
+			var thrm = this.flags.thermal;
+			if(thrm){
+				thrm = Thermal.findThermal(thrm, layerNumber);
+				if(thrm)
+					thrm.clear(ctx, this.x, this.y, this.clearance, this.od, this.id);
+			}
 
-	Via.prototype.renderGL = function(gl, shaderProgram){
+			if(!thrm){
+				ctx.beginPath();
+				ctx.arc(this.x, this.y, (this.clearance + this.od) / 2.0, 0, Math.PI * 2, true);
+				ctx.closePath();
+				ctx.fill();
+			}
 
-		gl.uniform1f(shaderProgram.roundPointsUniform, true);
+		};
 
-		gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+		Via.prototype.clearInner = function(ctx){
 
-		gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+			ctx.beginPath();
+			ctx.arc(this.x, this.y, this.id / 2.0, 0, Math.PI * 2, true);
+			ctx.closePath();
+			ctx.fill();
 
-		gl.uniform4f(shaderProgram.vColorUniform, 0.59, 0.59, 0.59, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.od*gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+		};
 
-		gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
-		gl.uniform1f(shaderProgram.pointsizeUniform, this.id*gl.scaleFactor);
-		gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+		Via.prototype.renderGL = function(gl, shaderProgram){
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+	
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
 
-		gl.uniform1f(shaderProgram.roundPointsUniform, false);
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+	
+			gl.uniform4f(shaderProgram.vColorUniform, 0.59, 0.59, 0.59, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.od*gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform4f(shaderProgram.vColorUniform, 0.74, 0.74, 0.74, 1.0);
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.id*gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+	
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+	
+		}
+	
+		Via.prototype.clearGL = function(gl, shaderProgram, layerNumber){
+	
+			var thrm = this.flags.thermal;
+			if(thrm){
+				thrm = Thermal.findThermal(thrm, layerNumber);
+				if(thrm)
+					thrm.clearGL(gl, shaderProgram, this.x, this.y, this.pointBuffer, this.clearance, this.od, this.id);
+			}
+
+			if(!thrm){
+				gl.uniform1f(shaderProgram.roundPointsUniform, true);
+
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+				gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+
+				gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+
+				gl.uniform1f(shaderProgram.pointsizeUniform, (this.od + this.clearance) * gl.scaleFactor);
+				gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+
+				gl.uniform1f(shaderProgram.roundPointsUniform, false);
+			}
+	
+		};
+	
+		Via.prototype.cleanupGL = function(gl){
+	
+			if(this.pointBuffer){
+				gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+				gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
+				gl.deleteBuffer(this.pointBuffer);
+				this.pointBuffer = null;
+			}
+	
+		}
+
+		Via.prototype.clearInnerGL = function(gl, shaderProgram){
+			gl.uniform1f(shaderProgram.roundPointsUniform, true);
+
+			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
+			gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.pointBuffer.itemSize, gl.FLOAT, false, 0, 0);
+
+			gl.uniform1f(shaderProgram.innerRadiusUniform, 0.0);
+
+			gl.uniform1f(shaderProgram.pointsizeUniform, this.id * gl.scaleFactor);
+			gl.drawArrays(gl.POINTS, 0, this.pointBuffer.numItems);
+
+			gl.uniform1f(shaderProgram.roundPointsUniform, false);
+		};
+
+		Via.prototype.setup3DArrayBuffer = function(gl){
+	
+			var vBuffer;
+			vBuffer = gl.createBuffer();
+			gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
+			gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x,this.y,0.0]), gl.STATIC_DRAW);
+			vBuffer.itemSize = 3;
+			vBuffer.numItems = 1;
+			this.pointBuffer = vBuffer;
+	
+		}
+	
+		return Via;
 
 	}
-
-	Via.prototype.cleanupGL = function(gl){
-
-		if(this.pointBuffer){
-			gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
-			gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
-			gl.deleteBuffer(this.pointBuffer);
-			this.pointBuffer = null;
-		}
-
-	}
-
-	Via.prototype.setup3DArrayBuffer = function(gl){
-
-		var vBuffer;
-		vBuffer = gl.createBuffer();
-		gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
-		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([this.x,this.y,0.0]), gl.STATIC_DRAW);
-		vBuffer.itemSize = 3;
-		vBuffer.numItems = 1;
-		this.pointBuffer = vBuffer;
-
-	}
-
-	return Via;
-
-});
+);

--- /dev/null
+++ b/src/js/circuit/PCB/parseFlags.js
@@ -1,1 +1,72 @@
+define(
+	[
+	 	"./Thermal"
+	],
+	function(
+		Thermal
+	){
+	
+		var parseFlags = function(defaultFlags, flags){
+	
+			if(!flags) return {};
+	
+			var parsedFlags, split, parts, flag, attr, thrm, i, j, k;
+	
+			split = flags.split("\(.*?\)|(,)");
+	
+			parsedFlags = {};
+	
+			for(attr in defaultFlags)
+	            if(defaultFlags.hasOwnProperty(attr))
+	            	parsedFlags[attr] = defaultFlags[attr];
 
+			for(i = 0; i < split.length; i++){
+	
+				flag = split[i];
+	
+				if(flag.indexOf("thermal") != -1){
+
+					thrm = [];
+	
+					flag = flag.split('(')[1].split(')')[0].split(',');
+					for(j = 0; j < flag.length; j++){
+						// check for #-#
+						// for each add layer
+						//else layer #
+						parts = flag[j].split('-');
+						if(parts.length == 2){
+							parts = flag[j][flag[j].length-1];
+							if(isNaN(parseInt(parts))){
+								parts = flag[j].substring(0, flag[j].length - 1).split('-');
+								attr = parts;
+							} else {
+								parts = flag[j].split('-');
+								attr = 'O';
+							}
+							
+							for(k = parseInt(parts[0]); k <= parseInt(parts[1]); k++){
+								thrm.push(new Thermal(k, attr));
+							}
+						} else {
+							parts = flag[j][flag[j].length-1];
+							if(isNaN(parseInt(parts)))
+								thrm.push(new Thermal(parseInt(flag[j].substring(0, flag[j].length - 1)), parts));
+							else
+								thrm.push(new Thermal(parseInt(flag[j].substring(0, flag[j].length)), 'O'));
+						}
+					}
+					parsedFlags.thermal = thrm;
+				}
+				else
+					parsedFlags[flag] = true;
+	
+			}
+	
+			return parsedFlags;
+	
+		};
+	
+		return parseFlags;
+
+	}
+);

--- a/src/js/main.js
+++ b/src/js/main.js
@@ -1,29 +1,33 @@
 requirejs.config({
 
 	baseUrl: 'js',
+	paths: {
+		shaders: '../data/shaders',
+	}
 
 });
 
 require(['circuit/PCB/PCBViewer'], function(PCBV){
 
-	var PCBListSelect, PCBListReq;
+	var PCBListSelect, PCBListReq, PCBCanvasContainer, status;
 
 	window.PCBViewer = {};
 
 	PCBListSelect = document.getElementById("samplePCBs");
-
-	window.PCBViewer.canvas = document.getElementById('pcbcan');
-
-	window.PCBViewer.canvas.width = window.innerWidth-20;
-	window.PCBViewer.canvas.height = window.innerHeight-50;
+	PCBCanvasContainer = document.getElementById("PCB-canvas-container");
+	status = document.getElementById("Status");
 
 	window.onresize = function(e){
 
-		window.PCBViewer.canvas.width = window.innerWidth-20;
-		window.PCBViewer.canvas.height = window.innerHeight-50;
+		if(window.PCBViewer.canvas){
 
-		window.PCBViewer.pcb.resize();
-		window.PCBViewer.pcb.render(true);
+			window.PCBViewer.canvas.width = window.innerWidth-20;
+			window.PCBViewer.canvas.height = window.innerHeight-50;
+
+			window.PCBViewer.pcb.resize();
+			window.PCBViewer.pcb.render(true);
+
+		}
 
 	};
 
@@ -58,12 +62,29 @@
 
 		PCBLoadReq.onload = function(){
 
-			if(window.PCBViewer.pcb)
-				window.PCBViewer.pcb.destroy();
+			var pcb = window.PCBViewer.pcb;
 
-			window.PCBViewer.pcb = new PCBV(window.PCBViewer.canvas, true);
-			window.PCBViewer.pcb.parse_data(PCBLoadReq.response);
-			window.PCBViewer.pcb.render();
+			if(pcb){
+				pcb.destroy();
+				pcb = null;
+			}
+
+			var mode = document.querySelector('input[name="mode"]:checked').value;
+
+			PCBCanvasContainer.innerHTML = '<canvas id="pcbcan" width="800" height="600" tabindex="1"></canvas>';
+
+			window.PCBViewer.canvas = document.getElementById('pcbcan');
+
+			window.PCBViewer.canvas.width = window.innerWidth-20;
+			window.PCBViewer.canvas.height = window.innerHeight-50;
+
+			pcb = new PCBV(window.PCBViewer.canvas, true, mode);
+			window.PCBViewer.pcb = pcb;
+			pcb.parse(PCBLoadReq.response);
+			pcb.setup();
+			pcb.render();
+
+			status.innerHTML = window.PCBViewer.pcb.mode;
 
 		};