Partially implement B&W mode
parent
2aec89d0a2
commit
949b18d23b
5
TODO.md
5
TODO.md
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
var aliasing = true;
|
||||
var transparency = false;
|
||||
var monochrome = false;
|
||||
|
||||
var magnification = 1;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue