*
* The Initial Developer of the Original Code is
* Robert Kaiser <kairo@kairo.at>.
- * Portions created by the Initial Developer are Copyright (C) 2008
+ * Portions created by the Initial Developer are Copyright (C) 2008-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert Kaiser <kairo@kairo.at>
+ * prefiks (patch for some speedups)
+ * Boris Zbarsky <bzbarsky@mit.edu> (use imageData for canvas interaction)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
function Startup() {
updateIterMenu();
+ updateAlgoMenu();
updatePaletteMenu();
gMbrotBundle = document.getElementById("mbrotBundle");
document.getElementById("statusLabel").value = gMbrotBundle.getString("statusEmpty");
let Ci_max = dimensions[3];
let Ci_scale = Ci_max - Ci_min;
- let pixels = [];
+ let lines = Math.min(canvas.height - line, 8);
+ let imageData = context.createImageData(canvas.width, lines);
+ let pixels = imageData.data;
+ let idx = 0;
for (var img_y = line; img_y < canvas.height && img_y < line+8; img_y++)
for (let img_x = 0; img_x < canvas.width; img_x++) {
let C = new complex(Cr_min + (img_x / canvas.width) * Cr_scale,
Ci_min + (img_y / canvas.height) * Ci_scale);
- pixels.push.apply(pixels, drawPoint(context, img_x, img_y, C, iterMax, algorithm));
+ let colors = drawPoint(context, img_x, img_y, C, iterMax, algorithm);
+ pixels[idx++] = colors[0];
+ pixels[idx++] = colors[1];
+ pixels[idx++] = colors[2];
+ pixels[idx++] = colors[3];
}
- context.putImageData({width: canvas.width, height: pixels.length/4/canvas.width, data: pixels}, 0, line);
+ context.putImageData(imageData, 0, line);
if (img_y < canvas.height)
setTimeout(drawLine, 0, img_y, dimensions, canvas, context, iterMax, algorithm);
}
}
+function exitMandelbrot() {
+ var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
+ .getService(Components.interfaces.nsIXULAppInfo);
+ if (appInfo.ID == "mandelbrot@kairo.at")
+ quitApp(false);
+ else
+ window.close();
+}
+
function updateBookmarkMenu(aParent) {
document.getElementById("bookmarkSave").disabled =
(!document.getElementById("drawButton").hidden || (gStartTime > 0));
}
function imgSettings() {
- window.openDialog("chrome://mandelbrot/content/image-settings.xul");
+ if (document.getElementById("mandelbrotWindow").nodeName == "page")
+ document.getElementById("imgSettingsPanel").showPopup(null, "before_start");
+ else
+ window.openDialog("chrome://mandelbrot/content/image-settings.xul");
}
function updateDebugMenu() {
- var jitMenuItem = document.getElementById("jitEnabled");
- jitMenuItem.setAttribute("checked", gPref.getBoolPref("javascript.options.jit.chrome"));
+ let scope = (document.getElementById("mandelbrotWindow").nodeName == "page") ? "content" : "chrome";
+ for each (let type in ["tracejit", "methodjit"]) {
+ let jitMenuItem = document.getElementById(type + "Enabled");
+ jitMenuItem.setAttribute("checked", gPref.getBoolPref("javascript.options." + type + "." + scope));
+ }
}
-function toggleJITState(jitMenuItem) {
- var jitEnabled = !gPref.getBoolPref("javascript.options.jit.chrome");
- gPref.setBoolPref("javascript.options.jit.chrome", jitEnabled)
- jitMenuItem.setAttribute("checked", jitEnabled? "true" : "false");
+function toggleJITState(jitMenuItem, jittype) {
+ let scope = (document.getElementById("mandelbrotWindow").nodeName == "page") ? "content" : "chrome";
+ let jitpref = "javascript.options." + jittype + "jit." + scope;
+ let jitEnabled = !gPref.getBoolPref(jitpref);
+ gPref.setBoolPref(jitpref, jitEnabled)
+ jitMenuItem.setAttribute("checked", jitEnabled ? "true" : "false");
}
function updateAlgoMenu() {
toOpenWindowByType("global:console", "chrome://global/content/console.xul");
}
+function initImgSettings() {
+ // Get values from prefs.
+ for each (let coord in ["Cr_min", "Cr_max", "Ci_min", "Ci_max"]) {
+ document.getElementById("is_" + coord).value =
+ roundCoord(parseFloat(gPref.getCharPref("mandelbrot.last_image." + coord)));
+ }
+ for each (let dim in ["width", "height"]) {
+ document.getElementById("is_img_" + dim).value =
+ gPref.getIntPref("mandelbrot.image." + dim);
+ }
+ document.getElementById("is_syncProp").checked =
+ gPref.getBoolPref("mandelbrot.syncProportions");
+
+ // Calculate scales.
+ recalcCoord("Cr", "scale");
+ recalcCoord("Ci", "scale");
+
+ // Clear the preview.
+ let canvas = document.getElementById("is_mbrotPreview");
+ let context = canvas.getContext("2d");
+ context.fillStyle = "rgba(255, 255, 255, 127)";
+ context.fillRect(0, 0, canvas.width, canvas.height);
+}
+
+function closeImgSettings() {
+ // Hide popup, which will automatically make a call to save values.
+ document.getElementById("imgSettingsPanel").hidePopup();
+}
+
+function saveImgSettings() {
+ // Get values to prefs.
+ for each (let coord in ["Cr_min", "Cr_max", "Ci_min", "Ci_max"]) {
+ gPref.setCharPref("mandelbrot.last_image." + coord,
+ document.getElementById("is_" + coord).value);
+ }
+ for each (let dim in ["width", "height"]) {
+ gPref.setIntPref("mandelbrot.image." + dim,
+ document.getElementById("is_img_" + dim).value);
+ }
+ gPref.setBoolPref("mandelbrot.syncProportions",
+ document.getElementById("is_syncProp").checked);
+}
+
+function checkISValue(textbox, type) {
+ if (type == "coord") {
+ textbox.value = roundCoord(parseFloat(textbox.value));
+ }
+ else if (type == "dim") {
+ textbox.value = parseInt(textbox.value);
+ }
+}
+
+function drawPreview() {
+ let canvas = document.getElementById("is_mbrotPreview");
+ let context = canvas.getContext("2d");
+
+ if (document.getElementById("is_img_width").value /
+ document.getElementById("is_img_height").value
+ < 80 / 50) {
+ canvas.height = 50;
+ canvas.width = canvas.height *
+ document.getElementById("is_img_width").value /
+ document.getElementById("is_img_height").value;
+ }
+ else {
+ canvas.width = 80;
+ canvas.height = canvas.width *
+ document.getElementById("is_imgHeight").value /
+ document.getElementById("is_imgWidth").value;
+ }
+
+ let Cr_min = parseFloat(document.getElementById("is_Cr_min").value);
+ let Cr_max = parseFloat(document.getElementById("is_Cr_max").value);
+ if ((Cr_min < -2) || (Cr_min > 2) ||
+ (Cr_max < -2) || (Cr_max > 2) || (Cr_min >= Cr_max)) {
+ Cr_min = -2.0; Cr_max = 1.0;
+ }
+
+ let Ci_min = parseFloat(document.getElementById("is_Ci_min").value);
+ let Ci_max = parseFloat(document.getElementById("is_Ci_max").value);
+ if ((Ci_min < -2) || (Ci_min > 2) ||
+ (Ci_max < -2) || (Ci_max > 2) || (Ci_min >= Ci_max)) {
+ Ci_min = -2.0; Ci_max = 1.0;
+ }
+
+ let iterMax = gPref.getIntPref("mandelbrot.iteration_max");
+ let algorithm = gPref.getCharPref("mandelbrot.use_algorithm");
+
+ context.fillStyle = "rgba(255, 255, 255, 127)";
+ context.fillRect(0, 0, canvas.width, canvas.height);
+
+ try {
+ var currentPalette = gPref.getCharPref("mandelbrot.color_palette");
+ }
+ catch(e) {
+ var currentPalette = "";
+ }
+ if (!currentPalette.length) {
+ currentPalette = "kairo";
+ }
+ gColorPalette = getColorPalette(currentPalette);
+
+ drawLine(0, [Cr_min, Cr_max, Ci_min, Ci_max],
+ canvas, context, iterMax, algorithm);
+}
+
+function recalcCoord(coord, target) {
+ let othercoord = (coord == "Ci") ? "Cr" : "Ci";
+ let owndim = (coord == "Ci") ? "height" : "width";
+ let otherdim = (coord == "Ci") ? "width" : "height";
+ if (target == "scale") {
+ var myscale =
+ parseFloat(document.getElementById("is_" + coord + "_max").value) -
+ parseFloat(document.getElementById("is_" + coord + "_min").value);
+ document.getElementById("is_" + coord + "_scale").value = roundCoord(myscale);
+ }
+ else if (target == 'max') {
+ let mymax =
+ parseFloat(document.getElementById("is_" + coord + "_min").value) +
+ parseFloat(document.getElementById("is_" + coord + "_scale").value);
+ document.getElementById("is_" + coord + "_max").value = roundCoord(mymax);
+ var myscale = document.getElementById("is_" + coord + "_scale").value;
+ }
+ if (document.getElementById("is_syncProp").checked) {
+ let otherscale = myscale *
+ document.getElementById("is_img_" + otherdim).value /
+ document.getElementById("is_img_" + owndim).value;
+ document.getElementById("is_" + othercoord + "_scale").value = roundCoord(otherscale);
+ let othermax =
+ parseFloat(document.getElementById("is_" + othercoord + "_min").value) +
+ parseFloat(document.getElementById("is_" + othercoord + "_scale").value);
+ document.getElementById("is_" + othercoord + "_max").value = roundCoord(othermax);
+ }
+}
+
+function checkProportions() {
+ if (!document.getElementById("is_syncProp").checked) {
+ recalcCoord("Cr", "scale");
+ }
+}
+
+function roundCoord(floatval) {
+ // We should round to 10 decimals here or so
+ return parseFloat(floatval.toFixed(10));
+}
+
/***** helper functions from external sources *****/
// function below is based on http://developer.mozilla.org/en/docs/Code_snippets:Canvas