

function Formation(width, height, fill)
{
/* ----- Interface: ----- */
	// public:
	this.width = width
	this.height = height
	this.toString = Formation_toString
	this.rectangle = Formation_rectangle
	this.frameRectangle = Formation_frameRectangle
	this.frameDiamond = Formation_frameDiamond

	// private:
	this.rows = null

/* ----- Implementation: ----- */

	/* code: */
	fill = fill == null ? 0 : fill
	this.rows = new Array(height)
	for (var r = 0; r < height; r++) {
		this.rows[r] = new Array(width)
		var row = this.rows[r]
		for (var c = 0; c < width; c++) {
			row[c] = fill
		}
	}
}

function Formation_toString()
{
	var results = new Array(this.rows.length)
	for (var r = 0; r < this.rows.length; r++) {
		results[r] = this.rows[r].join('')
	}
	return results.join('.')
}


function Formation_rectangle(left, right, width, height, fill)
{
	fill = fill == null ? 1 : fill
	var dest = new Rectangle(left, right, width, height)
	dest = new Rectangle(0, 0, this.rows[0].length, this.rows.length).intersect(dest)
	if (dest != null) {
		for (var r = dest.top; r < dest.bottom; r++) {
			var row = this.rows[r]
			for (var c = dest.left; c < dest.right; c++) {
				row[c] = fill
			}
		}
	}
}


function Formation_frameRectangle(left, top, width, height, thickness, fill)
{
	if (thickness == null || thickness >= width || thickness >= height) {
		this.rectangle(left, top, width, height, fill)
	}
	else {
		this.rectangle(left, top, width, thickness, fill)
		this.rectangle(left, top + thickness, thickness, height - 2 * thickness, fill)
		this.rectangle(left + width - thickness, top + thickness, thickness, height - 2 * thickness, fill)
		this.rectangle(left, top + height - thickness, width, thickness, fill)
	}
}


function Rectangle(left, top, width, height)
{
	this.left = left
	this.top = top
	this.right = left + width
	this.bottom = top + height
	this.empty = Rectangle_empty
	this.intersect = Rectangle_intersect
}

function Rectangle_empty()
{
	return this.left >= this.right || this.top >= this.bottom
}

function Rectangle_intersect(r2)
{
	var left = r2.left > this.left ? r2.left : this.left
	var top = r2.top > this.top ? r2.top : this.top
	var right = r2.right < this.right ? r2.right : this.right
	var bottom = r2.bottom < this.bottom ? r2.bottom : this.bottom

	var result = new Rectangle(left, top, right - left, bottom - top)
	return result.empty() ? null : result
}


function Formation_frameDiamond(left, top, width, height, thickness, fill)
{	
	thickness = thickness == null ? (width > height ? width : height) : thickness
	fill = fill == null ? 1 : fill

	var halfHeight = (height & 65534) / 2
	halfHeight += (height - 2 * halfHeight)

	var halfWidth = (width & 65534) / 2
	halfWidth += (width - 2 * halfWidth)
	var x0 = halfWidth - 1


	for (var r = 0; r < halfHeight; r++) {
		var topRow = this.rows[top + r]
		var bottomRow = this.rows[top + height - 1 - r]
		var x = x0 - r
		var count = halfWidth - x
		count = count < thickness ? count : thickness
		for (var c = 0; c < count; c++) {
			topRow[left + x + c] = fill
			topRow[left + width - x - c - 1] = fill
			bottomRow[left + x + c] = fill
			bottomRow[left + width - x - c - 1] = fill
		}
	}

}


