+/** Find a point along the coordinate system given by the given line,
+ * <t> units forward from the start of the line, <u> units to the right of it.
+ * @param {!number} x1
+ * @param {!number} x2
+ * @param {!number} y1
+ * @param {!number} y2
+ * @param {!number} t
+ * @param {!number} u
+ * @return {!string} The point in "x y" form, suitable for SVG paths.
+ */
+var point_from_start = function(x1, y1, x2, y2, t, u) {
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+
+ var norm = 1.0 / Math.sqrt(dx * dx + dy * dy);
+ dx *= norm;
+ dy *= norm;
+
+ var x = x1 + dx * t + dy * u;
+ var y = y1 + dy * t - dx * u;
+ return x + " " + y;
+}
+
+/** Find a point along the coordinate system given by the given line,
+ * <t> units forward from the end of the line, <u> units to the right of it.
+ * @param {!number} x1
+ * @param {!number} x2
+ * @param {!number} y1
+ * @param {!number} y2
+ * @param {!number} t
+ * @param {!number} u
+ * @return {!string} The point in "x y" form, suitable for SVG paths.
+ */
+var point_from_end = function(x1, y1, x2, y2, t, u) {
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+
+ var norm = 1.0 / Math.sqrt(dx * dx + dy * dy);
+ dx *= norm;
+ dy *= norm;
+
+ var x = x2 + dx * t + dy * u;
+ var y = y2 + dy * t - dx * u;
+ return x + " " + y;
+}
+
+var position_arrow = function(arrow) {
+ if (arrow.svg) {
+ arrow.svg.parentElement.removeChild(arrow.svg);
+ delete arrow.svg;
+ }
+ if (current_display_line !== null && !current_display_line_is_history) {
+ return;
+ }
+
+ var pos = $(".square-a8").position();
+
+ var zoom_factor = $("#board").width() / 400.0;
+ var line_width = arrow.line_width * zoom_factor;
+ var arrow_size = arrow.arrow_size * zoom_factor;
+
+ var square_width = $(".square-a8").width();
+ var from_y = (7 - arrow.from_row + 0.5)*square_width;
+ var to_y = (7 - arrow.to_row + 0.5)*square_width;
+ var from_x = (arrow.from_col + 0.5)*square_width;
+ var to_x = (arrow.to_col + 0.5)*square_width;
+
+ var SVG_NS = "http://www.w3.org/2000/svg";
+ var XHTML_NS = "http://www.w3.org/1999/xhtml";
+ var svg = document.createElementNS(SVG_NS, "svg");
+ svg.setAttribute("width", /** @type{number} */ ($("#board").width()));
+ svg.setAttribute("height", /** @type{number} */ ($("#board").height()));
+ svg.setAttribute("style", "position: absolute");
+ svg.setAttribute("position", "absolute");
+ svg.setAttribute("version", "1.1");
+ svg.setAttribute("class", "c1");
+ svg.setAttribute("xmlns", XHTML_NS);
+
+ var x1 = from_x;
+ var y1 = from_y;
+ var x2 = to_x;
+ var y2 = to_y;
+
+ // Draw the line.
+ var outline = document.createElementNS(SVG_NS, "path");
+ outline.setAttribute("d", "M " + point_from_start(x1, y1, x2, y2, arrow_size / 2, 0) + " L " + point_from_end(x1, y1, x2, y2, -arrow_size / 2, 0));
+ outline.setAttribute("xmlns", XHTML_NS);
+ outline.setAttribute("stroke", "#666");
+ outline.setAttribute("stroke-width", line_width + 2);
+ outline.setAttribute("fill", "none");
+ svg.appendChild(outline);
+
+ var path = document.createElementNS(SVG_NS, "path");
+ path.setAttribute("d", "M " + point_from_start(x1, y1, x2, y2, arrow_size / 2, 0) + " L " + point_from_end(x1, y1, x2, y2, -arrow_size / 2, 0));
+ path.setAttribute("xmlns", XHTML_NS);
+ path.setAttribute("stroke", arrow.fg_color);
+ path.setAttribute("stroke-width", line_width);
+ path.setAttribute("fill", "none");
+ svg.appendChild(path);
+
+ // Then the arrow head.
+ var head = document.createElementNS(SVG_NS, "path");
+ head.setAttribute("d",
+ "M " + point_from_end(x1, y1, x2, y2, 0, 0) +
+ " L " + point_from_end(x1, y1, x2, y2, -arrow_size, -arrow_size / 2) +
+ " L " + point_from_end(x1, y1, x2, y2, -arrow_size * .623, 0.0) +
+ " L " + point_from_end(x1, y1, x2, y2, -arrow_size, arrow_size / 2) +
+ " L " + point_from_end(x1, y1, x2, y2, 0, 0));
+ head.setAttribute("xmlns", XHTML_NS);
+ head.setAttribute("stroke", "#000");
+ head.setAttribute("stroke-width", "1");
+ head.setAttribute("fill", arrow.fg_color);
+ svg.appendChild(head);
+
+ $(svg).css({ top: pos.top, left: pos.left });
+ document.body.appendChild(svg);
+ arrow.svg = svg;