Commits

Walter Dörwald committed f35e837

Finish implementation of JS versions of rgb/hls/hsv functions. Add tests.

Comments (0)

Files changed (3)

 
 	_fu_rgb: function(r, g, b, a)
 	{
-		var c = this._clone(this.Color);
-		c.r = r;
-		c.g = g;
-		c.b = b;
-		c.a = a;
-		return c;
+		return this.Color.create(255*r, 255*g, 255*b, typeof(a) == "undefined" ? 0xff : (255*a));
 	},
 
 	_fu_type: function(obj)
 		return new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds());
 	},
 
+	_fu_hls: function(h, l, s, a)
+	{
+		var _v = function(m1, m2, hue)
+		{
+			hue = hue % 1.0;
+			if (hue < 1/6)
+				return m1 + (m2-m1)*hue*6.0;
+			else if (hue < 0.5)
+				return m2;
+			else if (hue < 2/3)
+				return m1 + (m2-m1)*(2/3-hue)*6.0;
+			return m1;
+		};
+
+		var m1, m2;
+		if (typeof(a) === "undefined")
+			a = 1;
+		if (s == 0.0)
+		    return this._fu_rgb(l, l, l, a);
+		if (l <= 0.5)
+		    m2 = l * (1.0+s);
+		else
+		    m2 = l+s-(l*s);
+		m1 = 2.0*l - m2;
+		return this._fu_rgb(_v(m1, m2, h+1/3), _v(m1, m2, h), _v(m1, m2, h-1/3), a);
+	},
+
+	_fu_hsv: function(h, s, v, a)
+	{
+		if (typeof(a) === "undefined")
+			a = 1;
+		if (s == 0.0)
+			return this._fu_rgb(v, v, v, a);
+		var i = Math.floor(h*6.0);
+		var f = (h*6.0) - i;
+		var p = v*(1.0 - s);
+		var q = v*(1.0 - s*f);
+		var t = v*(1.0 - s*(1.0-f));
+		switch (i%6)
+		{
+			case 0:
+				return this._fu_rgb(v, t, p, a);
+			case 1:
+				return this._fu_rgb(q, v, p, a);
+			case 2:
+				return this._fu_rgb(p, v, t, a);
+			case 3:
+				return this._fu_rgb(p, q, v, a);
+			case 4:
+				return this._fu_rgb(t, p, v, a);
+			case 5:
+				return this._fu_rgb(v, p, q, a);
+		}
+	},
+
 	// Functions with the ``_me_`` prefix implement UL4 methods
 	_me_replace: function(string, searchstring, replacestring, count)
 	{
 		return obj.witha(newa);
 	},
 
-	_hls: function(h, l, s, a)
-	{
-		var _v = function(m1, m2, hue)
-		{
-			hue = hue % 1.0;
-			if (hue < 1/6)
-				return m1 + (m2-m1)*hue*6.0;
-			else if (hue < 0.5)
-				return m2;
-			else if (hue < 2/3)
-				return m1 + (m2-m1)*(2/3-hue)*6.0;
-			return m1;
-		};
-
-		var m1, m2;
-		if (typeof(a) === "undefined")
-			a = 1;
-		if (s == 0.0)
-		    return this._fu_rgb(l*255, l*255, l*255, a*255);
-		if (l <= 0.5)
-		    m2 = l * (1.0+s);
-		else
-		    m2 = l+s-(l*s);
-		m1 = 2.0*l - m2;
-		return this._fu_rgb(_v(m1, m2, h+1/3)*255, _v(m1, m2, h)*255, _v(m1, m2, h-1/3)*255, a*255);
-	},
-
 	_me_withlum: function(obj, newlum)
 	{
 		if (!this._fu_iscolor(obj))
 	Color: {
 		__iscolor__: true,
 
+		create: function(r, g, b, a)
+		{
+			var c = ul4._clone(this);
+			c.r = r;
+			c.g = g;
+			c.b = b;
+			c.a = a;
+			return c;
+		},
+
 		lum: function()
 		{
 			return this.hls()[1];
 		{
 			if (typeof(a) !== "number")
 				throw "witha() requires a number";
-			return ul4._fu_rgb(this.r, this.g, this.b, a);
+			return ul4.Color.create(this.r, this.g, this.b, a);
 		},
 
 		withlum: function(lum)
 			if (typeof(lum) !== "number")
 				throw "witha() requires a number";
 			var hlsa = this.hlsa();
-			return ul4._hls(hlsa[0], lum, hlsa[2], hlsa[3]);
+			return ul4._fu_hls(hlsa[0], lum, hlsa[2], hlsa[3]);
 		}
 	},
 
 			args[6] //= 1000
 		self._jssource_line(u"r{op.r1} = new Date({date});".format(op=opcode, date=", ".join(map(str, args))))
 	def _jssource_dispatch_loadcolor(self, opcode):
-		self._jssource_line(u"r{op.r1} = ul4._fu_rgb(0x{r}, 0x{g}, 0x{b}, 0x{a});".format(op=opcode, r=opcode.arg[:2], g=opcode.arg[2:4], b=opcode.arg[4:6], a=opcode.arg[6:]))
+		self._jssource_line(u"r{op.r1} = ul4.Color.create(0x{r}, 0x{g}, 0x{b}, 0x{a});".format(op=opcode, r=opcode.arg[:2], g=opcode.arg[2:4], b=opcode.arg[4:6], a=opcode.arg[6:]))
 	def _jssource_dispatch_buildlist(self, opcode):
 		self._jssource_line(u"r{op.r1} = [];".format(op=opcode))
 	def _jssource_dispatch_builddict(self, opcode):
 		if opcode.arg in {"range", "zip", "hls", "hsv", "randrange"}:
 			self._jssource_line(u"r{op.r1} = ul4._fu_{op.arg}(r{op.r2}, r{op.r3}, r{op.r4});".format(op=opcode))
 		elif opcode.arg == "rgb":
-			self._jssource_line(u"r{op.r1} = ul4._fu_{op.arg}(r{op.r2}, r{op.r3}, r{op.r4}, 0xff);".format(op=opcode))
+			self._jssource_line(u"r{op.r1} = ul4._fu_{op.arg}(r{op.r2}, r{op.r3}, r{op.r4}, 1.0);".format(op=opcode))
 		else:
 			raise UnknownFunctionError(opcode.arg)
 	def _jssource_dispatch_callfunc4(self, opcode):
 		if opcode.arg in {"rgb", "hls", "hsv"}:
-			self._jssource_line(u"r{op.r1} = ul4._fu_{op.arg}(r{op.r2}, r{op.r3}, r{op.r4}, r{op.5});".format(op=opcode))
+			self._jssource_line(u"r{op.r1} = ul4._fu_{op.arg}(r{op.r2}, r{op.r3}, r{op.r4}, r{op.r5});".format(op=opcode))
 		else:
 			raise UnknownFunctionError(opcode.arg)
 	def _jssource_dispatch_callmeth0(self, opcode):
 	elif isinstance(obj, datetime.date):
 		return format(obj, u"new Date({}, {}, {})".format(obj.year, obj.month-1, obj.day))
 	elif isinstance(obj, color.Color):
-		return u"ul4._fu_rgb({}, {}, {}, {})".format(*obj)
+		return u"ul4.Color.create({}, {}, {}, {})".format(*obj)
 	elif isinstance(obj, (tuple, list)):
 		return u"[{}]".format(u", ".join(_json(item) for item in obj))
 	elif isinstance(obj, dict):
 		assert "(3)(2)(1)" == r(code, x=(1, 2, 3))
 
 
+def test_function_rgb():
+	for r in allrenders():
+		assert "#369" == r("<?print repr(rgb(0.2, 0.4, 0.6))?>")
+		assert "#369c" == r("<?print repr(rgb(0.2, 0.4, 0.6, 0.8))?>")
+
+
+def test_function_hls():
+	for r in allrenders():
+		assert "#fff" == r("<?print repr(hls(0, 1, 0))?>")
+		assert "#fff0" == r("<?print repr(hls(0, 1, 0, 0))?>")
+
+
+def test_function_hsv():
+	for r in allrenders():
+		assert "#fff" == r("<?print repr(hsv(0, 0, 1))?>")
+		assert "#fff0" == r("<?print repr(hsv(0, 0, 1, 0))?>")
+
+
 def test_method_upper():
 	for r in allrenders():
 		assert "GURK" == r(u"<?print 'gurk'.upper()?>")