Partially implement B&W mode

main
Isaiah Odhner 2017-06-24 06:22:29 +00:00
parent 2aec89d0a2
commit 949b18d23b
5 changed files with 130 additions and 13 deletions

View File

@ -7,8 +7,8 @@
* Link-esque things
* Popups (I'd probably make the text within the popups selectable)
* Related topics (I'd probably make this a heading with links instead of the weird context menu thing)
* Note unsupported features
* "To use black and white instead of color"
* Note unsupported features (or just implement these)
* "To use black and white instead of color" (partially implemented)
* "To display gridlines"
* Update topics
* "To use a picture as the desktop background":
@ -23,7 +23,6 @@
* Add topics
* In "Tips and Tricks" (which is just a lame section)
* Transparency
* Replace "To use black and white instead of color"?
* Multiplayer / collaboration / "To share the document On-Line" or whatever
* Index
* Search

View File

@ -11,6 +11,8 @@ function $ColorBox(){
var $background_color = $(E("div")).addClass("color-selection");
$current_colors.append($background_color, $foreground_color);
// TODO: show patterns when selected
// TODO: show black outline all around when displaying patterns
$current_colors.css({
position: "relative",
});
@ -38,14 +40,31 @@ function $ColorBox(){
$G.triggerHandler("option-changed");
});
// the only color editted by Colors > Edit Colors...
// the one color editted by "Edit Colors..."
var $last_fg_color_button;
// TODO: un-hardcode.. or "softcode" this
var button_width = 16;
var swatch_canvas_width = 13;
var build_palette = function(){
$palette.empty();
$.each(palette, function(i, color){
var $b = $(E("div")).addClass("color-button");
$b.appendTo($palette);
$b.css("background-color", color);
var swatch_canvas = new Canvas();
$(swatch_canvas).css({pointerEvents: "none"}).appendTo($b);
// $b.css("background-color", color);
var update_swatch_canvas = function(){
swatch_canvas.width = swatch_canvas_width;
swatch_canvas.height = swatch_canvas_width;
// swatch_canvas.width = $b.innerWidth();
// swatch_canvas.height = $b.innerHeight();
swatch_canvas.ctx.fillStyle = color;
swatch_canvas.ctx.fillRect(0, 0, swatch_canvas.width, swatch_canvas.height);
};
update_swatch_canvas();
// the last foreground color button starts out as the first one
if(i === 0){
@ -56,14 +75,15 @@ function $ColorBox(){
$i.appendTo($b);
$i.on("change", function(){
color = $i.val();
$b.css("background-color", color);
// $b.css("background-color", color);
update_swatch_canvas();
set_color(color);
});
$i.css("opacity", 0);
$i.prop("enabled", false);
$i.val(rgb2hex($b.css("background-color")));
$i.val(rgb2hex(color));
var button, ctrl;
$b.on("pointerdown", function(e){
@ -73,9 +93,9 @@ function $ColorBox(){
$last_fg_color_button = $b;
}
set_color($b.css("background-color"));
set_color(color);
$i.val(rgb2hex($b.css("background-color")));
$i.val(rgb2hex(color));
$i.prop("enabled", true);
setTimeout(function(){
@ -104,6 +124,9 @@ function $ColorBox(){
$G.trigger("option-changed");
};
function rgb2hex(col){
if(!col.match){ // i.e. CanvasPattern
return "#000000";
}
var rgb = col.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x){
return ("0" + parseInt(x).toString(16)).slice(-2);
@ -111,7 +134,6 @@ function $ColorBox(){
return rgb ? ("#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3])) : col;
}
});
var button_width = 16;
$palette.width(Math.ceil(palette.length/2) * button_width);
};
build_palette();

View File

@ -1,6 +1,7 @@
var aliasing = true;
var transparency = false;
var monochrome = false;
var magnification = 1;

View File

@ -557,6 +557,77 @@ function detect_transparency(){
}
}
function make_monochrome_pattern(lightness){
var dither_threshold_table = Array.from({length: 64}, function(undef, p){
var q = p ^ (p >> 3);
return (
((p & 4) >> 2) | ((q & 4) >> 1) |
((p & 2) << 1) | ((q & 2) << 2) |
((p & 1) << 4) | ((q & 1) << 5)
) / 64;
});
var pattern_canvas = document.createElement("canvas");
var pattern_ctx = pattern_canvas.getContext("2d");
pattern_canvas.width = 8;
pattern_canvas.height = 8;
var pattern_image_data = ctx.createImageData(pattern_canvas.width, pattern_canvas.height);
// for(var i = 0, px_i = 0; i < pattern_image_data.data.length; i += 4, px_i += 1){
// // var px_white = (px_i % lightness_index) == 0;
// // var px_white = Math.random() < lightness;
// // var px_white = ((px_i * lightness) % 2 * lightness) > lightness;
// var px_white = Math.sin(px_i) * lightness < lightness;
// pattern_image_data.data[i + 0] = px_white * 255;
// pattern_image_data.data[i + 1] = px_white * 255;
// pattern_image_data.data[i + 2] = px_white * 255;
// pattern_image_data.data[i + 3] = 255;
// }
for(var x = 0; x < pattern_canvas.width; x += 1){
for(var y = 0; y < pattern_canvas.width; y += 1){
var map_value = dither_threshold_table[(x & 7) + ((y & 7) << 3)];
var px_white = lightness > map_value;
var index = ((y * pattern_image_data.height) + x) * 4;
pattern_image_data.data[index + 0] = px_white * 255;
pattern_image_data.data[index + 1] = px_white * 255;
pattern_image_data.data[index + 2] = px_white * 255;
pattern_image_data.data[index + 3] = 255;
}
}
pattern_ctx.putImageData(pattern_image_data, 0, 0);
return ctx.createPattern(pattern_canvas, "repeat");
}
function switch_to_monochrome(){
// TODO: maybe *offer* to convert the existing image to monochrome
// (offer as opposed to forcing it)
palette = [];
// var n_colors = 28;
// for(var i=0; i<n_colors; i++){
// var lightness = i / n_colors;
// palette[i] = make_monochrome_pattern(lightness);
// }
var n_colors_per_row = 14;
var n_colors = n_colors_per_row * 2;
for(var i=0; i<n_colors_per_row; i++){
var lightness = i / n_colors;
palette.push(make_monochrome_pattern(lightness));
}
for(var i=0; i<n_colors_per_row; i++){
var lightness = 1 - i / n_colors;
palette.push(make_monochrome_pattern(lightness));
}
$colorbox.rebuild_palette();
reset_colors();
}
function image_attributes(){
if(image_attributes.$window){
image_attributes.$window.close();
@ -617,6 +688,11 @@ function image_attributes(){
current_unit = new_unit;
}).triggerHandler("change");
var $colors = $(E("fieldset")).appendTo($main).append('<legend>Colors</legend>');
$colors.append('<label><input type="radio" name="colors" value="monochrome">Black and White</label>');
$colors.append('<label><input type="radio" name="colors" value="polychrome">Color</label>');
$colors.find("[value=" + (monochrome ? "monochrome" : "polychrome") + "]").attr({checked: true});
var $transparency = $(E("fieldset")).appendTo($main).append('<legend>Transparency</legend>');
$transparency.append('<label><input type="radio" name="transparency" value="transparent">Transparent</label>');
$transparency.append('<label><input type="radio" name="transparency" value="opaque">Opaque</label>');
@ -625,11 +701,19 @@ function image_attributes(){
// Buttons on the right
$w.$Button("Okay", function(){
var to = $transparency.find(":checked").val();
var transparency_option = $transparency.find(":checked").val();
var colors_option = $colors.find(":checked").val();
var unit = $units.find(":checked").val();
var was_monochrome = monochrome;
image_attributes.unit = unit;
transparency = (to == "transparent");
transparency = (transparency_option == "transparent");
monochrome = (colors_option == "monochrome");
if(monochrome && !was_monochrome){
switch_to_monochrome();
}
var unit_to_px = unit_sizes_in_px[unit];
var width = $width.val() * unit_to_px;

View File

@ -240,7 +240,18 @@ button.selected,
border-right: 1px solid #BBBBBB;
border-bottom: 1px solid #BBBBBB;
position: relative;
box-shadow: 1px 1px 0px black inset;
/*box-shadow: 1px 1px 0px black inset;*/
}
.current-colors:before,
.color-button:before {
content: '';
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
border-left: 1px solid black;
border-top: 1px solid black;
}
.current-colors:after,
.color-button:after {