aboutsummaryrefslogtreecommitdiff
path: root/static/js/paintbbs
diff options
context:
space:
mode:
Diffstat (limited to 'static/js/paintbbs')
-rw-r--r--static/js/paintbbs/PaintBBS-1.1.11.css535
-rw-r--r--static/js/paintbbs/PaintBBS-1.1.11.js5686
-rw-r--r--static/js/paintbbs/PaintBBS-1.3.4.css547
-rw-r--r--static/js/paintbbs/PaintBBS-1.3.4.js6171
4 files changed, 12939 insertions, 0 deletions
diff --git a/static/js/paintbbs/PaintBBS-1.1.11.css b/static/js/paintbbs/PaintBBS-1.1.11.css
new file mode 100644
index 0000000..776f63d
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.1.11.css
@@ -0,0 +1,535 @@
+.NEO {
+ margin:0;
+ line-height:18px;
+
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+
+ touch-callout: none;
+ -webkit-touch-callout: none;
+}
+
+.NEO *:active,
+.NEO *:hover {
+ cursor: default;
+}
+
+.NEO #container{
+ width: 100%;
+ height: 100%;
+ position: relative;
+ border: 1px dotted transparent;
+}
+
+.NEO #center{
+ display: table;
+ position: relative;
+ height: 100%;
+ margin: auto;
+}
+
+.NEO #toolsWrapper{
+ width: 52px;
+ display: table;
+ position:absolute;
+ top: 0;
+ right: -3px;
+}
+
+.NEO #tools{
+ width: 52px;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterContainer{
+ display:table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterWrapper{
+ padding: 0 55px 0 0;
+ position: relative;
+
+ float:right; /* なぜかChrome55でずれるので対策 */
+}
+
+.NEO #upper {
+ height:30px;
+ padding-right: 20px;
+ text-align:right;
+}
+
+.NEO #lower {
+ height:30px;
+}
+
+.NEO #painter {
+ position: relative;
+ padding: 20px 20px 20px 20px;
+}
+
+.NEO #canvas {
+ position: relative;
+ width: 300px;
+ height: 300px;
+ background-color: white;
+}
+
+.NEO #headerButtons {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+}
+
+.NEO #footerButtons {
+ position: absolute;
+ bottom: 5px;
+ left: 5px;
+}
+
+
+/*
+-----------------------
+ Modal Window
+-----------------------
+*/
+
+.NEO #pageView{
+ background-color: white;
+}
+
+.NEO #windowView{
+ z-index: 9999;
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ background-color: white;
+}
+
+/*
+-----------------------
+ Controls
+-----------------------
+*/
+
+.NEO #zoomMinus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+ margin-left:1px;
+}
+
+.NEO #zoomPlus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+}
+
+.NEO #zoomMinusWrapper {
+ position: absolute;
+ right: -20px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-align:center;
+}
+
+.NEO #zoomPlusWrapper {
+ position: absolute;
+ left: -21px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-overflow: hidden;
+ text-align:center;
+}
+
+.NEO #scrollH {
+ position: absolute;
+ left: 1px;
+ bottom: -20px;
+ width: calc(100% - 2px);
+ height: 18px;
+}
+
+.NEO #scrollV {
+ position: absolute;
+ right: -20px;
+ top: 1px;
+ width: 18px;
+ height: calc(100% - 2px);
+}
+
+.NEO #scrollH div {
+ position: absolute;
+ width: 50px;
+ height: 16px;
+}
+
+.NEO #scrollV div {
+ position: absolute;
+ width: 16px;
+ height: 50px;
+}
+
+.NEO #scrollH div:hover {}
+.NEO #scrollV div:hover {}
+
+.NEO #neoWarning {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ color: red;
+ pointer-events: none;
+ text-align: left;
+ transition: all 2s;
+}
+
+/*
+-----------------------
+ Widgets
+-----------------------
+*/
+
+.NEO .buttonOff {
+ display: inline-block;
+ border: 1px solid white;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+
+}
+
+.NEO .buttonOff:hover {}
+
+.NEO .buttonOff:active,
+.NEO .buttonOn {
+ display: inline-block;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+}
+
+.NEO .toolTipOff,
+.NEO .toolTipFixed {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid #ffffff;
+ border-left: 1px solid #ffffff;
+ border-right: 1px solid #9397b2;
+ border-bottom: 1px solid #9397b2;
+}
+
+.NEO .toolTipOn {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid #ffffff;
+ border-bottom: 1px solid #ffffff;
+}
+
+.NEO .toolTipOff canvas,
+.NEO .toolTipOn canvas,
+.NEO .toolTipFixed canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.NEO .toolTipOff .label,
+.NEO .toolTipOn .label,
+.NEO .toolTipFixed .label {
+ position: absolute;
+ bottom: -4px;
+ left: 1px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: -1px;
+}
+
+.NEO .colorTips {
+ position:relative;
+ width: 48px;
+ height: 144px;
+ padding: 0;
+ margin: 0;
+ margin-top: 4px;
+ margin-left: 0px;
+}
+
+.NEO .colorTipOff {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOff img {
+ left: 0;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorTipOn {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOn img {
+ left: -22px;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorSlider {
+ width: 48px;
+ height:13px;
+ position: relative;
+ margin-top: 3px;
+}
+
+.NEO .colorSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .colorSlider .slider {
+ position: absolute;
+ height: 100%;
+ left: 0px;
+ width: 50%;
+ background-color: #fa9696;
+ box-shadow: -1px 0 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .colorSlider .hit {
+ position:absolute;
+ width: 60px;
+ height: 13px;
+ left: -6px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .sizeSlider {
+ width: 48px;
+ height:33px;
+ position: relative;
+ margin-top: 4px;
+}
+
+.NEO .sizeSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .sizeSlider .slider {
+ position: absolute;
+ width: 100%;
+ top: 0px;
+ height: 33%;
+ background-color: #82f238;
+ box-shadow: 0 -1px 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .sizeSlider .hit {
+ position:absolute;
+ width: 48px;
+ height: 41px;
+ top: -4px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .reserveControl {
+ width: 48px;
+ height: 13px;
+ position: relative;
+}
+
+.NEO .reserveControl .reserve {
+ position: absolute;
+ width: 11px;
+ height: 8px;
+ background-color: white;
+}
+
+.NEO .layerControl {
+ width: 48px;
+ height: 20px;
+ position: relative;
+ margin-top: 6px;
+}
+
+.NEO .layerControl .bg {
+ position: absolute;
+ width: 44px;
+ height: 9px;
+ margin: 0;
+
+ top: 0px;
+ left: 2px;
+}
+
+.NEO .layerControl .line1 {
+ position: absolute;
+ width: 50px;
+ height:10px;
+ margin: 0;
+ padding: 0;
+
+ top: 0px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .line0 {
+ position: absolute;
+ width: 50px;
+ height: 10px;
+ margin: 0;
+ padding: 0;
+
+ top: 10px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .label1 {
+ position: absolute;
+ left: 2px;
+ Top: -4px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+.NEO .layerControl .label0 {
+ position: absolute;
+ left: 2px;
+ Top: 6px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+/*
+-----------------------
+ InputText
+-----------------------
+*/
+
+.NEO .inputText {
+ z-index: 100000;
+ position: absolute;
+
+ text-align: left;
+ white-space: nowrap;
+ color: #0000ff;
+
+ font-family: 'Arial';
+ padding: 1px 5px 1px 5px;
+ font-size: 32px;
+
+ line-height: 40px;
+ height: 40px;
+ min-width: 10em;
+
+ bottom: 0px;
+ left: 250px;
+
+ border: 1px solid #aaa;
+ background-color: white;
+}
+
+*[contenteditable] {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto !important;
+}
+
+#testtext {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto;
+}
+
+[contenteditable="true"]:focus {
+ outline: 1px solid #b1d6fd;
+ border: 1px solid #b1d6fd;
+}
diff --git a/static/js/paintbbs/PaintBBS-1.1.11.js b/static/js/paintbbs/PaintBBS-1.1.11.js
new file mode 100644
index 0000000..8ca50e7
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.1.11.js
@@ -0,0 +1,5686 @@
+'use strict';
+
+document.addEventListener("DOMContentLoaded", function() {
+ Neo.init();
+
+ if (!navigator.userAgent.match("Electron")) {
+ Neo.start();
+ }
+});
+
+
+var Neo = function() {};
+
+Neo.version = "1.1.11";
+Neo.painter;
+Neo.fullScreen = false;
+Neo.uploaded = false;
+
+Neo.config = {
+ width: 300,
+ height: 300,
+
+ color_bk: "#ccccff",
+ color_bk2: "#bbbbff",
+ color_tool_icon: "#e8dfae",
+ color_icon: "#ccccff",
+ color_iconselect: "#ffaaaa",
+ color_text: "#666699",
+ color_bar: "#6f6fae",
+
+ tool_color_button: "#e8dfae",
+ tool_color_button2: "#f8daaa",
+ tool_color_text: "#773333",
+ tool_color_bar: "#ddddff",
+ tool_color_frame: "#000000",
+
+ colors: [
+ "#000000", "#FFFFFF",
+ "#B47575", "#888888",
+ "#FA9696", "#C096C0",
+ "#FFB6FF", "#8080FF",
+ "#25C7C9", "#E7E58D",
+ "#E7962D", "#99CB7B",
+ "#FCECE2", "#F9DDCF"
+ ]
+};
+
+Neo.reservePen = {};
+Neo.reserveEraser = {};
+
+Neo.SLIDERTYPE_RED = 0;
+Neo.SLIDERTYPE_GREEN = 1;
+Neo.SLIDERTYPE_BLUE = 2;
+Neo.SLIDERTYPE_ALPHA = 3;
+Neo.SLIDERTYPE_SIZE = 4;
+
+document.neo = Neo;
+
+Neo.init = function() {
+ var applets = document.getElementsByTagName('applet');
+ if (applets.length == 0) {
+ applets = document.getElementsByTagName('applet-dummy');
+ }
+
+ for (var i = 0; i < applets.length; i++) {
+ var applet = applets[i];
+ var name = applet.attributes.name.value;
+ if (name == "paintbbs") {
+ Neo.applet = applet;
+ Neo.createContainer(applet);
+ Neo.initConfig(applet);
+ Neo.init2();
+ }
+ }
+};
+
+Neo.init2 = function() {
+ var pageview = document.getElementById("pageView");
+ pageview.style.width = Neo.config.applet_width + "px";
+ pageview.style.height = Neo.config.applet_height + "px";
+
+ Neo.canvas = document.getElementById("canvas");
+ Neo.container = document.getElementById("container");
+ Neo.toolsWrapper = document.getElementById("toolsWrapper");
+
+ Neo.painter = new Neo.Painter();
+ Neo.painter.build(Neo.canvas, Neo.config.width, Neo.config.height);
+
+ Neo.container.oncontextmenu = function() {return false;};
+
+ // 続きから描く
+ if (Neo.config.image_canvas) {
+ Neo.painter.loadImage(Neo.config.image_canvas);
+ }
+
+ // 描きかけの画像が見つかったとき
+ if (sessionStorage.getItem('timestamp')) {
+ setTimeout(function () {
+ if (confirm("¿Cargar datos guardados?")) {
+ Neo.painter.loadSession();
+ }
+ }, 1);
+ }
+
+ window.addEventListener("beforeunload", function(e) {
+ if (!Neo.uploaded) {
+ Neo.painter.saveSession();
+ } else {
+ Neo.painter.clearSession();
+ }
+ }, false);
+}
+
+Neo.initConfig = function(applet) {
+ if (applet) {
+ var name = applet.attributes.name.value || "neo";
+ var appletWidth = applet.attributes.width;
+ var appletHeight = applet.attributes.height;
+ if (appletWidth) Neo.config.applet_width = parseInt(appletWidth.value);
+ if (appletHeight) Neo.config.applet_height = parseInt(appletHeight.value);
+
+ var params = applet.getElementsByTagName('param');
+ for (var i = 0; i < params.length; i++) {
+ var p = params[i];
+ Neo.config[p.name] = Neo.fixConfig(p.value);
+
+ if (p.name == "image_width") Neo.config.width = parseInt(p.value);
+ if (p.name == "image_height") Neo.config.height = parseInt(p.value);
+ }
+
+ var e = document.getElementById("container");
+ Neo.config.inherit_color = Neo.getInheritColor(e);
+ if (!Neo.config.color_frame) Neo.config.color_frame = Neo.config.color_text;
+ }
+
+ Neo.config.reserves = [
+ { size:1,
+ color:"#000000", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_PEN,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:5,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:10,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ ];
+
+ Neo.reservePen = Neo.clone(Neo.config.reserves[0]);
+ Neo.reserveEraser = Neo.clone(Neo.config.reserves[1]);
+};
+
+Neo.fixConfig = function(value) {
+ // javaでは"#12345"を色として解釈するがjavascriptでは"#012345"に変換しないとだめ
+ if (value.match(/^#[0-9a-fA-F]{5}$/)) {
+ value = "#0" + value.slice(1);
+ }
+ return value;
+};
+
+Neo.initSkin = function() {
+ var sheet = document.styleSheets[0];
+ if (!sheet) {
+ var style = document.createElement("style");
+ document.head.appendChild(style); // must append before you can access sheet property
+ sheet = style.sheet;
+ }
+
+ Neo.styleSheet = sheet;
+
+ var lightBorder = Neo.multColor(Neo.config.color_icon, 1.3);
+ var darkBorder = Neo.multColor(Neo.config.color_icon, 0.7);
+ var lightBar = Neo.multColor(Neo.config.color_bar, 1.3);
+ var darkBar = Neo.multColor(Neo.config.color_bar, 0.7);
+ var bgImage = Neo.backgroundImage();
+
+ Neo.addRule(".NEO #container", "background-image", "url(" + bgImage + ")");
+ Neo.addRule(".NEO .colorSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .sizeSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label1", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label0", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOn .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOff .label", "color", Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO #toolSet", "background-color", Neo.config.color_bk);
+ Neo.addRule(".NEO #tools", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .bg", "border-bottom", "1px solid " + Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO .buttonOn", "color", Neo.config.color_text);
+ Neo.addRule(".NEO .buttonOff", "color", Neo.config.color_text);
+
+ Neo.addRule(".NEO .buttonOff", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-top", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-left", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "box-shadow", "0 0 0 1px " + Neo.config.color_icon + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:hover", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff:hover", "border-top", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "border-left", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "background-color", darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-top", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-left", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO #canvas", "border", "1px solid " + Neo.config.color_frame);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "box-shadow", "0 0 0 1px white" + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "background-color", Neo.config.color_bar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "box-shadow", "0 0 0 1px " + Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH div:hover, .NEO #scrollV div:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-top", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-left", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-right", "1px solid " + darkBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-bottom", "1px solid " + darkBar);
+
+ Neo.addRule(".NEO .toolTipOn", "background-color", Neo.multColor(Neo.config.tool_color_button, 0.7));
+ Neo.addRule(".NEO .toolTipOff", "background-color", Neo.config.tool_color_button);
+ Neo.addRule(".NEO .toolTipFixed", "background-color", Neo.config.tool_color_button2);
+
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .layerControl", "background-color", Neo.config.tool_color_bar);
+
+ Neo.addRule(".NEO .colorTipOn, .NEO .colorTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipOn, .NEO .toolTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipFixed", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .layerControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl .reserve", "border", "1px solid " + Neo.config.tool_color_frame);
+};
+
+Neo.addRule = function(selector, styleName, value, sheet) {
+ if (!sheet) sheet = Neo.styleSheet;
+ if (sheet.addRule) {
+ sheet.addRule(selector, styleName + ":" + value, sheet.rules.length);
+
+ } else if (sheet.insertRule) {
+ var rule = selector + "{" + styleName + ":" + value + "}";
+ var index = sheet.cssRules.length;
+ sheet.insertRule(rule, index);
+ }
+};
+
+Neo.getInheritColor = function(e) {
+ var result = "#000000";
+ while (e && e.style) {
+ if (e.style.color != "") {
+ result = e.style.color;
+ break;
+ }
+ if (e.attributes["text"]) {
+ result = e.attributes["text"].value;
+ break;
+ }
+ e = e.parentNode;
+ }
+ return result;
+};
+
+Neo.backgroundImage = function() {
+ var c1 = Neo.painter.getColor(Neo.config.color_bk) | 0xff000000;
+ var c2 = Neo.painter.getColor(Neo.config.color_bk2) | 0xff000000;
+ var bgCanvas = document.createElement("canvas");
+ bgCanvas.width = 16;
+ bgCanvas.height = 16;
+ var ctx = bgCanvas.getContext("2d");
+ var imageData = ctx.getImageData(0, 0, 16, 16);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ for (var y = 0; y < 16; y++) {
+ for (var x = 0; x < 16; x++) {
+ buf32[index++] = (x == 14 || y == 14) ? c2 : c1;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+ return bgCanvas.toDataURL('image/png');
+};
+
+Neo.multColor = function(c, scale) {
+ var r = Math.round(parseInt(c.substr(1, 2), 16) * scale);
+ var g = Math.round(parseInt(c.substr(3, 2), 16) * scale);
+ var b = Math.round(parseInt(c.substr(5, 2), 16) * scale);
+ r = ("0" + Math.min(Math.max(r, 0), 255).toString(16)).substr(-2);
+ g = ("0" + Math.min(Math.max(g, 0), 255).toString(16)).substr(-2);
+ b = ("0" + Math.min(Math.max(b, 0), 255).toString(16)).substr(-2);
+ return '#' + r + g + b;
+};
+
+Neo.initComponents = function() {
+ document.getElementById("copyright").innerHTML += "v" + Neo.version;
+
+ //アプレットのborderの動作をエミュレート
+ if (navigator.userAgent.search("FireFox") > -1) {
+ var container = document.getElementById("container");
+ container.addEventListener("mousedown", function(e) {
+ container.style.borderColor = Neo.config.inherit_color;
+ e.stopPropagation();
+ }, false);
+ document.addEventListener("mousedown", function(e) {
+ container.style.borderColor = 'transparent';
+ }, false);
+ }
+
+ // 投稿に失敗する可能性があるときは警告を表示する
+ Neo.showWarning();
+
+ if (Neo.styleSheet) {
+ Neo.addRule("*", "user-select", "none");
+ Neo.addRule("*", "-webkit-user-select", "none");
+ Neo.addRule("*", "-ms-user-select", "none");
+ }
+}
+
+Neo.initButtons = function() {
+ new Neo.Button().init("undo").onmouseup = function() {
+ new Neo.UndoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("redo").onmouseup = function () {
+ new Neo.RedoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("window").onmouseup = function() {
+ new Neo.WindowCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("submit").onmouseup = function() {
+ new Neo.SubmitCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("copyright").onmouseup = function() {
+ new Neo.CopyrightCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomPlus").onmouseup = function() {
+ new Neo.ZoomPlusCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomMinus").onmouseup = function() {
+ new Neo.ZoomMinusCommand(Neo.painter).execute();
+ };
+
+ Neo.fillButton = new Neo.Button().init("fill", {type:'fill'});
+
+ // toolTip
+ Neo.penTip = new Neo.PenTip().init("pen");
+ Neo.pen2Tip = new Neo.Pen2Tip().init("pen2");
+ Neo.effectTip = new Neo.EffectTip().init("effect");
+ Neo.effect2Tip = new Neo.Effect2Tip().init("effect2");
+ Neo.eraserTip = new Neo.EraserTip().init("eraser");
+ Neo.drawTip = new Neo.DrawTip().init("draw");
+ Neo.maskTip = new Neo.MaskTip().init("mask");
+
+ Neo.toolButtons = [Neo.fillButton,
+ Neo.penTip,
+ Neo.pen2Tip,
+ Neo.effectTip,
+ Neo.effect2Tip,
+ Neo.drawTip,
+ Neo.eraserTip];
+
+ // colorTip
+ for (var i = 1; i <= 14; i++) {
+ new Neo.ColorTip().init("color" + i, {index:i});
+ };
+
+ // colorSlider
+ Neo.sliders[Neo.SLIDERTYPE_RED] = new Neo.ColorSlider().init(
+ "sliderRed", {type:Neo.SLIDERTYPE_RED});
+ Neo.sliders[Neo.SLIDERTYPE_GREEN] = new Neo.ColorSlider().init(
+ "sliderGreen", {type:Neo.SLIDERTYPE_GREEN});
+ Neo.sliders[Neo.SLIDERTYPE_BLUE] = new Neo.ColorSlider().init(
+ "sliderBlue", {type:Neo.SLIDERTYPE_BLUE});
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA] = new Neo.ColorSlider().init(
+ "sliderAlpha", {type:Neo.SLIDERTYPE_ALPHA});
+
+ // sizeSlider
+ Neo.sliders[Neo.SLIDERTYPE_SIZE] = new Neo.SizeSlider().init(
+ "sliderSize", {type:Neo.SLIDERTYPE_SIZE});
+
+ // reserveControl
+ for (var i = 1; i <= 3; i++) {
+ new Neo.ReserveControl().init("reserve" + i, {index:i});
+ };
+
+ new Neo.LayerControl().init("layerControl");
+ new Neo.ScrollBarButton().init("scrollH");
+ new Neo.ScrollBarButton().init("scrollV");
+};
+
+Neo.start = function(isApp) {
+ if (!Neo.painter) return;
+
+ Neo.initSkin();
+ Neo.initComponents();
+ Neo.initButtons();
+
+ Neo.isApp = isApp;
+ if (Neo.applet) {
+ var name = Neo.applet.attributes.name.value || "paintbbs";
+ Neo.applet.outerHTML = "";
+ document[name] = Neo;
+
+ Neo.resizeCanvas();
+ Neo.container.style.visibility = "visible";
+
+ if (Neo.isApp) {
+ var ipc = require('electron').ipcRenderer;
+ ipc.sendToHost('neo-status', 'ok');
+ }
+ }
+};
+
+Neo.showWarning = function() {
+ var futaba = location.hostname.match(/2chan.net/i);
+ var samplebbs = location.hostname.match(/neo.websozai.jp/i);
+
+ var chrome = navigator.userAgent.match(/Chrome\/(\d+)/i);
+ if (chrome && chrome.length > 1) chrome = chrome[1];
+
+ var edge = navigator.userAgent.match(/Edge\/(\d+)/i);
+ if (edge && edge.length > 1) edge = edge[1];
+
+ var ms = false;
+ if (/MSIE 10/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 10
+ }
+ if (/MSIE 9/i.test(navigator.userAgent) ||
+ /rv:11.0/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 9 or 11
+ }
+
+ var str = "";
+ if (futaba || samplebbs) {
+ if (ms || (edge && edge < 15)) {
+ str = "このブラウザでは<br>投稿に失敗することがあります<br>";
+ }
+ }
+
+ // もし<PARAM NAME="neo_warning" VALUE="...">があれば表示する
+ if (Neo.config.neo_warning) {
+ str += Neo.config.neo_warning;
+ }
+
+ var warning = document.getElementById("neoWarning")
+ warning.innerHTML = str;
+ setTimeout(function() { warning.style.opacity = "0"; }, 15000);
+};
+
+/*
+-----------------------------------------------------------------------
+UIの更新
+-----------------------------------------------------------------------
+*/
+
+Neo.updateUI = function() {
+ var current = Neo.painter.tool.getToolButton();
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ if (current) {
+ if (current == toolTip) {
+ toolTip.setSelected(true);
+ toolTip.update();
+ } else {
+ toolTip.setSelected(false);
+ }
+ }
+ }
+ if (Neo.drawTip) {
+ Neo.drawTip.update();
+ }
+
+ Neo.updateUIColor(true, false);
+}
+
+Neo.updateUIColor = function(updateSlider, updateColorTip) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.update();
+ }
+
+ if (updateSlider) {
+ for (var i = 0; i < Neo.sliders.length; i++) {
+ var slider = Neo.sliders[i];
+ slider.update();
+ }
+ }
+
+ // パレットを変更するとき
+ if (updateColorTip) {
+ var colorTip = Neo.ColorTip.getCurrent();
+ if (colorTip) {
+ colorTip.setColor(Neo.painter.foregroundColor);
+ }
+ }
+};
+
+/*
+-----------------------------------------------------------------------
+リサイズ対応
+-----------------------------------------------------------------------
+*/
+
+Neo.updateWindow = function() {
+ if (Neo.fullScreen) {
+ document.getElementById("windowView").style.display = "block";
+ document.getElementById("windowView").appendChild(Neo.container);
+
+ } else {
+ document.getElementById("windowView").style.display = "none";
+ document.getElementById("pageView").appendChild(Neo.container);
+ }
+ Neo.resizeCanvas();
+};
+
+Neo.resizeCanvas = function() {
+ var appletWidth = Neo.container.clientWidth;
+ var appletHeight = Neo.container.clientHeight;
+
+ var canvasWidth = Neo.painter.canvasWidth;
+ var canvasHeight = Neo.painter.canvasHeight;
+
+ var width0 = canvasWidth * Neo.painter.zoom;
+ var height0 = canvasHeight * Neo.painter.zoom;
+
+ var width = (width0 < appletWidth - 100) ? width0 : appletWidth - 100;
+ var height = (height0 < appletHeight - 120) ? height0 : appletHeight - 120;
+
+ //width, heightは偶数でないと誤差が出るため
+ width = Math.floor(width / 2) * 2;
+ height = Math.floor(height / 2) * 2;
+
+ Neo.painter.destWidth = width;
+ Neo.painter.destHeight = height;
+
+ Neo.painter.destCanvas.width = width;
+ Neo.painter.destCanvas.height = height;
+ Neo.painter.destCanvasCtx = Neo.painter.destCanvas.getContext("2d");
+ Neo.painter.destCanvasCtx.imageSmoothingEnabled = false;
+ Neo.painter.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ Neo.canvas.style.width = width + "px";
+ Neo.canvas.style.height = height + "px";
+
+ var top = (Neo.container.clientHeight - toolsWrapper.clientHeight) / 2;
+ Neo.toolsWrapper.style.top = ((top > 0) ? top : 0) + "px";
+
+ if (top < 0) {
+ var s = Neo.container.clientHeight / toolsWrapper.clientHeight;
+ Neo.toolsWrapper.style.transform =
+ "translate(0, " + top + "px) scale(1," + s + ")";
+ } else {
+ Neo.toolsWrapper.style.transform = "";
+ }
+
+ Neo.painter.setZoom(Neo.painter.zoom);
+ Neo.painter.updateDestCanvas(0, 0, canvasWidth, canvasHeight);
+};
+
+/*
+-----------------------------------------------------------------------
+投稿
+-----------------------------------------------------------------------
+*/
+
+Neo.clone = function(src) {
+ var dst = {};
+ for (var k in src) {
+ dst[k] = src[k];
+ }
+ return dst;
+};
+
+Neo.getSizeString = function(len) {
+ var result = String(len);
+ while (result.length < 8) {
+ result = "0" + result;
+ }
+ return result;
+};
+
+Neo.openURL = function(url) {
+ if (Neo.isApp) {
+ require('electron').shell.openExternal(url);
+
+ } else {
+ location.href = url;
+ }
+};
+
+Neo.submit = function(board, blob, thumbnail, thumbnail2) {
+ var url = Neo.config.url_save;
+ console.log("submit url=" + url);
+
+ var headerString = Neo.config.send_header || "";
+ var imageType = Neo.config.send_header_image_type;
+ if (imageType && imageType == "true") {
+ headerString = "image_type=png&" + headerString
+ console.log("header=" + headerString);
+ }
+
+ var header = new Blob([headerString]);
+ var headerLength = this.getSizeString(header.size);
+ var imgLength = this.getSizeString(blob.size);
+
+ var array = ['P', // PaintBBS
+ headerLength,
+ header,
+ imgLength,
+ '\r\n',
+ blob];
+
+ if (thumbnail) {
+ var thumbnailLength = this.getSizeString(thumbnail.size);
+ array.push(thumbnailLength, thumbnail);
+ }
+ if (thumbnail2) {
+ var thumbnail2Length = this.getSizeString(thumbnail2.size);
+ array.push(thumbnail2Length, thumbnail2);
+ }
+
+ var body = new Blob(array, {type: 'application/octet-binary'}); //これが必要!!
+
+ var request = new XMLHttpRequest();
+ request.open("POST", url, true);
+
+ request.onload = function(e) {
+ console.log(request.response);
+ Neo.uploaded = true;
+
+ var url = Neo.config.url_exit;
+ /*if (url[0] == '/') {
+ url = url.replace(/^.*\//, ''); //よくわかんないけどとりあえず
+ }*/
+
+ // ふたばのpaintpost.phpは、画像投稿に成功するとresponseに
+ // "./futaba.php?mode=paintcom&amp;painttmp=.png"
+ // という文字列を返します。
+ //
+ // NEOでは、responseに文字列"painttmp="が含まれる場合は
+ // <PARAM>で指定されたurl_exitを無視して、このURLにジャンプします。
+ var responseURL = request.response.replace(/&amp;/g, '&');
+ if (responseURL.match(/painttmp=/)) {
+ url = responseURL;
+ }
+ //var exitURL = board + url;
+ var exitURL = url;
+
+ // しぃちゃんのドキュメントをよく見たら
+ // responseが "URL:〜" の形だった場合はそこへ飛ばすって書いてありました。
+ // こっちを使うべきでした……
+ if (responseURL.match(/^URL:/)) {
+ exitURL = responseURL.replace(/^URL:/, '');
+ }
+
+ location.href = exitURL;
+ };
+ request.onerror = function(e) {
+ console.log("error");
+ };
+ request.onabort = function(e) {
+ console.log("abort");
+ };
+ request.ontimeout = function(e) {
+ console.log("timeout");
+ };
+
+ if (0) { // データのデバッグのため送信するデータをuint8arrayにコピーしておく
+ var fr = new FileReader();
+ fr.onload = function () {
+ var result = fr.result;
+ }
+ fr.readAsArrayBuffer(body);
+ }
+
+ request.send(body);
+};
+
+/*
+-----------------------------------------------------------------------
+LiveConnect
+-----------------------------------------------------------------------
+*/
+
+Neo.getColors = function() {
+ console.log("getColors");
+ return Neo.config.colors.join('\n');
+};
+
+Neo.setColors = function(colors) {
+ console.log("setColors");
+ var array = colors.split('\n');
+ for (var i = 0; i < 14; i++) {
+ var color = array[i];
+ Neo.config.colors[i] = color;
+ Neo.colorTips[i].setColor(color);
+ }
+};
+
+/*
+-----------------------------------------------------------------------
+DOMツリーの作成
+-----------------------------------------------------------------------
+*/
+
+Neo.createContainer = function(applet) {
+ var neo = document.createElement("div");
+ neo.className = "NEO";
+ neo.id = "NEO";
+ neo.innerHTML = (function() {/*
+
+<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
+
+<div id="pageView" style="width:450px; height:470px; margin:auto;">
+ <div id="container" style="visibility:hidden;">
+ <div id="center">
+ <div id="painterContainer">
+ <div id="painterWrapper">
+ <div id="upper">
+ <div id="redo">Rehacer</div>
+ <div id="undo">Deshacer</div>
+ <div id="fill">Llenar</div>
+ </div>
+ <div id="painter">
+ <div id="canvas">
+ <div id="scrollH"></div>
+ <div id="scrollV"></div>
+ <div id="zoomPlusWrapper">
+ <div id="zoomPlus">+</div>
+ </div>
+ <div id="zoomMinusWrapper">
+ <div id="zoomMinus">-</div>
+ </div>
+ <div id="neoWarning"></div>
+ </div>
+ </div>
+ <div id="lower">
+ </div>
+ </div>
+ <div id="toolsWrapper">
+ <div id="tools">
+ <div id="toolSet">
+ <div id="pen"></div>
+ <div id="pen2"></div>
+ <div id="effect"></div>
+ <div id="effect2"></div>
+ <div id="eraser"></div>
+ <div id="draw"></div>
+ <div id="mask"></div>
+
+ <div class="colorTips">
+ <div id="color2"></div><div id="color1"></div><br>
+ <div id="color4"></div><div id="color3"></div><br>
+ <div id="color6"></div><div id="color5"></div><br>
+ <div id="color8"></div><div id="color7"></div><br>
+ <div id="color10"></div><div id="color9"></div><br>
+ <div id="color12"></div><div id="color11"></div><br>
+ <div id="color14"></div><div id="color13"></div>
+ </div>
+
+ <div id="sliderRed"></div>
+ <div id="sliderGreen"></div>
+ <div id="sliderBlue"></div>
+ <div id="sliderAlpha"></div>
+ <div id="sliderSize"></div>
+
+ <div class="reserveControl" style="margin-top:4px;">
+ <div id="reserve1"></div>
+ <div id="reserve2"></div>
+ <div id="reserve3"></div>
+ </div>
+ <div id="layerControl" style="margin-top:6px;"></div>
+
+ <!--<div id="toolPad" style="height:20px;"></div>-->
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="headerButtons">
+ <div id="window">Ventana</div>
+ </div>
+ <div id="footerButtons">
+ <div id="submit">Enviar</div>
+ <div id="copyright">(C)しいちゃん PaintBBS NEO</div>
+ </div>
+ </div>
+</div>
+
+<div id="windowView" style="display: none;">
+
+</div>
+
+
+*/}).toString().match(/\/\*([^]*)\*\//)[1];
+
+ var parent = applet.parentNode;
+ parent.appendChild(neo);
+ parent.insertBefore(neo, applet);
+
+// applet.style.display = "none";
+
+ // NEOを組み込んだURLをアプリ版で開くとDOMツリーが2重にできて格好悪いので消しておく
+ setTimeout(function() {
+ var tmp = document.getElementsByClassName("NEO");
+ if (tmp.length > 1) {
+ for (var i = 1; i < tmp.length; i++) {
+ tmp[i].style.display = "none";
+ }
+ }
+ }, 0);
+};
+
+
+'use strict';
+
+Neo.Painter = function() {
+ this._undoMgr = new Neo.UndoManager(50);
+};
+
+Neo.Painter.prototype.container;
+Neo.Painter.prototype._undoMgr;
+Neo.Painter.prototype.tool;
+Neo.Painter.prototype.inputText;
+
+//Canvas Info
+Neo.Painter.prototype.canvasWidth;
+Neo.Painter.prototype.canvasHeight;
+Neo.Painter.prototype.canvas = [];
+Neo.Painter.prototype.canvasCtx = [];
+Neo.Painter.prototype.visible = [];
+Neo.Painter.prototype.current = 0;
+
+//Temp Canvas Info
+Neo.Painter.prototype.tempCanvas;
+Neo.Painter.prototype.tempCanvasCtx;
+Neo.Painter.prototype.tempX = 0;
+Neo.Painter.prototype.tempY = 0;
+
+//Destination Canvas for display
+Neo.Painter.prototype.destCanvas;
+Neo.Painter.prototype.destCanvasCtx;
+
+
+Neo.Painter.prototype.backgroundColor = "#ffffff";
+Neo.Painter.prototype.foregroundColor = "#000000";
+
+Neo.Painter.prototype.lineWidth = 1;
+Neo.Painter.prototype.alpha = 1;
+Neo.Painter.prototype.zoom = 1;
+Neo.Painter.prototype.zoomX = 0;
+Neo.Painter.prototype.zoomY = 0;
+
+Neo.Painter.prototype.isMouseDown;
+Neo.Painter.prototype.isMouseDownRight;
+Neo.Painter.prototype.prevMouseX;
+Neo.Painter.prototype.prevMouseY;
+Neo.Painter.prototype.mouseX;
+Neo.Painter.prototype.mouseY;
+
+Neo.Painter.prototype.slowX = 0;
+Neo.Painter.prototype.slowY = 0;
+Neo.Painter.prototype.stab = null;
+
+Neo.Painter.prototype.isShiftDown = false;
+Neo.Painter.prototype.isCtrlDown = false;
+Neo.Painter.prototype.isAltDown = false;
+
+//Neo.Painter.prototype.onUpdateCanvas;
+Neo.Painter.prototype._roundData = [];
+Neo.Painter.prototype._toneData = [];
+Neo.Painter.prototype.toolStack = [];
+
+Neo.Painter.prototype.maskType = 0;
+Neo.Painter.prototype.drawType = 0;
+Neo.Painter.prototype.maskColor = "#000000";
+Neo.Painter.prototype._currentColor = [];
+Neo.Painter.prototype._currentMask = [];
+
+Neo.Painter.prototype.aerr;
+
+Neo.Painter.LINETYPE_NONE = 0;
+Neo.Painter.LINETYPE_PEN = 1;
+Neo.Painter.LINETYPE_ERASER = 2;
+Neo.Painter.LINETYPE_BRUSH = 3;
+Neo.Painter.LINETYPE_TONE = 4;
+Neo.Painter.LINETYPE_DODGE = 5;
+Neo.Painter.LINETYPE_BURN = 6;
+
+Neo.Painter.MASKTYPE_NONE = 0;
+Neo.Painter.MASKTYPE_NORMAL = 1;
+Neo.Painter.MASKTYPE_REVERSE = 2;
+Neo.Painter.MASKTYPE_ADD = 3;
+Neo.Painter.MASKTYPE_SUB = 4;
+
+Neo.Painter.DRAWTYPE_FREEHAND = 0;
+Neo.Painter.DRAWTYPE_LINE = 1;
+Neo.Painter.DRAWTYPE_BEZIER = 2;
+
+Neo.Painter.ALPHATYPE_NONE = 0;
+Neo.Painter.ALPHATYPE_PEN = 1;
+Neo.Painter.ALPHATYPE_FILL = 2;
+Neo.Painter.ALPHATYPE_BRUSH = 3;
+
+Neo.Painter.TOOLTYPE_NONE = 0;
+Neo.Painter.TOOLTYPE_PEN = 1;
+Neo.Painter.TOOLTYPE_ERASER = 2;
+Neo.Painter.TOOLTYPE_HAND = 3;
+Neo.Painter.TOOLTYPE_SLIDER = 4;
+Neo.Painter.TOOLTYPE_FILL = 5;
+Neo.Painter.TOOLTYPE_MASK = 6;
+Neo.Painter.TOOLTYPE_ERASEALL = 7;
+Neo.Painter.TOOLTYPE_ERASERECT = 8;
+Neo.Painter.TOOLTYPE_COPY = 9;
+Neo.Painter.TOOLTYPE_PASTE = 10;
+Neo.Painter.TOOLTYPE_MERGE = 11;
+Neo.Painter.TOOLTYPE_FLIP_H = 12;
+Neo.Painter.TOOLTYPE_FLIP_V = 13;
+
+Neo.Painter.TOOLTYPE_BRUSH = 14;
+Neo.Painter.TOOLTYPE_TEXT = 15;
+Neo.Painter.TOOLTYPE_TONE = 16;
+Neo.Painter.TOOLTYPE_BLUR = 17;
+Neo.Painter.TOOLTYPE_DODGE = 18;
+Neo.Painter.TOOLTYPE_BURN = 19;
+Neo.Painter.TOOLTYPE_RECT = 20;
+Neo.Painter.TOOLTYPE_RECTFILL = 21;
+Neo.Painter.TOOLTYPE_ELLIPSE = 22;
+Neo.Painter.TOOLTYPE_ELLIPSEFILL = 23;
+Neo.Painter.TOOLTYPE_BLURRECT = 24;
+Neo.Painter.TOOLTYPE_TURN = 25;
+
+Neo.Painter.prototype.build = function(div, width, height)
+{
+ this.container = div;
+ this._initCanvas(div, width, height);
+ this._initRoundData();
+ this._initToneData();
+ this._initInputText();
+
+ this.setTool(new Neo.PenTool());
+
+};
+
+Neo.Painter.prototype.setTool = function(tool) {
+ if (this.tool && this.tool.saveStates) this.tool.saveStates();
+
+ if (this.tool && this.tool.kill) {
+ this.tool.kill();
+ }
+ this.tool = tool;
+ tool.init();
+ if (this.tool && this.tool.loadStates) this.tool.loadStates();
+};
+
+Neo.Painter.prototype.pushTool = function(tool) {
+ this.toolStack.push(this.tool);
+ this.tool = tool;
+ tool.init();
+};
+
+Neo.Painter.prototype.popTool = function() {
+ var tool = this.tool;
+ if (tool && tool.kill) {
+ tool.kill();
+ }
+ this.tool = this.toolStack.pop();
+};
+
+Neo.Painter.prototype.getCurrentTool = function() {
+ if (this.tool) {
+ var tool = this.tool;
+ if (tool && tool.type == Neo.Painter.TOOLTYPE_SLIDER) {
+ var stack = this.toolStack;
+ if (stack.length > 0) {
+ tool = stack[stack.length - 1];
+ }
+ }
+ return tool;
+ }
+ return null;
+};
+
+Neo.Painter.prototype.setToolByType = function(toolType) {
+ switch (parseInt(toolType)) {
+ case Neo.Painter.TOOLTYPE_PEN: this.setTool(new Neo.PenTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASER: this.setTool(new Neo.EraserTool()); break;
+ case Neo.Painter.TOOLTYPE_HAND: this.setTool(new Neo.HandTool()); break;
+ case Neo.Painter.TOOLTYPE_FILL: this.setTool(new Neo.FillTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASEALL: this.setTool(new Neo.EraseAllTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASERECT: this.setTool(new Neo.EraseRectTool()); break;
+
+ case Neo.Painter.TOOLTYPE_COPY: this.setTool(new Neo.CopyTool()); break;
+ case Neo.Painter.TOOLTYPE_PASTE: this.setTool(new Neo.PasteTool()); break;
+ case Neo.Painter.TOOLTYPE_MERGE: this.setTool(new Neo.MergeTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_H: this.setTool(new Neo.FlipHTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_V: this.setTool(new Neo.FlipVTool()); break;
+
+ case Neo.Painter.TOOLTYPE_BRUSH: this.setTool(new Neo.BrushTool()); break;
+ case Neo.Painter.TOOLTYPE_TEXT: this.setTool(new Neo.TextTool()); break;
+ case Neo.Painter.TOOLTYPE_TONE: this.setTool(new Neo.ToneTool()); break;
+ case Neo.Painter.TOOLTYPE_BLUR: this.setTool(new Neo.BlurTool()); break;
+ case Neo.Painter.TOOLTYPE_DODGE: this.setTool(new Neo.DodgeTool()); break;
+ case Neo.Painter.TOOLTYPE_BURN: this.setTool(new Neo.BurnTool()); break;
+
+ case Neo.Painter.TOOLTYPE_RECT: this.setTool(new Neo.RectTool()); break;
+ case Neo.Painter.TOOLTYPE_RECTFILL: this.setTool(new Neo.RectFillTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSE: this.setTool(new Neo.EllipseTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:this.setTool(new Neo.EllipseFillTool()); break;
+ case Neo.Painter.TOOLTYPE_BLURRECT: this.setTool(new Neo.BlurRectTool()); break;
+ case Neo.Painter.TOOLTYPE_TURN: this.setTool(new Neo.TurnTool()); break;
+
+ default:
+ console.log("unknown toolType " + toolType);
+ break;
+ }
+};
+
+Neo.Painter.prototype._initCanvas = function(div, width, height) {
+ width = parseInt(width);
+ height = parseInt(height);
+ var destWidth = parseInt(div.clientWidth);
+ var destHeight = parseInt(div.clientHeight);
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.canvasWidth = width;
+ this.canvasHeight = height;
+ this.zoomX = width * 0.5;
+ this.zoomY = height * 0.5;
+
+ for (var i = 0; i < 2; i++) {
+ this.canvas[i] = document.createElement("canvas");
+ this.canvas[i].width = width;
+ this.canvas[i].height = height;
+ this.canvasCtx[i] = this.canvas[i].getContext("2d");
+
+ this.canvas[i].style.imageRendering = "pixelated";
+ this.canvasCtx[i].imageSmoothingEnabled = false;
+ this.canvasCtx[i].mozImageSmoothingEnabled = false;
+ this.visible[i] = true;
+ }
+
+ this.tempCanvas = document.createElement("canvas");
+ this.tempCanvas.width = width;
+ this.tempCanvas.height = height;
+ this.tempCanvasCtx = this.tempCanvas.getContext("2d");
+ this.tempCanvas.style.position = "absolute";
+ this.tempCanvas.enabled = false;
+
+ var array = this.container.getElementsByTagName("canvas");
+ if (array.length > 0) {
+ this.destCanvas = array[0];
+ } else {
+ this.destCanvas = document.createElement("canvas");
+ this.container.appendChild(this.destCanvas);
+ }
+
+ this.destCanvasCtx = this.destCanvas.getContext("2d");
+ this.destCanvas.width = destWidth;
+ this.destCanvas.height = destHeight;
+
+ this.destCanvas.style.imageRendering = "pixelated";
+ this.destCanvasCtx.imageSmoothingEnabled = false;
+ this.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ var ref = this;
+
+ var container = document.getElementById("container");
+
+ if (window.PointerEvent) {
+ container.addEventListener("pointerdown", function(e) {
+ ref._mouseDownHandler(e); });
+ container.addEventListener("pointerup", function(e) {
+ ref._mouseUpHandler(e); });
+ container.addEventListener("pointermove", function(e) {
+ ref._mouseMoveHandler(e); });
+ container.addEventListener("pointerover", function(e) {
+ ref._rollOverHandler(e); });
+ container.addEventListener("pointerout", function(e) {
+ ref._rollOutHandler(e); });
+
+ } else {
+ container.onmousedown = function(e) {ref._mouseDownHandler(e)};
+ container.onmousemove = function(e) {ref._mouseMoveHandler(e)};
+ container.onmouseup = function(e) {ref._mouseUpHandler(e)};
+ container.onmouseover = function(e) {ref._rollOverHandler(e)};
+ container.onmouseout = function(e) {ref._rollOutHandler(e)};
+
+ container.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ }, true);
+ container.addEventListener("touchmove", function(e) {
+ ref._mouseMoveHandler(e);
+ }, true);
+ container.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+ }
+
+ document.onkeydown = function(e) {ref._keyDownHandler(e)};
+ document.onkeyup = function(e) {ref._keyUpHandler(e)};
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype._initRoundData = function() {
+ for (var r = 1; r <= 30; r++) {
+ this._roundData[r] = new Uint8Array(r * r);
+ var mask = this._roundData[r];
+ var d = Math.floor(r / 2.0);
+ var index = 0;
+ for (var x = 0; x < r; x++) {
+ for (var y = 0; y < r; y++) {
+ var xx = x + 0.5 - r/2.0;
+ var yy = y + 0.5 - r/2.0;
+ mask[index++] = (xx*xx + yy*yy <= r*r/4) ? 1 : 0;
+ }
+ }
+ }
+ this._roundData[3][0] = 0;
+ this._roundData[3][2] = 0;
+ this._roundData[3][6] = 0;
+ this._roundData[3][8] = 0;
+
+ this._roundData[5][1] = 0;
+ this._roundData[5][3] = 0;
+ this._roundData[5][5] = 0;
+ this._roundData[5][9] = 0;
+ this._roundData[5][15] = 0;
+ this._roundData[5][19] = 0;
+ this._roundData[5][21] = 0;
+ this._roundData[5][23] = 0;
+};
+
+Neo.Painter.prototype._initToneData = function() {
+ var pattern = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
+
+ for (var i = 0; i < 16; i++) {
+ this._toneData[i] = new Uint8Array(16);
+ for (var j = 0; j < 16; j++) {
+ this._toneData[i][j] = (i >= pattern[j]) ? 1 : 0;
+ }
+ }
+};
+
+Neo.Painter.prototype.getToneData = function(alpha) {
+ var alphaTable = [23,
+ 47,
+ 69,
+ 92,
+ 114,
+ 114,
+ 114,
+ 138,
+ 161,
+ 184,
+ 184,
+ 207,
+ 230,
+ 230,
+ 253,
+ ];
+
+ for (var i = 0; i < alphaTable.length; i++) {
+ if (alpha < alphaTable[i]) {
+ return this._toneData[i];
+ }
+ }
+ return this._toneData[i];
+};
+
+Neo.Painter.prototype._initInputText = function() {
+ var text = document.getElementById("inputtext");
+ if (!text) {
+ text = document.createElement("div");
+ }
+
+ text.id = "inputext";
+ text.setAttribute("contentEditable", true);
+ text.spellcheck = false;
+ text.className = "inputText";
+ text.innerHTML = "";
+
+ text.style.display = "none";
+// text.style.userSelect = "none";
+ Neo.painter.container.appendChild(text);
+ this.inputText = text;
+
+ this.updateInputText();
+};
+
+Neo.Painter.prototype.hideInputText = function() {
+ var text = this.inputText;
+ text.blur();
+ text.style.display = "none";
+};
+
+Neo.Painter.prototype.updateInputText = function() {
+ var text = this.inputText;
+ var d = this.lineWidth;
+ var fontSize = Math.round(d * 55/28 + 7);
+ var height = Math.round(d * 68/28 + 12);
+
+ text.style.fontSize = fontSize + "px";
+ text.style.lineHeight = fontSize + "px";
+ text.style.height = fontSize + "px";
+ text.style.marginTop = -fontSize + "px";
+};
+
+/*
+-----------------------------------------------------------------------
+ Mouse Event Handling
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype._keyDownHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = true;
+
+ if (!this.isShiftDown && this.isCtrlDown) {
+ if (!this.isAltDown) {
+ if (e.keyCode == 90 || e.keyCode == 85) this.undo(); //Ctrl+Z,Ctrl.U
+ if (e.keyCode == 89) this.redo(); //Ctrl+Y
+ } else {
+ if (e.keyCode == 90) this.redo(); //Ctrl+Alt+Z
+ }
+ }
+
+ if (!this.isShiftDown && !this.isCtrlDown && !this.isAltDown) {
+ if (e.keyCode == 107) new Neo.ZoomPlusCommand(this).execute(); // +
+ if (e.keyCode == 109) new Neo.ZoomMinusCommand(this).execute(); // -
+ }
+
+ if (this.tool.keyDownHandler) {
+ this.tool.keyDownHandler(e);
+ }
+
+ //スペース・Shift+スペースででスクロールしないように
+ if (document.activeElement != this.inputText) e.preventDefault();
+};
+
+Neo.Painter.prototype._keyUpHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = false;
+
+ if (this.tool.keyUpHandler) {
+ this.tool.keyUpHandler(oe);
+ }
+};
+
+Neo.Painter.prototype._rollOverHandler = function(e) {
+ if (this.tool.rollOverHandler) {
+ this.tool.rollOverHandler(this);
+ }
+};
+
+Neo.Painter.prototype._rollOutHandler = function(e) {
+ if (this.tool.rollOutHandler) {
+ this.tool.rollOutHandler(this);
+ }
+};
+
+Neo.Painter.prototype._mouseDownHandler = function(e) {
+ if (e.target == Neo.painter.destCanvas) {
+ //よくわからないがChromeでドラッグの時カレットが出るのを防ぐ
+ //http://stackoverflow.com/questions/2745028/chrome-sets-cursor-to-text-while-dragging-why
+ e.preventDefault();
+ }
+
+ if (e.button == 2) {
+ this.isMouseDownRight = true;
+
+ } else {
+ if (!e.shiftKey && e.ctrlKey && e.altKey) {
+ this.isMouseDown = true;
+
+ } else {
+ if (e.ctrlKey || e.altKey) {
+ this.isMouseDownRight = true;
+ } else {
+ this.isMouseDown = true;
+ }
+ }
+ }
+
+ this._updateMousePosition(e);
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+
+ if (this.isMouseDownRight) {
+ this.isMouseDownRight = false;
+ if (!this.isWidget(e.target)) {
+ this.pickColor(this.mouseX, this.mouseY);
+ return;
+ }
+ }
+
+ if (!this.isUIPaused()) {
+ if (e.target['data-bar']) {
+ this.pushTool(new Neo.HandTool());
+
+ } else if (this.isSpaceDown && document.activeElement != this.inputText) {
+ this.pushTool(new Neo.HandTool());
+ this.tool.reverse = true;
+
+ } else if (e.target['data-slider'] != undefined) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = e.target;
+
+ } else if (e.ctrlKey && e.altKey && !e.shiftKey) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = Neo.sliders[Neo.SLIDERTYPE_SIZE].element;
+ this.tool.alt = true;
+
+ } else if (this.isWidget(e.target)) {
+ this.isMouseDown = false;
+ this.pushTool(new Neo.DummyTool());
+ }
+ }
+ this.tool.downHandler(this);
+
+ var ref = this;
+ document.onmouseup = function(e) {
+ ref._mouseUpHandler(e)
+ };
+};
+
+Neo.Painter.prototype._mouseUpHandler = function(e) {
+ this.isMouseDown = false;
+ this.isMouseDownRight = false;
+ this.tool.upHandler(this);
+ document.onmouseup = undefined;
+};
+
+Neo.Painter.prototype._mouseMoveHandler = function(e) {
+ this._updateMousePosition(e);
+
+ if (this.isMouseDown || this.isMouseDownRight) {
+ this.tool.moveHandler(this);
+ } else {
+ if (this.tool.upMoveHandler) {
+ this.tool.upMoveHandler(this);
+ }
+ }
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+};
+
+
+Neo.Painter.prototype._updateMousePosition = function(e) {
+ var rect = this.destCanvas.getBoundingClientRect();
+ var x = (e.clientX !== undefined) ? e.clientX : e.touches[0].clientX;
+ var y = (e.clientY !== undefined) ? e.clientY : e.touches[0].clientY;
+
+ if (this.zoom <= 0) this.zoom = 1; //なぜか0になることがあるので
+
+ this.mouseX = (x - rect.left) / this.zoom
+ + this.zoomX
+ - this.destCanvas.width * 0.5 / this.zoom;
+ this.mouseY = (y - rect.top) / this.zoom
+ + this.zoomY
+ - this.destCanvas.height * 0.5 / this.zoom;
+
+ if (isNaN(this.prevMouseX)) {
+ this.prevMouseX = this.mouseX;
+ }
+ if (isNaN(this.prevMouseY)) {
+ this.prevMosueY = this.mouseY;
+ }
+
+ this.slowX = this.slowX * 0.8 + this.mouseX * 0.2;
+ this.slowY = this.slowY * 0.8 + this.mouseY * 0.2;
+ var now = new Date().getTime();
+ if (this.stab) {
+ var pause = this.stab[3];
+ if (pause) {
+ // ポーズ中
+ if (now > pause) {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ } else {
+ // ポーズされていないとき
+ var prev = this.stab[2];
+ if (now - prev > 150) { // 150ms以上止まっていたらポーズをオンにする
+ this.stab[3] = now + 200 // 200msペンの位置を固定
+
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+ }
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ this.rawMouseX = x;
+ this.rawMouseY = y;
+ this.clipMouseX = Math.max(Math.min(this.canvasWidth, this.mouseX), 0);
+ this.clipMouseY = Math.max(Math.min(this.canvasHeight, this.mouseY), 0);
+};
+
+Neo.Painter.prototype._beforeUnloadHandler = function(e) {
+ // quick save
+};
+
+Neo.Painter.prototype.getStabilized = function() {
+ return this.stab;
+};
+
+/*
+-------------------------------------------------------------------------
+ Undo
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.undo = function() {
+ var undoItem = this._undoMgr.popUndo();
+ if (undoItem) {
+ this._pushRedo();
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.redo = function() {
+ var undoItem = this._undoMgr.popRedo();
+ if (undoItem) {
+ this._pushUndo(0,0,this.canvasWidth, this.canvasHeight, true);
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.hasUndo = function() {
+ return true;
+};
+
+Neo.Painter.prototype._pushUndo = function(x, y, w, h, holdRedo) {
+ x = (x == undefined) ? 0 : x;
+ y = (y == undefined) ? 0 : y;
+ w = (w == undefined) ? this.canvasWidth : w;
+ h = (h == undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushUndo(undoItem, holdRedo);
+};
+
+Neo.Painter.prototype._pushRedo = function(x, y, w, h) {
+ x = (x == undefined) ? 0 : x;
+ y = (y == undefined) ? 0 : y;
+ w = (w == undefined) ? this.canvasWidth : w;
+ h = (h == undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushRedo(undoItem);
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Data Cache for Undo / Redo
+-------------------------------------------------------------------------
+*/
+
+Neo.UndoManager = function(_maxStep){
+ this._maxStep = _maxStep;
+ this._undoItems = [];
+ this._redoItems = [];
+}
+Neo.UndoManager.prototype._maxStep;
+Neo.UndoManager.prototype._redoItems;
+Neo.UndoManager.prototype._undoItems;
+
+//アクションをしてUndo情報を更新
+Neo.UndoManager.prototype.pushUndo = function(undoItem, holdRedo) {
+ this._undoItems.push(undoItem);
+ if (this._undoItems.length > this._maxStep) {
+ this._undoItems.shift();
+ }
+
+ if (!holdRedo == true) {
+ this._redoItems = [];
+ }
+};
+
+Neo.UndoManager.prototype.popUndo = function() {
+ return this._undoItems.pop();
+}
+
+Neo.UndoManager.prototype.pushRedo = function(undoItem) {
+ this._redoItems.push(undoItem);
+}
+
+Neo.UndoManager.prototype.popRedo = function() {
+ return this._redoItems.pop();
+}
+
+
+Neo.UndoItem = function() {}
+Neo.UndoItem.prototype.data;
+Neo.UndoItem.prototype.x;
+Neo.UndoItem.prototype.y;
+Neo.UndoItem.prototype.width;
+Neo.UndoItem.prototype.height;
+
+/*
+-------------------------------------------------------------------------
+ Zoom Controller
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.setZoom = function(value) {
+ this.zoom = value;
+
+ var container = document.getElementById("container");
+ var width = this.canvasWidth * this.zoom;
+ var height = this.canvasHeight * this.zoom;
+ if (width > container.clientWidth - 100) width = container.clientWidth - 100;
+ if (height > container.clientHeight - 130) height = container.clientHeight - 130;
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight, false);
+ this.setZoomPosition(this.zoomX, this.zoomY);
+};
+
+Neo.Painter.prototype.setZoomPosition = function(x, y) {
+ var minx = (this.destCanvas.width / this.zoom) * 0.5;
+ var maxx = this.canvasWidth - minx;
+ var miny = (this.destCanvas.height / this.zoom) * 0.5;
+ var maxy = this.canvasHeight - miny;
+
+
+ x = Math.round(Math.max(Math.min(maxx,x),minx));
+ y = Math.round(Math.max(Math.min(maxy,y),miny));
+
+ this.zoomX = x;
+ this.zoomY = y;
+ this.updateDestCanvas(0,0,this.canvasWidth,this.canvasHeight,false);
+
+ this.scrollBarX = (maxx == minx) ? 0 : (x - minx) / (maxx - minx);
+ this.scrollBarY = (maxy == miny) ? 0 : (y - miny) / (maxy - miny);
+ this.scrollWidth = maxx - minx;
+ this.scrollHeight = maxy - miny;
+
+ if (Neo.scrollH) Neo.scrollH.update(this);
+ if (Neo.scrollV) Neo.scrollV.update(this);
+
+ this.hideInputText();
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Drawing Helper
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.submit = function(board) {
+ var thumbnail = null;
+ var thumbnail2 = null;
+
+ if (this.useThumbnail()) {
+ thumbnail = this.getThumbnail(Neo.config.thumbnail_type || "png");
+ if (Neo.config.thumbnail_type2) {
+ thumbnail2 = this.getThumbnail(Neo.config.thumbnail_type2);
+ }
+ }
+ Neo.submit(board, this.getPNG(), thumbnail2, thumbnail);
+};
+
+Neo.Painter.prototype.useThumbnail = function() {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth && thumbnailHeight) {
+ if (thumbnailWidth < this.canvasWidth ||
+ thumbnailHeight < this.canvasHeight) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.dataURLtoBlob = function(dataURL) {
+ var byteString;
+ if (dataURL.split(',')[0].indexOf('base64') >= 0) {
+ byteString = atob(dataURL.split(',')[1]);
+ } else {
+ byteString = unescape(dataURL.split(',')[1]);
+ }
+
+ // write the bytes of the string to a typed array
+ var ia = new Uint8Array(byteString.length);
+ for (var i = 0; i < byteString.length; i++) {
+ ia[i] = byteString.charCodeAt(i);
+ }
+ return new Blob([ia], {type:'image/png'});
+};
+
+Neo.Painter.prototype.getImage = function(imageWidth, imageHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ imageWidth = imageWidth || width;
+ imageHeight = imageHeight || height;
+
+ var pngCanvas = document.createElement("canvas");
+ pngCanvas.width = imageWidth;
+ pngCanvas.height = imageHeight;
+ var pngCanvasCtx = pngCanvas.getContext("2d");
+ pngCanvasCtx.fillStyle = "#ffffff";
+ pngCanvasCtx.fillRect(0, 0, imageWidth, imageHeight);
+
+ if (this.visible[0]) {
+ pngCanvasCtx.drawImage(this.canvas[0],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ if (this.visible[1]) {
+ pngCanvasCtx.drawImage(this.canvas[1],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ return pngCanvas;
+};
+
+Neo.Painter.prototype.getPNG = function() {
+ var image = this.getImage();
+ var dataURL = image.toDataURL('image/png');
+ return this.dataURLtoBlob(dataURL);
+};
+
+Neo.Painter.prototype.getThumbnail = function(type) {
+ if (type != "animation") {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth || thumbnailHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ if (thumbnailWidth == 0) {
+ thumbnailWidth = thumbnailHeight * width / height;
+ }
+ if (thumbnailHeight == 0) {
+ thumbnailHeight = thumbnailWidth * height / width;
+ }
+ } else {
+ thumbnailWidth = thumbnailHeight = null;
+ }
+
+ console.log("get thumbnail", thumbnailWidth, thumbnailHeight);
+
+ var image = this.getImage(thumbnailWidth, thumbnailHeight);
+ var dataURL = image.toDataURL('image/' + type);
+ return this.dataURLtoBlob(dataURL);
+
+ } else {
+ return new Blob([]); //animationには対応していないのでダミーデータを返す
+ }
+};
+
+Neo.Painter.prototype.getThumbnailWidth = function() {
+ var width = Neo.config.thumbnail_width;
+ if (width) {
+ if (width.match(/%$/)) {
+ return Math.floor(this.canvasWidth * (parseInt(width) / 100.0));
+ } else {
+ return parseInt(width);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.getThumbnailHeight = function() {
+ var height = Neo.config.thumbnail_height;
+ if (height) {
+ if (height.match(/%$/)) {
+ return Math.floor(this.canvasHeight * (parseInt(height) / 100.0));
+ } else {
+ return parseInt(height);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.clearCanvas = function(doConfirm) {
+ if (!doConfirm || confirm("Borrar todo")) {
+ //Register undo first;
+ this._pushUndo();
+
+ this.canvasCtx[0].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.canvasCtx[1].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+ }
+};
+
+Neo.Painter.prototype.updateDestCanvas = function(x, y, width, height, useTemp) {
+ var canvasWidth = this.canvasWidth;
+ var canvasHeight = this.canvasHeight;
+ var updateAll = false;
+ if (x == 0 && y == 0 && width == canvasWidth && height == canvasHeight) {
+ updateAll = true;
+ };
+
+ if (x + width > this.canvasWidth) width = this.canvasWidth - x;
+ if (y + height > this.canvasHeight) height = this.canvasHeight - y;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (width <= 0 || height <= 0) return;
+
+ var ctx = this.destCanvasCtx;
+ ctx.save();
+ ctx.fillStyle = "#ffffff";
+
+ if (updateAll) {
+ ctx.fillRect(0, 0, this.destCanvas.width, this.destCanvas.height);
+ } else {
+ //カーソルの描画ゴミが残るのをごまかすため
+ if (x + width == this.canvasWidth) width++;
+ if (y + height == this.canvasHeight) height++;
+ }
+
+ ctx.translate(this.destCanvas.width*.5, this.destCanvas.height*.5);
+ ctx.scale(this.zoom, this.zoom);
+ ctx.translate(-this.zoomX, -this.zoomY);
+ ctx.globalAlpha = 1.0;
+ ctx.msImageSmoothingEnabled = 0;
+
+ if (!updateAll) {
+ ctx.fillRect(x, y, width, height);
+ }
+
+ if (this.visible[0]) {
+ ctx.drawImage(this.canvas[0],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (this.visible[1]) {
+ ctx.drawImage(this.canvas[1],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (useTemp) {
+ ctx.globalAlpha = 1.0; //this.alpha;
+ ctx.drawImage(this.tempCanvas,
+ x, y, width, height,
+ x + this.tempX, y + this.tempY, width, height);
+ }
+ ctx.restore();
+};
+
+Neo.Painter.prototype.getBound = function(x0, y0, x1, y1, r) {
+ var left = Math.floor((x0 < x1) ? x0 : x1);
+ var top = Math.floor((y0 < y1) ? y0 : y1);
+ var width = Math.ceil(Math.abs(x0 - x1));
+ var height = Math.ceil(Math.abs(y0 - y1));
+ r = Math.ceil(r + 1);
+
+ if (!r) {
+ width += 1;
+ height += 1;
+
+ } else {
+ left -= r;
+ top -= r;
+ width += r * 2;
+ height += r * 2;
+ }
+ return [left, top, width, height];
+};
+
+Neo.Painter.prototype.getColor = function(c) {
+ if (!c) c = this.foregroundColor;
+ var r = parseInt(c.substr(1, 2), 16);
+ var g = parseInt(c.substr(3, 2), 16);
+ var b = parseInt(c.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+ return a <<24 | b<<16 | g<<8 | r;
+};
+
+Neo.Painter.prototype.getColorString = function(c) {
+ var rgb = ("000000" + (c & 0xffffff).toString(16)).substr(-6);
+ return '#' + rgb;
+};
+
+Neo.Painter.prototype.setColor = function(c) {
+ if (typeof c != "string") c = this.getColorString(c);
+ this.foregroundColor = c;
+
+ Neo.updateUI();
+};
+
+Neo.Painter.prototype.getAlpha = function(type) {
+ var a1 = this.alpha;
+
+ switch (type) {
+ case Neo.Painter.ALPHATYPE_PEN:
+ if (a1 > 0.5) {
+ a1 = 1.0/16 + (a1 - 0.5) * 30.0/16;
+ } else {
+ a1 = Math.sqrt(2 * a1) / 16.0;
+ }
+ a1 = Math.min(1, Math.max(0, a1));
+ break;
+
+ case Neo.Painter.ALPHATYPE_FILL:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1 * 10));
+ break;
+
+ case Neo.Painter.ALPHATYPE_BRUSH:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1));
+ break;
+ }
+
+ // アルファが小さい時は適当に点を抜いて見た目の濃度を合わせる
+ if (a1 < 1.0/255) {
+ this.aerr += a1;
+ a1 = 0;
+ while (this.aerr > 1.0/255) {
+ a1 = 1.0/255;
+ this.aerr -= 1.0/255;
+ }
+ }
+ return a1;
+};
+
+Neo.Painter.prototype.prepareDrawing = function () {
+ var r = parseInt(this.foregroundColor.substr(1, 2), 16);
+ var g = parseInt(this.foregroundColor.substr(3, 2), 16);
+ var b = parseInt(this.foregroundColor.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+
+ var maskR = parseInt(this.maskColor.substr(1, 2), 16);
+ var maskG = parseInt(this.maskColor.substr(3, 2), 16);
+ var maskB = parseInt(this.maskColor.substr(5, 2), 16);
+
+ this._currentColor = [r, g, b, a];
+ this._currentMask = [maskR, maskG, maskB];
+};
+
+Neo.Painter.prototype.isMasked = function (buf8, index) {
+ var r = this._currentMask[0];
+ var g = this._currentMask[1];
+ var b = this._currentMask[2];
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3];
+
+ if (a0 == 0) {
+ r0 = 0xff;
+ g0 = 0xff;
+ b0 = 0xff;
+ }
+
+ var type = this.maskType;
+
+ //TODO
+ //いろいろ試したのですが半透明で描画するときの加算・逆加算を再現する方法がわかりません。
+ //とりあえず単純に無視しています。
+ if (type == Neo.Painter.MASKTYPE_ADD ||
+ type == Neo.Painter.MASKTYPE_SUB) {
+ if (this._currentColor[3] < 250) {
+ type = Neo.Painter.MASKTYPE_NONE;
+ }
+ }
+
+ switch (type) {
+ case Neo.Painter.MASKTYPE_NONE:
+ return;
+
+ case Neo.Painter.MASKTYPE_NORMAL:
+ return (r0 == r &&
+ g0 == g &&
+ b0 == b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_REVERSE:
+ return (r0 != r ||
+ g0 != g ||
+ b0 != b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_ADD:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] < this._currentColor[c]) return true;
+ }
+ return false;
+
+ } else {
+ return false;
+ }
+
+ case Neo.Painter.MASKTYPE_SUB:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] > this._currentColor[c]) return true;
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+};
+
+Neo.Painter.prototype.setPoint = function(buf8, bufWidth, x0, y0, left, top, type) {
+ var x = x0 - left;
+ var y = y0 - top;
+
+ switch (type) {
+ case Neo.Painter.LINETYPE_PEN:
+ this.setPenPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BRUSH:
+ this.setBrushPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_TONE:
+ this.setTonePoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_ERASER:
+ this.setEraserPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BLUR:
+ this.setBlurPoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_DODGE:
+ this.setDodgePoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BURN:
+ this.setBurnPoint(buf8, bufWidth, x, y);
+ break;
+
+ default:
+ break;
+ }
+};
+
+
+Neo.Painter.prototype.setPenPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_PEN);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0 * (1 - a1x)) / a;
+ var g = (g1 * a1x + g0 * a0 * (1 - a1x)) / a;
+ var b = (b1 * a1x + b0 * a0 * (1 - a1x)) / a;
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBrushPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0) / (a0 + a1x);
+ var g = (g1 * a1x + g0 * a0) / (a0 + a1x);
+ var b = (b1 * a1x + b0 * a0) / (a0 + a1x);
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setTonePoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ if (r0%2) { x0++; y0++; } //なぜか模様がずれるので
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+
+ var r = this._currentColor[0];
+ var g = this._currentColor[1];
+ var b = this._currentColor[2];
+ var a = this._currentColor[3];
+
+ var toneData = this.getToneData(a);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ if (toneData[((y0+i)%4) + (((x0+j)%4) * 4)]) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = 255;
+ }
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setEraserPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+ var a = Math.floor(this.alpha * 255);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var k = (buf8[index + 3] / 255.0) * (1.0 - (a / 255.0));
+
+ buf8[index + 3] -= a / (d * (255.0 - a) / 255.0);
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBlurPoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var height = buf8.length / (width * 4);
+
+// var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ var a1 = this.alpha / 12;
+ if (a1 == 0) return;
+ var blur = a1;
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) {
+ tmp[i] = buf8[i];
+ }
+
+ var left = x0 - x - r0;
+ var top = y0 - y - r0;
+
+ var xstart = 0, xend = d;
+ var ystart = 0, yend = d;
+ if (xstart > left) xstart = -left;
+ if (ystart > top) ystart = -top;
+ if (xend > this.canvasWidth - left) xend = this.canvasWidth - left;
+ if (yend > this.canvasHeight - top) yend = this.canvasHeight - top;
+
+ for (var j = ystart; j < yend; j++) {
+ var index = (j * width + xstart) * 4;
+ for (var i = xstart; i < xend; i++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+ if (i > xstart) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < xend - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > ystart) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < yend - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.round((rgba[3] / rgba[4]) * 255.0);
+ }
+ index += 4;
+ }
+ }
+};
+
+Neo.Painter.prototype.setDodgePoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = r0 * 255 / (255 - a1);
+ var g1 = g0 * 255 / (255 - a1);
+ var b1 = b0 * 255 / (255 - a1);
+ } else {
+ var r1 = 255.0;
+ var g1 = 255.0;
+ var b1 = 255.0;
+ }
+
+ var r = Math.ceil(r1);
+ var g = Math.ceil(g1);
+ var b = Math.ceil(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBurnPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = 255 - (255 - r0) * 255 / (255 - a1);
+ var g1 = 255 - (255 - g0) * 255 / (255 - a1);
+ var b1 = 255 - (255 - b0) * 255 / (255 - a1);
+ } else {
+ var r1 = 0;
+ var g1 = 0;
+ var b1 = 0;
+ }
+
+ var r = Math.floor(r1);
+ var g = Math.floor(g1);
+ var b = Math.floor(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+
+Neo.Painter.prototype.xorPixel = function(buf32, bufWidth, x, y, c) {
+ var index = y * bufWidth + x;
+ if (!c) c = 0xffffff;
+ buf32[index] ^= c;
+};
+
+Neo.Painter.prototype.getBezierPoint = function(t, x0, y0, x1, y1, x2, y2, x3, y3) {
+ var a0 = (1 - t) * (1 - t) * (1 - t);
+ var a1 = (1 - t) * (1 - t) * t * 3;
+ var a2 = (1 - t) * t * t * 3;
+ var a3 = t * t * t;
+
+ var x = x0 * a0 + x1 * a1 + x2 * a2 + x3 * a3;
+ var y = y0 * a0 + y1 * a1 + y2 * a2 + y3 * a3;
+ return [x, y];
+};
+
+var nmax = 1;
+
+Neo.Painter.prototype.drawBezier = function(ctx, x0, y0, x1, y1, x2, y2, x3, y3, type) {
+ var xmax = Math.max(x0, x1, x2, x3);
+ var xmin = Math.min(x0, x1, x2, x3);
+ var ymax = Math.max(y0, y1, y2, y3);
+ var ymin = Math.min(y0, y1, y2, y3);
+ var n = Math.ceil(((xmax - xmin) + (ymax - ymin)) * 2.5);
+
+ if (n > nmax) {
+ n = (n < nmax * 2) ? n : nmax * 2;
+ nmax = n;
+ }
+
+ for (var i = 0; i < n; i++) {
+ var t = i * 1.0 / n;
+ var p = this.getBezierPoint(t, x0, y0, x1, y1, x2, y2, x3, y3);
+ this.drawPoint(ctx, p[0], p[1], type);
+ }
+};
+
+Neo.Painter.prototype.prevLine = null; // 始点または終点が2度プロットされることがあるので
+Neo.Painter.prototype.drawLine = function(ctx, x0, y0, x1, y1, type) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+ var prev = [x0, y0, x1, y1];
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+ var r = Math.ceil(this.lineWidth / 2);
+
+ var left = ((x0 < x1) ? x0 : x1) - r;
+ var top = ((y0 < y1) ? y0 : y1) - r;
+
+ var imageData = ctx.getImageData(left, top, width + r*2, height + r*2);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+ this.aerr = 0;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+ this.setPoint(buf8, imageData.width, x0, y0, left, top, type);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+
+ this.prevLine = prev;
+};
+
+Neo.Painter.prototype.drawPoint = function(ctx, x, y, type) {
+ this.drawLine(ctx, x, y, x, y, type);
+};
+
+Neo.Painter.prototype.xorRect = function(buf32, bufWidth, x, y, width, height, c) {
+ var index = y * bufWidth + x;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ buf32[index] ^= c;
+ index++;
+ }
+ index += width - bufWidth;
+ }
+};
+
+Neo.Painter.prototype.drawXORRect = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ if (!c) c = 0xffffff;
+
+ if (isFill) {
+ this.xorRect(buf32, width, 0, 0, width, height, c);
+
+ } else {
+ for (var i = 0; i < width; i++) { //top
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ if (height > 1) {
+ index = width;
+ for (var i = 1; i < height; i++) { //left
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ if (width > 1) {
+ index = width * 2 - 1;
+ for (var i = 1; i < height - 1; i++) { //right
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ index = width * (height - 1) + 1;
+ for (var i = 1; i < width; i++) { // bottom
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXOREllipse = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+ if (!c) c = 0xffffff;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+
+ var a = width-1, b = height-1, b1 = b&1; /* values of diameter */
+ var dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
+ var err = dx+dy+b1*a*a, e2; /* error of 1.step */
+
+ var x0 = x;
+ var y0 = y;
+ var x1 = x0+a;
+ var y1 = y0+b;
+
+ if (x0 > x1) { x0 = x1; x1 += a; }
+ if (y0 > y1) y0 = y1;
+ y0 += Math.floor((b+1)/2); y1 = y0-b1; /* starting pixel */
+ a *= 8*a; b1 = 8*b*b;
+ var ymin = y0 - 1;
+
+ do {
+ if (isFill) {
+ if (ymin < y0) {
+ this.xorRect(buf32, width, x0-x, y0 - y, x1 - x0, 1, c);
+ if (y0 != y1) {
+ this.xorRect(buf32, width, x0-x, y1 - y, x1 - x0, 1, c);
+ }
+ ymin = y0;
+ }
+ } else {
+ this.xorPixel(buf32, width, x1-x, y0-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x0-x, y0-y, c);
+ }
+ if (y0 != y1) {
+ this.xorPixel(buf32, width, x0-x, y1-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x1-x, y1-y, c);
+ }
+ }
+ }
+ e2 = 2*err;
+ if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
+ if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
+ } while (x0 <= x1);
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXORLine = function(ctx, x0, y0, x1, y1, c) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+
+ var left = ((x0 < x1) ? x0 : x1);
+ var top = ((y0 < y1) ? y0 : y1);
+// console.log("left:"+left+" top:"+top+" width:"+width+" height:"+height);
+
+ var imageData = ctx.getImageData(left, top, width + 1, height + 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+
+ this.xorPixel(buf32, imageData.width, x0 - left, y0 - top, c);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+};
+
+
+Neo.Painter.prototype.eraseRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var a = 1.0 - this.alpha;
+ if (a != 0) {
+ a = Math.ceil(2.0 / a);
+ } else {
+ a = 255;
+ }
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (!this.isMasked(buf8, index)) {
+ buf8[index + 3] -= a;
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipH = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(width / 2);
+ for (var j = 0; j < height; j++) {
+ var index = j * width;
+ var index2 = index + (width - 1);
+ for (var i = 0; i < half; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 -i];
+ buf32[index2 - i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipV = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(height / 2);
+ for (var j = 0; j < half; j++) {
+ var index = j * width;
+ var index2 = (height - 1 - j) * width;
+ for (var i = 0; i < width; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 + i];
+ buf32[index2 + i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.merge = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = [];
+ var buf32 = [];
+ var buf8 = [];
+ for (var i = 0; i < 2; i++) {
+ imageData[i] = this.canvasCtx[i].getImageData(x, y, width, height);
+ buf32[i] = new Uint32Array(imageData[i].data.buffer);
+ buf8[i] = new Uint8ClampedArray(imageData[i].data.buffer);
+ }
+
+ var dst = this.current;
+ var src = (dst == 1) ? 0 : 1;
+ var size = width * height;
+ var index = 0;
+ for (var i = 0; i < size; i++) {
+ var r0 = buf8[0][index + 0];
+ var g0 = buf8[0][index + 1];
+ var b0 = buf8[0][index + 2];
+ var a0 = buf8[0][index + 3] / 255.0;
+ var r1 = buf8[1][index + 0];
+ var g1 = buf8[1][index + 1];
+ var b1 = buf8[1][index + 2];
+ var a1 = buf8[1][index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var r = Math.floor((r1 * a1 + r0 * a0 * (1 - a1)) / a + 0.5);
+ var g = Math.floor((g1 * a1 + g0 * a0 * (1 - a1)) / a + 0.5);
+ var b = Math.floor((b1 * a1 + b0 * a0 * (1 - a1)) / a + 0.5);
+ }
+ buf8[src][index + 0] = 0;
+ buf8[src][index + 1] = 0;
+ buf8[src][index + 2] = 0;
+ buf8[src][index + 3] = 0;
+ buf8[dst][index + 0] = r;
+ buf8[dst][index + 1] = g;
+ buf8[dst][index + 2] = b;
+ buf8[dst][index + 3] = Math.floor(a * 255 + 0.5);
+ index += 4;
+ }
+
+ for (var i = 0; i < 2; i++) {
+ imageData[i].data.set(buf8[i]);
+ this.canvasCtx[i].putImageData(imageData[i], x, y);
+ }
+};
+
+Neo.Painter.prototype.blurRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) tmp[i] = buf8[i];
+
+ var index = 0;
+ var a1 = this.alpha / 12;
+ var blur = a1;
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+
+ if (i > 0) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < width - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > 0) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < height - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ var w = rgba[4];
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.ceil((rgba[3] / w) * 255.0);
+
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.addBlur = function(buffer, index, a, rgba) {
+ var r0 = rgba[0];
+ var g0 = rgba[1];
+ var b0 = rgba[2];
+ var a0 = rgba[3];
+ var r1 = buffer[index + 0];
+ var g1 = buffer[index + 1];
+ var b1 = buffer[index + 2];
+ var a1 = (buffer[index + 3] / 255.0) * a;
+ rgba[4] += a;
+
+ var a = a0 + a1;
+ if (a > 0) {
+ rgba[0] = (r1 * a1 + r0 * a0) / (a0 + a1);
+ rgba[1] = (g1 * a1 + g0 * a0) / (a0 + a1);
+ rgba[2] = (b1 * a1 + b0 * a0) / (a0 + a1);
+ rgba[3] = a;
+ }
+};
+
+Neo.Painter.prototype.pickColor = function(x, y) {
+ var r = 0xff, g = 0xff, b = 0xff, a;
+
+ x = Math.floor(x);
+ y = Math.floor(y);
+ if (x >= 0 && x < this.canvasWidth &&
+ y >= 0 && y < this.canvasHeight) {
+
+ for (var i = 0; i < 2; i++) {
+ if (this.visible[i]) {
+ var ctx = this.canvasCtx[i];
+ var imageData = ctx.getImageData(x, y, 1, 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var a = buf8[3] / 255.0;
+ r = r * (1.0 - a) + buf8[2] * a;
+ g = g * (1.0 - a) + buf8[1] * a;
+ b = b * (1.0 - a) + buf8[0] * a;
+ }
+ }
+ r = Math.max(Math.min(Math.round(r), 255), 0);
+ g = Math.max(Math.min(Math.round(g), 255), 0);
+ b = Math.max(Math.min(Math.round(b), 255), 0);
+ var result = r | g<<8 | b<<16;
+ }
+ this.setColor(result);
+
+
+ if (this.current > 0) {
+ if (a == 0 && (result == 0xffffff || this.getEmulationMode() < 2.16)) {
+ this.setToolByType(Neo.eraserTip.tools[Neo.eraserTip.mode]);
+
+ } else {
+ if (Neo.eraserTip.selected) {
+ this.setToolByType(Neo.penTip.tools[Neo.penTip.mode]);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.fillHorizontalLine = function(buf32, x0, x1, y) {
+ var index = y * this.canvasWidth + x0;
+ var fillColor = this.getColor();
+ for (var x = x0; x <= x1; x++) {
+ buf32[index++] = fillColor;
+ }
+};
+
+Neo.Painter.prototype.scanLine = function(x0, x1, y, baseColor, buf32, stack) {
+ var width = this.canvasWidth;
+
+ while (x0 <= x1) {
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] == baseColor) break;
+ }
+ if (x1 < x0) break;
+
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] != baseColor) break;
+ }
+ stack.push({x:x0 - 1, y: y})
+ }
+};
+
+Neo.Painter.prototype.fill = function(x, y, ctx) {
+ // http://sandbox.serendip.ws/javascript_canvas_scanline_seedfill.html
+ x = Math.round(x);
+ y = Math.round(y);
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var width = imageData.width;
+ var stack = [{x: x, y: y}];
+
+ var baseColor = buf32[y * width + x];
+ var fillColor = this.getColor();
+
+ if ((baseColor & 0xffffff00) == 0 ||
+ (baseColor & 0xffffff) != (fillColor & 0xffffff)) {
+ while (stack.length > 0) {
+ var point = stack.pop();
+ var x0 = point.x;
+ var x1 = point.x;
+ var y = point.y;
+
+ if (buf32[y * width + x] == fillColor)
+ break;
+
+ for (; 0 < x0; x0--) {
+ if (buf32[y * width + (x0 - 1)] != baseColor) break;
+ }
+ for (; x1 < this.canvasHeight - 1; x1++) {
+ if (buf32[y * width + (x1 + 1)] != baseColor) break;
+ }
+ this.fillHorizontalLine(buf32, x0, x1, y);
+
+ if (y + 1 < this.canvasHeight) {
+ this.scanLine(x0, x1, y + 1, baseColor, buf32, stack);
+ }
+ if (y - 1 >= 0) {
+ this.scanLine(x0, x1, y - 1, baseColor, buf32, stack);
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.copy = function(x, y, width, height) {
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+
+ var imageData = this.canvasCtx[this.current].getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ this.temp = new Uint32Array(buf32.length);
+ for (var i = 0; i < buf32.length; i++) {
+ this.temp[i] = buf32[i];
+ }
+
+ //tempCanvasに乗せる画像を作る
+ imageData = this.tempCanvasCtx.getImageData(x, y, width, height);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ if (this.temp[i] >> 24) {
+ buf32[i] = this.temp[i] | 0xff000000;
+ } else {
+ buf32[i] = 0xffffffff;
+ }
+ }
+ imageData.data.set(buf8);
+ this.tempCanvasCtx.putImageData(imageData, x, y);
+};
+
+
+Neo.Painter.prototype.paste = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+// console.log(this.tempX, this.tempY);
+
+ var imageData = ctx.getImageData(x + this.tempX, y + this.tempY, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ buf32[i] = this.temp[i];
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x + this.tempX, y + this.tempY);
+
+ this.temp = null;
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.turn = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+
+ // 傾けツールのバグを再現するため一番上のラインで対象領域を埋める
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var temp = new Uint32Array(buf32.length);
+
+ var index = 0;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ temp[index] = buf32[index];
+ if (index >= width) {
+ buf32[index] = buf32[index % width];
+ }
+ index++;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+
+ // 90度回転させて貼り付け
+ imageData = ctx.getImageData(x, y, height, width);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ index = 0;
+ for (var j = height - 1; j >= 0; j--) {
+ for (var i = 0; i < width; i++) {
+ buf32[i * height + j] = temp[index++];
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.doFill = function(ctx, x, y, width, height, maskFunc) {
+ if (Math.round(x) != x) console.log("*");
+ if (Math.round(width) != width) console.log("*");
+ if (Math.round(height) != height) console.log("*");
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.ALPHATYPE_FILL);
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (maskFunc && maskFunc.call(this, i, j, width, height)) {
+ //なぜか加算逆加算は適用されない
+ if (this.maskType >= Neo.Painter.MASKTYPE_ADD ||
+ !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+
+ if (a > 0) {
+ var a1x = a1;
+ var ax = 1 + a0 * (1 - a1x);
+
+ var r = (r1 + r0 * a0 * (1 - a1x)) / ax;
+ var g = (g1 + g0 * a0 * (1 - a1x)) / ax;
+ var b = (b1 + b0 * a0 * (1 - a1x)) / ax
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+ }
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.rectFillMask = function(x, y, width, height) {
+ return true;
+};
+
+Neo.Painter.prototype.rectMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ return (x < d || x > width - 1 - d ||
+ y < d || y > height - 1 - d) ? true : false;
+};
+
+Neo.Painter.prototype.ellipseFillMask = function(x, y, width, height) {
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ return ((x * x) + (y * y) < 1) ? true : false;
+}
+
+Neo.Painter.prototype.ellipseMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+
+ if (cx <= d || cy <= d) return this.ellipseFillMask(x, y, width, height);
+
+ var x2 = (x - cx) / (cx - d + 1);
+ var y2 = (y - cy) / (cy - d + 1);
+
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ if ((x * x) + (y * y) < 1) {
+ if ((x2 * x2) + (y2 * y2) >= 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.getDestCanvasPosition = function(mx, my, isClip, isCenter) {
+ var mx = Math.floor(mx); //Math.round(mx);
+ var my = Math.floor(my); //Math.round(my);
+ if (isCenter) {
+ mx += 0.499;
+ my += 0.499;
+ }
+ var x = (mx - this.zoomX + this.destCanvas.width * 0.5 / this.zoom) * this.zoom;
+ var y = (my - this.zoomY + this.destCanvas.height * 0.5 / this.zoom) * this.zoom;
+
+ if (isClip) {
+ x = Math.max(Math.min(x, this.destCanvas.width), 0);
+ y = Math.max(Math.min(y, this.destCanvas.height), 0);
+ }
+ return {x:x, y:y};
+};
+
+Neo.Painter.prototype.isWidget = function(element) {
+ while (1) {
+ if (element == null ||
+ element.id == "canvas" ||
+ element.id == "container") break;
+
+ if (element.id == "tools" ||
+ element.className == "buttonOn" ||
+ element.className == "buttonOff" ||
+ element.className == "inputText") {
+ return true;
+ }
+ element = element.parentNode;
+ }
+ return false;
+};
+
+
+Neo.Painter.prototype.loadImage = function (filename) {
+ console.log("loadImage " + filename);
+ var img = new Image();
+ img.src = filename;
+ img.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].drawImage(img, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ };
+}
+
+Neo.Painter.prototype.loadSession = function (filename) {
+ if (sessionStorage) {
+ var img0 = new Image();
+ img0.src = sessionStorage.getItem('layer0');
+ img0.onload = function() {
+ var img1 = new Image();
+ img1.src = sessionStorage.getItem('layer1');
+ img1.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[1].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[0].drawImage(img0, 0, 0);
+ oe.canvasCtx[1].drawImage(img1, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.saveSession = function() {
+ if (sessionStorage) {
+ sessionStorage.setItem('timestamp', +(new Date()));
+ sessionStorage.setItem('layer0', this.canvas[0].toDataURL('image/png'));
+ sessionStorage.setItem('layer1', this.canvas[1].toDataURL('image/png'));
+ }
+};
+
+Neo.Painter.prototype.clearSession = function() {
+ if (sessionStorage) {
+ sessionStorage.removeItem('timestamp');
+ sessionStorage.removeItem('layer0');
+ sessionStorage.removeItem('layer1');
+ }
+};
+
+Neo.Painter.prototype.sortColor = function(r0, g0, b0) {
+ var min = (r0 < g0) ? ((r0 < b0) ? 0 : 2) : ((g0 < b0) ? 1 : 2);
+ var max = (r0 > g0) ? ((r0 > b0) ? 0 : 2) : ((g0 > b0) ? 1 : 2);
+ var mid = (min + max == 1) ? 2 : ((min + max == 2) ? 1 : 0);
+ return [min, mid, max];
+};
+
+Neo.Painter.prototype.doText = function(x, y, string, fontSize) {
+ //テキスト描画
+ //描画位置がずれるので適当に調整
+ var offset = parseInt(fontSize, 10);
+// y -= Math.round((5.0 + offset/8) / this.zoom);
+// x += Math.round(2.0 / this.zoom);
+
+ var ctx = this.tempCanvasCtx;
+ ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ ctx.save();
+ ctx.translate(x, y);
+// ctx.scale(1/this.zoom, 1/this.zoom);
+
+ ctx.font = fontSize + " Arial";
+ ctx.fillStyle = 0;
+ ctx.fillText(string, 0, 0);
+ ctx.restore();
+
+ // 適当に二値化
+ var c = this.getColor();
+ var r = c & 0xff;
+ var g = (c & 0xff00) >> 8;
+ var b = (c & 0xff0000) >> 16;
+ var a = Math.round(this.alpha * 255.0);
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var length = this.canvasWidth * this.canvasHeight;
+ var index = 0;
+ for (var i = 0; i < length; i++) {
+ if (buf8[index + 3] >= 0x60) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ } else {
+ buf8[index + 0] = 0;
+ buf8[index + 1] = 0;
+ buf8[index + 2] = 0;
+ buf8[index + 3] = 0;
+ }
+ index += 4;
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ //キャンバスに貼り付け
+ ctx = this.canvasCtx[this.current];
+ ctx.globalAlpha = 1.0;
+ ctx.drawImage(this.tempCanvas,
+ 0, 0, this.canvasWidth, this.canvasHeight,
+ 0, 0, this.canvasWidth, this.canvasHeight);
+
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.isUIPaused = function() {
+ if (this.drawType == Neo.Painter.DRAWTYPE_BEZIER) {
+ if (this.tool.step && this.tool.step > 0) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.getEmulationMode = function() {
+ return parseFloat(Neo.config.neo_emulation_mode || 2.22)
+};
+
+'use strict';
+
+Neo.ToolBase = function() {};
+
+Neo.ToolBase.prototype.startX;
+Neo.ToolBase.prototype.startY;
+Neo.ToolBase.prototype.init = function(oe) {}
+Neo.ToolBase.prototype.kill = function(oe) {}
+Neo.ToolBase.prototype.lineType = Neo.Painter.LINETYPE_NONE;
+
+Neo.ToolBase.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+};
+
+Neo.ToolBase.prototype.upHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.moveHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.transformForZoom = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ ctx.translate(oe.canvasWidth * 0.5, oe.canvasHeight * 0.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+};
+
+Neo.ToolBase.prototype.getType = function() {
+ return this.type;
+};
+
+Neo.ToolBase.prototype.getToolButton = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TEXT:
+ return Neo.penTip;
+
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ return Neo.pen2Tip;
+
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.effectTip;
+
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+ case Neo.Painter.TOOLTYPE_FLIP_H:
+ case Neo.Painter.TOOLTYPE_FLIP_V:
+ case Neo.Painter.TOOLTYPE_TURN:
+ return Neo.effect2Tip;
+
+ case Neo.Painter.TOOLTYPE_ERASER:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ return Neo.eraserTip;
+
+ case Neo.Painter.TOOLTYPE_FILL:
+ return Neo.fillButton;
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.getReserve = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_ERASER:
+ return Neo.reserveEraser;
+
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_FIP_H:
+ case Neo.Painter.TOOLTYPE_FIP_V:
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+
+ case Neo.Painter.TOOLTYPE_TEXT:
+ case Neo.Painter.TOOLTYPE_TURN:
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.reservePen;
+
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.updateUI();
+ }
+};
+
+Neo.ToolBase.prototype.saveStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ reserve.size = Neo.painter.lineWidth;
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ DrawToolBase(描画ツールのベースクラス)
+-------------------------------------------------------------------------
+*/
+
+Neo.DrawToolBase = function() {};
+Neo.DrawToolBase.prototype = new Neo.ToolBase();
+Neo.DrawToolBase.prototype.isUpMove = false;
+Neo.DrawToolBase.prototype.step = 0;
+
+Neo.DrawToolBase.prototype.init = function() {
+ this.step = 0;
+ this.isUpMove = true;
+};
+
+Neo.DrawToolBase.prototype.downHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierDownHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.moveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upMoveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.keyDownHandler = function(e) {
+ switch (Neo.painter.drawType) {
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierKeyDownHandler(e); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.rollOverHandler= function(oe) {};
+Neo.DrawToolBase.prototype.rollOutHandler= function(oe) {
+ if (!oe.isMouseDown && !oe.isMouseDownRight){
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+
+/* FreeHand (手書き) */
+
+Neo.DrawToolBase.prototype.freeHandDownHandler = function(oe) {
+ //Register undo first;
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ this.isUpMove = false;
+ var ctx = oe.canvasCtx[oe.current];
+ if (oe.alpha >= 1 || this.lineType != Neo.Painter.LINETYPE_BRUSH) {
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, x0, y0, this.lineType);
+ }
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ if (oe.alpha >= 1) {
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.mouseX, oe.mouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ }
+};
+
+Neo.DrawToolBase.prototype.freeHandUpHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+// oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+// this.drawCursor(oe);
+ oe.prevLine = null;
+};
+
+Neo.DrawToolBase.prototype.freeHandMoveHandler = function(oe) {
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ var x1 = Math.floor(oe.prevMouseX);
+ var y1 = Math.floor(oe.prevMouseY);
+ oe.drawLine(ctx, x0, y0, x1, y1, this.lineType);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.prevMouseX, oe.prevMouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+};
+
+Neo.DrawToolBase.prototype.freeHandUpMoveHandler = function(oe) {
+ this.isUpMove = true;
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+ this.drawCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.drawCursor = function(oe) {
+ if (oe.lineWidth <= 8) return;
+ var mx = oe.mouseX;
+ var my = oe.mouseY;
+ var d = oe.lineWidth;
+
+ var x = (mx - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y = (my - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var r = d * 0.5 * oe.zoom;
+
+ if (!(x > -r &&
+ y > -r &&
+ x < oe.destCanvas.width + r &&
+ y < oe.destCanvas.height + r)) return;
+
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var c = (this.type == Neo.Painter.TOOLTYPE_ERASER) ? 0x0000ff : 0xffff7f;
+ oe.drawXOREllipse(ctx, x-r, y-r, r*2, r*2, false, c);
+
+ ctx.restore();
+ oe.cursorRect = oe.getBound(mx, my, mx, my, Math.ceil(d / 2));
+}
+
+
+/* Line (直線) */
+
+Neo.DrawToolBase.prototype.lineDownHandler = function(oe) {
+ this.isUpMove = false;
+ this.startX = Math.floor(oe.mouseX);
+ this.startY = Math.floor(oe.mouseY);
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.lineUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+
+ oe._pushUndo();
+ oe.prepareDrawing();
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, this.startX, this.startY, this.lineType);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.lineMoveHandler = function(oe) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.drawLineCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.lineUpMoveHandler = function(oe) {
+};
+
+Neo.DrawToolBase.prototype.drawLineCursor = function(oe, mx, my) {
+ if (!mx) mx = Math.floor(oe.mouseX);
+ if (!my) my = Math.floor(oe.mouseY);
+ var nx = this.startX;
+ var ny = this.startY;
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var x0 = (mx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y0 = (my +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var x1 = (nx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y1 = (ny +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ oe.drawXORLine(ctx, x0, y0, x1, y1);
+
+ ctx.restore();
+};
+
+
+/* Bezier (BZ曲線) */
+
+Neo.DrawToolBase.prototype.bezierDownHandler = function(oe) {
+ this.isUpMove = false;
+
+ if (this.step == 0) {
+ this.startX = this.x0 = Math.floor(oe.mouseX);
+ this.startY = this.y0 = Math.floor(oe.mouseY);
+ }
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.bezierUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+ }
+
+ this.step++;
+ switch (this.step) {
+ case 1:
+ oe.prepareDrawing();
+ this.x3 = Math.floor(oe.mouseX);
+ this.y3 = Math.floor(oe.mouseY);
+ break;
+
+ case 2:
+ this.x1 = Math.floor(oe.mouseX);
+ this.y1 = Math.floor(oe.mouseY);
+ break;
+
+ case 3:
+ this.x2 = Math.floor(oe.mouseX);
+ this.y2 = Math.floor(oe.mouseY);
+
+ oe._pushUndo();
+ oe.drawBezier(oe.canvasCtx[oe.current],
+ this.x0, this.y0, this.x1, this.y1,
+ this.x2, this.y2, this.x3, this.y3, this.lineType);
+
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.step = 0;
+ break;
+
+ default:
+ this.step = 0;
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierMoveHandler = function(oe) {
+ switch (this.step) {
+ case 0:
+ if (!this.isUpMove) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawLineCursor(oe);
+ }
+ break;
+ case 1:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor1(oe);
+ break;
+
+ case 2:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor2(oe);
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierUpMoveHandler = function(oe) {
+ this.bezierMoveHandler(oe);
+};
+
+Neo.DrawToolBase.prototype.bezierKeyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escでキャンセル
+ this.step = 0;
+
+ var oe = Neo.painter;
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+
+Neo.DrawToolBase.prototype.drawBezierCursor1 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+// var x = oe.mouseX; //Math.floor(oe.mouseX);
+// var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(x, y, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p0.x, p0.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ x, y,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ ctx.restore();
+};
+
+Neo.DrawToolBase.prototype.drawBezierCursor2 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+// var x = oe.mouseX; //Math.floor(oe.mouseX);
+// var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(oe.mouseX, oe.mouseY, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p1 = oe.getDestCanvasPosition(this.x1, this.y1, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p3.x, p3.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXORLine(ctx, p0.x, p0.y, p1.x, p1.y);
+ oe.drawXOREllipse(ctx, p1.x - 4, p1.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ this.x1, this.y1,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+ ctx.restore();
+};
+
+/*
+-------------------------------------------------------------------------
+ Pen(鉛筆)
+-------------------------------------------------------------------------
+*/
+
+Neo.PenTool = function() {};
+Neo.PenTool.prototype = new Neo.DrawToolBase();
+Neo.PenTool.prototype.type = Neo.Painter.TOOLTYPE_PEN;
+Neo.PenTool.prototype.lineType = Neo.Painter.LINETYPE_PEN;
+
+Neo.PenTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+}
+
+/*
+-------------------------------------------------------------------------
+ Brush(水彩)
+-------------------------------------------------------------------------
+*/
+
+Neo.BrushTool = function() {};
+Neo.BrushTool.prototype = new Neo.DrawToolBase();
+Neo.BrushTool.prototype.type = Neo.Painter.TOOLTYPE_BRUSH;
+Neo.BrushTool.prototype.lineType = Neo.Painter.LINETYPE_BRUSH;
+
+Neo.BrushTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.getAlpha();
+ Neo.updateUI();
+ }
+};
+
+Neo.BrushTool.prototype.getAlpha = function() {
+ var alpha = 241 - Math.floor(Neo.painter.lineWidth / 2) * 6;
+ return alpha / 255.0;
+};
+
+/*
+-------------------------------------------------------------------------
+ Tone(トーン)
+-------------------------------------------------------------------------
+*/
+
+Neo.ToneTool = function() {};
+Neo.ToneTool.prototype = new Neo.DrawToolBase();
+Neo.ToneTool.prototype.type = Neo.Painter.TOOLTYPE_TONE;
+Neo.ToneTool.prototype.lineType = Neo.Painter.LINETYPE_TONE;
+
+Neo.ToneTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 23 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Eraser(消しペン)
+-------------------------------------------------------------------------
+*/
+
+Neo.EraserTool = function() {};
+Neo.EraserTool.prototype = new Neo.DrawToolBase();
+Neo.EraserTool.prototype.type = Neo.Painter.TOOLTYPE_ERASER;
+Neo.EraserTool.prototype.lineType = Neo.Painter.LINETYPE_ERASER;
+
+
+/*
+-------------------------------------------------------------------------
+ Blur(ぼかし)
+-------------------------------------------------------------------------
+*/
+
+Neo.BlurTool = function() {};
+Neo.BlurTool.prototype = new Neo.DrawToolBase();
+Neo.BlurTool.prototype.type = Neo.Painter.TOOLTYPE_BLUR;
+Neo.BlurTool.prototype.lineType = Neo.Painter.LINETYPE_BLUR;
+
+Neo.BlurTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Dodge(覆い焼き)
+-------------------------------------------------------------------------
+*/
+
+Neo.DodgeTool = function() {};
+Neo.DodgeTool.prototype = new Neo.DrawToolBase();
+Neo.DodgeTool.prototype.type = Neo.Painter.TOOLTYPE_DODGE;
+Neo.DodgeTool.prototype.lineType = Neo.Painter.LINETYPE_DODGE;
+
+Neo.DodgeTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Burn(焼き込み)
+-------------------------------------------------------------------------
+*/
+
+Neo.BurnTool = function() {};
+Neo.BurnTool.prototype = new Neo.DrawToolBase();
+Neo.BurnTool.prototype.type = Neo.Painter.TOOLTYPE_BURN;
+Neo.BurnTool.prototype.lineType = Neo.Painter.LINETYPE_BURN;
+
+Neo.BurnTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Hand(スクロール)
+-------------------------------------------------------------------------
+*/
+
+Neo.HandTool = function() {};
+Neo.HandTool.prototype = new Neo.ToolBase();
+Neo.HandTool.prototype.type = Neo.Painter.TOOLTYPE_HAND;
+Neo.HandTool.prototype.isUpMove = false;
+Neo.HandTool.prototype.reverse = false;
+
+Neo.HandTool.prototype.downHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ this.isDrag = true;
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+};
+
+Neo.HandTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+};
+
+Neo.HandTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var dx = this.startX - oe.rawMouseX;
+ var dy = this.startY - oe.rawMouseY;
+
+ var ax = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var ay = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barWidth = oe.destCanvas.width * ax;
+ var barHeight = oe.destCanvas.height * ay;
+ var scrollWidthInScreen = oe.destCanvas.width - barWidth - 2;
+ var scrollHeightInScreen = oe.destCanvas.height - barHeight - 2;
+
+ dx *= oe.scrollWidth / scrollWidthInScreen;
+ dy *= oe.scrollHeight / scrollHeightInScreen;
+
+ if (this.reverse) {
+ dx *= -1;
+ dy *= -1;
+ }
+
+ oe.setZoomPosition(oe.zoomX - dx, oe.zoomY - dy);
+
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+ }
+};
+
+Neo.HandTool.prototype.rollOutHandler= function(oe) {};
+Neo.HandTool.prototype.upMoveHandler = function(oe) {}
+Neo.HandTool.prototype.rollOverHandler= function(oe) {}
+
+/*
+-------------------------------------------------------------------------
+ Slider(色やサイズのスライダを操作している時)
+-------------------------------------------------------------------------
+*/
+
+Neo.SliderTool = function() {};
+Neo.SliderTool.prototype = new Neo.ToolBase();
+Neo.SliderTool.prototype.type = Neo.Painter.TOOLTYPE_SLIDER;
+Neo.SliderTool.prototype.isUpMove = false;
+Neo.SliderTool.prototype.alt = false;
+
+Neo.SliderTool.prototype.downHandler = function(oe) {
+ if (!oe.isShiftDown) this.isDrag = true;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].downHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].upHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].moveHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+ }
+};
+
+Neo.SliderTool.prototype.upMoveHandler = function(oe) {}
+Neo.SliderTool.prototype.rollOutHandler= function(oe) {};
+Neo.SliderTool.prototype.rollOverHandler= function(oe) {}
+
+/*
+-------------------------------------------------------------------------
+ Fill(塗り潰し)
+-------------------------------------------------------------------------
+*/
+
+Neo.FillTool = function() {};
+Neo.FillTool.prototype = new Neo.ToolBase();
+Neo.FillTool.prototype.type = Neo.Painter.TOOLTYPE_FILL;
+Neo.FillTool.prototype.isUpMove = false;
+
+Neo.FillTool.prototype.downHandler = function(oe) {
+ var x = Math.floor(oe.mouseX);
+ var y = Math.floor(oe.mouseY);
+ oe._pushUndo();
+ oe.fill(x, y, oe.canvasCtx[oe.current]);
+};
+
+Neo.FillTool.prototype.upHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.rollOutHandler= function(oe) {};
+Neo.FillTool.prototype.upMoveHandler = function(oe) {}
+Neo.FillTool.prototype.rollOverHandler= function(oe) {}
+
+
+/*
+-------------------------------------------------------------------------
+ EraseAll(全消し)
+-------------------------------------------------------------------------
+*/
+
+Neo.EraseAllTool = function() {};
+Neo.EraseAllTool.prototype = new Neo.ToolBase();
+Neo.EraseAllTool.prototype.type = Neo.Painter.TOOLTYPE_ERASEALL;
+Neo.EraseAllTool.prototype.isUpMove = false;
+
+Neo.EraseAllTool.prototype.downHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ oe.canvasCtx[oe.current].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.EraseAllTool.prototype.upHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.rollOutHandler= function(oe) {};
+Neo.EraseAllTool.prototype.upMoveHandler = function(oe) {};
+Neo.EraseAllTool.prototype.rollOverHandler= function(oe) {};
+
+
+/*
+-------------------------------------------------------------------------
+ EffectToolBase(エフェックトツールのベースクラス)
+-------------------------------------------------------------------------
+*/
+
+Neo.EffectToolBase = function() {};
+Neo.EffectToolBase.prototype = new Neo.ToolBase();
+Neo.EffectToolBase.prototype.isUpMove = false;
+
+Neo.EffectToolBase.prototype.downHandler = function(oe) {
+ this.isUpMove = false;
+
+ this.startX = this.endX = oe.clipMouseX;
+ this.startY = this.endY = oe.clipMouseY;
+};
+
+Neo.EffectToolBase.prototype.upHandler = function(oe) {
+ if (this.isUpMove) return;
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+ var ctx = oe.canvasCtx[oe.current];
+
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (x + width > oe.canvasWidth) width = oe.canvasWidth - x;
+ if (y + height > oe.canvasHeight) height = oe.canvasHeight - y;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.prepareDrawing();
+ this.doEffect(oe, x, y, width, height);
+ }
+
+ if (oe.tool.type != Neo.Painter.TOOLTYPE_PASTE) {
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.EffectToolBase.prototype.moveHandler = function(oe) {
+ this.endX = oe.clipMouseX;
+ this.endY = oe.clipMouseY;
+
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ this.drawCursor(oe);
+};
+
+Neo.EffectToolBase.prototype.rollOutHandler= function(oe) {};
+Neo.EffectToolBase.prototype.upMoveHandler = function(oe) {};
+Neo.EffectToolBase.prototype.rollOverHandler= function(oe) {};
+
+Neo.EffectToolBase.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.startX, this.startY, true);
+ var end = oe.getDestCanvasPosition(this.endX, this.endY, true);
+
+ var x = (start.x < end.x) ? start.x : end.x;
+ var y = (start.y < end.y) ? start.y : end.y;
+ var width = Math.abs(start.x - end.x) + oe.zoom;
+ var height = Math.abs(start.y - end.y) + oe.zoom;
+
+ if (this.isEllipse) {
+ oe.drawXOREllipse(ctx, x, y, width, height, this.isFill);
+
+ } else {
+ oe.drawXORRect(ctx, x, y, width, height, this.isFill);
+ }
+ ctx.restore();
+};
+
+Neo.EffectToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.defaultAlpha || 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+-------------------------------------------------------------------------
+ EraseRect(消し四角)
+-------------------------------------------------------------------------
+*/
+
+Neo.EraseRectTool = function() {};
+Neo.EraseRectTool.prototype = new Neo.EffectToolBase();
+Neo.EraseRectTool.prototype.type = Neo.Painter.TOOLTYPE_ERASERECT;
+
+Neo.EraseRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.eraseRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ FlipH(左右反転)
+-------------------------------------------------------------------------
+*/
+
+Neo.FlipHTool = function() {};
+Neo.FlipHTool.prototype = new Neo.EffectToolBase();
+Neo.FlipHTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_H;
+
+Neo.FlipHTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipH(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ FlipV(上下反転)
+-------------------------------------------------------------------------
+*/
+
+Neo.FlipVTool = function() {};
+Neo.FlipVTool.prototype = new Neo.EffectToolBase();
+Neo.FlipVTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_V;
+
+Neo.FlipVTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipV(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ DodgeRect(角取り)
+-------------------------------------------------------------------------
+*/
+
+Neo.BlurRectTool = function() {};
+Neo.BlurRectTool.prototype = new Neo.EffectToolBase();
+Neo.BlurRectTool.prototype.type = Neo.Painter.TOOLTYPE_BLURRECT;
+
+Neo.BlurRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.blurRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.BlurRectTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 0.5;
+ Neo.updateUI();
+ };
+}
+
+/*
+-------------------------------------------------------------------------
+ Turn(傾け)
+-------------------------------------------------------------------------
+*/
+
+Neo.TurnTool = function() {};
+Neo.TurnTool.prototype = new Neo.EffectToolBase();
+Neo.TurnTool.prototype.type = Neo.Painter.TOOLTYPE_TURN;
+
+Neo.TurnTool.prototype.upHandler = function(oe) {
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.turn(x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Merge(レイヤー結合)
+-------------------------------------------------------------------------
+*/
+
+Neo.MergeTool = function() {};
+Neo.MergeTool.prototype = new Neo.EffectToolBase();
+Neo.MergeTool.prototype.type = Neo.Painter.TOOLTYPE_MERGE;
+
+Neo.MergeTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.merge(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ Copy(コピー)
+-------------------------------------------------------------------------
+*/
+
+Neo.CopyTool = function() {};
+Neo.CopyTool.prototype = new Neo.EffectToolBase();
+Neo.CopyTool.prototype.type = Neo.Painter.TOOLTYPE_COPY;
+
+Neo.CopyTool.prototype.doEffect = function(oe, x, y, width, height) {
+ oe.copy(x, y, width, height);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_PASTE);
+ oe.tool.x = x;
+ oe.tool.y = y;
+ oe.tool.width = width;
+ oe.tool.height = height;
+};
+
+/*
+-------------------------------------------------------------------------
+ Paste(ペースト)
+-------------------------------------------------------------------------
+*/
+
+Neo.PasteTool = function() {};
+Neo.PasteTool.prototype = new Neo.ToolBase();
+Neo.PasteTool.prototype.type = Neo.Painter.TOOLTYPE_PASTE;
+
+Neo.PasteTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+ this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.upHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.paste(this.x, this.y, this.width, this.height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+};
+
+Neo.PasteTool.prototype.moveHandler = function(oe) {
+ var dx = Math.floor(oe.mouseX - this.startX);
+ var dy = Math.floor(oe.mouseY - this.startY);
+ oe.tempX = dx;
+ oe.tempY = dy;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+// this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escでキャンセル
+ var oe = Neo.painter;
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+ }
+};
+
+Neo.PasteTool.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.x, this.y, true);
+ var end = oe.getDestCanvasPosition(this.x + this.width, this.y + this.height, true);
+
+ var x = start.x + oe.tempX * oe.zoom;
+ var y = start.y + oe.tempY * oe.zoom;
+ var width = Math.abs(start.x - end.x);
+ var height = Math.abs(start.y - end.y);
+ oe.drawXORRect(ctx, x, y, width, height);
+ ctx.restore();
+};
+
+/*
+-------------------------------------------------------------------------
+ Rect(線四角)
+-------------------------------------------------------------------------
+*/
+
+Neo.RectTool = function() {};
+Neo.RectTool.prototype = new Neo.EffectToolBase();
+Neo.RectTool.prototype.type = Neo.Painter.TOOLTYPE_RECT;
+
+Neo.RectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ RectFill(四角)
+-------------------------------------------------------------------------
+*/
+
+Neo.RectFillTool = function() {};
+Neo.RectFillTool.prototype = new Neo.EffectToolBase();
+Neo.RectFillTool.prototype.type = Neo.Painter.TOOLTYPE_RECTFILL;
+
+Neo.RectFillTool.prototype.isFill = true;
+Neo.RectFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ Ellipse(線楕円)
+-------------------------------------------------------------------------
+*/
+
+Neo.EllipseTool = function() {};
+Neo.EllipseTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSE;
+Neo.EllipseTool.prototype.isEllipse = true;
+Neo.EllipseTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ EllipseFill(楕円)
+-------------------------------------------------------------------------
+*/
+
+Neo.EllipseFillTool = function() {};
+Neo.EllipseFillTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseFillTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSEFILL;
+Neo.EllipseFillTool.prototype.isEllipse = true;
+Neo.EllipseFillTool.prototype.isFill = true;
+Neo.EllipseFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ Text(テキスト)
+-------------------------------------------------------------------------
+*/
+
+Neo.TextTool = function() {};
+Neo.TextTool.prototype = new Neo.ToolBase();
+Neo.TextTool.prototype.type = Neo.Painter.TOOLTYPE_TEXT;
+Neo.TextTool.prototype.isUpMove = false;
+
+Neo.TextTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+
+ if (Neo.painter.inputText) {
+ Neo.painter.updateInputText();
+
+ var rect = oe.container.getBoundingClientRect();
+ var text = Neo.painter.inputText;
+ var x = oe.rawMouseX - rect.left - 5;
+ var y = oe.rawMouseY - rect.top - 5;
+
+ text.style.left = x + "px";
+ text.style.top = y + "px";
+ text.style.display = "block";
+ text.focus();
+ }
+};
+
+Neo.TextTool.prototype.upHandler = function(oe) {
+};
+
+Neo.TextTool.prototype.moveHandler = function(oe) {};
+Neo.TextTool.prototype.upMoveHandler = function(oe) {};
+Neo.TextTool.prototype.rollOverHandler= function(oe) {};
+Neo.TextTool.prototype.rollOutHandler= function(oe) {};
+
+Neo.TextTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 13) { // Returnで確定
+ e.preventDefault();
+
+ var oe = Neo.painter;
+ var text = oe.inputText;
+ if (text) {
+ oe._pushUndo();
+ this.drawText(oe);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ text.style.display = "none";
+ text.blur();
+ }
+ }
+};
+
+Neo.TextTool.prototype.kill = function(oe) {
+ Neo.painter.hideInputText();
+};
+
+Neo.TextTool.prototype.drawText = function(oe) {
+ var text = oe.inputText;
+
+ // unescape entities
+ //var tmp = document.createElement("textarea");
+ //tmp.innerHTML = text.innerHTML;
+ //var string = tmp.value;
+
+ var string = text.textContent || text.innerText;
+
+ if (string.length <= 0) return;
+ oe.doText(this.startX, this.startY, string, text.style.fontSize);
+};
+
+Neo.TextTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+-------------------------------------------------------------------------
+ Dummy(何もしない時)
+-------------------------------------------------------------------------
+*/
+
+Neo.DummyTool = function() {};
+Neo.DummyTool.prototype = new Neo.ToolBase();
+Neo.DummyTool.prototype.type = Neo.Painter.TOOLTYPE_NONE;
+Neo.DummyTool.prototype.isUpMove = false;
+
+Neo.DummyTool.prototype.downHandler = function(oe) {
+};
+
+Neo.DummyTool.prototype.upHandler = function(oe) {
+ oe.popTool();
+};
+
+Neo.DummyTool.prototype.moveHandler = function(oe) {};
+Neo.DummyTool.prototype.upMoveHandler = function(oe) {}
+Neo.DummyTool.prototype.rollOverHandler= function(oe) {}
+Neo.DummyTool.prototype.rollOutHandler= function(oe) {}
+
+'use strict';
+
+Neo.CommandBase = function() {
+};
+Neo.CommandBase.prototype.data;
+Neo.CommandBase.prototype.execute = function() {}
+
+
+/*
+---------------------------------------------------
+ ZOOM
+---------------------------------------------------
+*/
+Neo.ZoomPlusCommand = function(data) {this.data = data};
+Neo.ZoomPlusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomPlusCommand.prototype.execute = function() {
+ if (this.data.zoom < 12) {
+ this.data.setZoom(this.data.zoom + 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+Neo.ZoomMinusCommand = function(data) {this.data = data};
+Neo.ZoomMinusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomMinusCommand.prototype.execute = function() {
+ if (this.data.zoom >= 2) {
+ this.data.setZoom(this.data.zoom - 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+/*
+---------------------------------------------------
+ UNDO
+---------------------------------------------------
+*/
+Neo.UndoCommand = function(data) {this.data = data};
+Neo.UndoCommand.prototype = new Neo.CommandBase();
+Neo.UndoCommand.prototype.execute = function() {
+ this.data.undo();
+};
+
+Neo.RedoCommand = function(data) {this.data = data};
+Neo.RedoCommand.prototype = new Neo.CommandBase();
+Neo.RedoCommand.prototype.execute = function() {
+ this.data.redo();
+};
+
+
+/*
+---------------------------------------------------
+---------------------------------------------------
+*/
+
+
+
+Neo.WindowCommand = function(data) {this.data = data};
+Neo.WindowCommand.prototype = new Neo.CommandBase();
+Neo.WindowCommand.prototype.execute = function() {
+ if (Neo.fullScreen) {
+ //if (confirm("¿Vista página?")) {
+ Neo.fullScreen = false;
+ Neo.updateWindow();
+ //}
+ } else {
+ //if (confirm("¿Vista ventana?")) {
+ Neo.fullScreen = true;
+ Neo.updateWindow();
+ //}
+ }
+};
+
+Neo.SubmitCommand = function(data) {this.data = data};
+Neo.SubmitCommand.prototype = new Neo.CommandBase();
+Neo.SubmitCommand.prototype.execute = function() {
+ var board = location.href.replace(/[^/]*$/, '');
+ console.log("submit: " + board);
+ this.data.submit(board);
+};
+
+Neo.CopyrightCommand = function(data) {this.data = data};
+Neo.CopyrightCommand.prototype = new Neo.CommandBase();
+Neo.CopyrightCommand.prototype.execute = function() {
+// var url = "http://hp.vector.co.jp/authors/VA016309/";
+// if (confirm(url + "\nしぃちゃんのホームページを表示しますか?")) {
+ var url = "http://github.com/funige/neo/";
+ if (confirm("PaintBBS NEOは、お絵描きしぃ掲示板 PaintBBS (©2000-2004 しぃちゃん) をhtml5化するプロジェクトです。\n\nPaintBBS NEOのホームページを表示しますか?" + "\n")) {
+ Neo.openURL(url);
+ }
+};
+
+'use strict';
+
+/*
+-------------------------------------------------------------------------
+ Button
+-------------------------------------------------------------------------
+*/
+
+Neo.Button = function() {};
+Neo.Button.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.selected = false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ if (window.PointerEvent) {
+ this.element.onpointerdown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onpointerup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onpointerover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onpointerout = function(e) { ref._mouseOutHandler(e); }
+
+ } else {
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ }
+ this.element.className = (!this.params.type == 'fill') ? "button" : "buttonOff";
+
+ return this;
+};
+
+Neo.Button.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ if ((this.params.type == "fill") && (this.selected == false)) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this.selected) ? false : true);
+ }
+ Neo.painter.setToolByType(Neo.Painter.TOOLTYPE_FILL);
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.Button.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.Button.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.Button.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.Button.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "buttonOn";
+ } else {
+ this.element.className = "buttonOff";
+ }
+ this.selected = selected;
+};
+
+Neo.Button.prototype.update = function() {
+};
+
+/*
+-------------------------------------------------------------------------
+ ColorTip
+-------------------------------------------------------------------------
+*/
+
+Neo.colorTips = [];
+
+Neo.ColorTip = function() {};
+Neo.ColorTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.selected = (this.name == "color1") ? true : false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ if (window.PointerEvent) {
+ this.element.onpointerdown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onpointerup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onpointerover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onpointerout = function(e) { ref._mouseOutHandler(e); }
+
+ } else {
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ }
+ this.element.className = "colorTipOff";
+
+ var index = parseInt(this.name.slice(5)) - 1;
+ this.element.style.left = (index % 2) ? "0px" : "26px";
+ this.element.style.top = Math.floor(index / 2) * 21 + "px";
+
+ // base64 ColorTip.png
+ this.element.innerHTML = "<img style='max-width:44px;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAASCAYAAAAg9DzcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANklEQVRIx+3OAQkAMADDsO3+Pe8qCj+0Akq6bQFqS2wTCpwE+R4IiyVYsGDBggULfirBgn8HX7BzCRwDx1QeAAAAAElFTkSuQmCC' />"
+
+ this.setColor(Neo.config.colors[params.index - 1]);
+
+ this.setSelected(this.selected);
+ Neo.colorTips.push(this);
+};
+
+Neo.ColorTip.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (this == colorTip) {
+ if (e.shiftKey) {
+ this.setColor(Neo.config.colors[this.params.index - 1]);
+ } else if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.setColor(Neo.painter.foregroundColor);
+ }
+ }
+ colorTip.setSelected(this == colorTip) ? true : false;
+ }
+ Neo.painter.setColor(this.color);
+ Neo.updateUIColor(true, false);
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.ColorTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ColorTip.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "colorTipOn";
+ } else {
+ this.element.className = "colorTipOff";
+ }
+ this.selected = selected;
+};
+
+Neo.ColorTip.prototype.setColor = function(color) {
+ this.color = color;
+ this.element.style.backgroundColor = color;
+};
+
+Neo.ColorTip.getCurrent = function() {
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (colorTip.selected) return colorTip;
+ }
+ return null;
+};
+
+/*
+-------------------------------------------------------------------------
+ ToolTip
+-------------------------------------------------------------------------
+*/
+
+Neo.toolTips = [];
+Neo.toolButtons = [];
+
+Neo.ToolTip = function() {};
+
+Neo.ToolTip.prototype.prevMode = -1;
+
+Neo.ToolTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.params.type = this.element.id;
+ this.name = name;
+ this.mode = 0;
+
+ this.isMouseDown = false;
+
+ var ref = this;
+ if (window.PointerEvent) {
+ this.element.onpointerdown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onpointerup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onpointerover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onpointerout = function(e) { ref._mouseOutHandler(e); }
+
+ } else {
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ }
+ this.selected = (this.params.type == "pen") ? true : false;
+ this.setSelected(this.selected);
+
+ this.element.innerHTML = "<canvas width=46 height=18></canvas><div class='label'></div>";
+ this.canvas = this.element.getElementsByTagName('canvas')[0];
+ this.label = this.element.getElementsByTagName('div')[0];
+
+ this.update();
+ return this;
+};
+
+Neo.ToolTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (this.isTool) {
+ if (this.selected == false) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this == toolTip) ? true : false);
+ }
+
+ } else {
+ var length = this.toolStrings.length;
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ }
+ Neo.painter.setToolByType(this.tools[this.mode]);
+ this.update();
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.ToolTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+
+Neo.ToolTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ToolTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ToolTip.prototype.setSelected = function(selected) {
+ if (this.fixed) {
+ this.element.className = "toolTipFixed";
+
+ } else {
+ if (selected) {
+ this.element.className = "toolTipOn";
+ } else {
+ this.element.className = "toolTipOff";
+ }
+ }
+ this.selected = selected;
+};
+
+Neo.ToolTip.prototype.update = function() {};
+
+Neo.ToolTip.prototype.draw = function(c) {
+ if (this.hasTintImage) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+ var ctx = this.canvas.getContext("2d");
+
+ if (this.prevMode != this.mode) {
+ this.prevMode = this.mode;
+
+ var img = new Image();
+ img.src = this.toolIcons[this.mode];
+ img.onload = function() {
+ var ref = this;
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ this.drawTintImage(ctx, img, c, 0, 0);
+ }.bind(this);
+
+ } else {
+ this.tintImage(ctx, c);
+ }
+ }
+};
+
+Neo.ToolTip.prototype.drawTintImage = function(ctx, img, c, x, y) {
+ ctx.drawImage(img, x, y);
+ this.tintImage(ctx, c);
+};
+
+Neo.ToolTip.prototype.tintImage = function(ctx, c) {
+ c = (Neo.painter.getColor(c) & 0xffffff);
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ for (var i = 0; i < buf32.length; i++) {
+ var a = buf32[i] & 0xff000000;
+ if (a) {
+ buf32[i] = buf32[i] & a | c;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+};
+
+Neo.ToolTip.bezier = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAT0lEQVRIx+3SQQoAIAhE0en+h7ZVEEKBZrX5b5sjKknAkRYpNslaMLPq44ZI9wwHs0vMQ/v87u0Kk8xfsaI242jbMdjPi5Y0r/zTAAAAD3UOjRf9jcO4sgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blur = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAASUlEQVRIx+3VMQ4AIAgEQeD/f8bWWBnJYUh2SgtgK82G8/MhzVKwxOtTLgIUx6tDout4laiPIICA0Qj4bXxAy0+8LZP9yACAJwsqkggS55eiZgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blurrect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAX0lEQVRIx+2XQQ4AEAwEt+I7/v+8Org6lJKt6NzLjjYE8DAKtLpYoDeCCCC7tYUd3ru2qQOzDTyndhJzB6KSAmxSgM0fAlGuzBnmlziqxB8jFJkUYJMCbAQYPxt2kF06fvYKgjPBO/IAAAAASUVORK5CYII=";
+Neo.ToolTip.brush = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQUlEQVRIx2NgGOKAEcb4z8CweRA4xpdUPSxofJ8BdP8WcjQxDaCDqQLQY4CsUBgFo2AUjIJRMApGwSgYBaNgZAIA0CoDwDbZu8oAAAAASUVORK5CYII=";
+Neo.ToolTip.burn = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAPklEQVRIx+3PMRIAMAQAQbzM0/0sKZPeiDG57TQ4keH0Htx9VR+MCM1vOezl8xUsv4IAAkYjoBsB3QgAgL9tYXgF19rh9yoAAAAASUVORK5CYII=";
+Neo.ToolTip.copy = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XMQoAIAwDU/E7/v95Orh2KMUSC7m5Qs6AUqAxG1gzOLirwxhgmXOjOlg1oQY8sjf2mvYNSICNBNhIgE3oH/jlzfdo34AE2EiATXsBA+5mww6S5QASDwSGMt8ouwAAAABJRU5ErkJggg==";
+Neo.ToolTip.copy2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAN0lEQVRIx+3PwQkAIBADwdPKt3MtQVCOPNz5B7JV0pNxOwRW9zng+G92n+hmQJoBaQakGSBJf9tyBgQUV/fKCAAAAABJRU5ErkJggg==";
+Neo.ToolTip.ellipse = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAATklEQVRIx+2VMQ4AIAgD6/8fjbOJi1LFmt4OPQ0KIE7LNgggCBLbHkuFM9lM+Om+QwDjpksyb4tT86vlvzgEbYxefQPyv5D8HjDGGGOk6b3jJ+lYubd8AAAAAElFTkSuQmCC";
+Neo.ToolTip.ellipsefill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAVUlEQVRIx+2VURIAEAgFc/9D5waSHpV5+43ZHRMizRnRA1REARLHHq6NCFl01Nail+LeEDMgU34nYhlQQd6K+PsGKkSEZyArBPoK3Y6K/AOEEEJIayZHbhIKjkZrFwAAAABJRU5ErkJggg==";
+Neo.ToolTip.eraser = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAABQElEQVRIx+1WQY7CMAwcI37Cad+yXOgH4Gu8gAt9CtrDirfMHjZJbbcktVSpQnROSeMkY3vsFHhzSG3xfLpz/JVmG0mIqDkIMcc6+7Kejx6fdb0dq7w09rVFkrjejrMOunQ9vg7f/5QEIAd6E1Eo38WF8fF7n8sdALCrLerIzoFI4sI0Vtv1SYZ8CVbeF7tzF7JugIkVkxOauc6CIe8842S+XmMfsq7TN9LRTngZmTmVD4SrnzYaGYhFoxCWgajXuMjYGTuJ3dlwIBIN3U0cUVqLXCs5E7YeVsvAYJul5HWeLUhL3EpstQwooqoOTEHDOebpMn7ngkUsg3RotU8X1MkuVDrYohkIupC0YArX6T+PfX3kcbQLNV/iCKi6EB3xqXdAZ0JKthZ8B0QEl673NIEX/0I/z36Rf6ENGzZ8EP4A8Lp+9e9VWC4AAAAASUVORK5CYII=";
+Neo.ToolTip.flip = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAZklEQVRIx+2XQQoAIAgE1+g7/f95degWHSyTTXDOhTsSiUBgOtCq8mD3DiOA3NxTCVgKaLA0qHiFOsHSnC8ELKQAmxRgE15APQfWv9pzLjwX+CXsjvBPKAXYpACb8AICzM2GHeSWAfVOCIiJuQ9tAAAAAElFTkSuQmCC";
+Neo.ToolTip.freehand = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAdUlEQVRIx+2WUQrAMAhD3dj9r+y+VoSyLhYDynzQv1qiJlCR4hzeAhVRsiC3Jkj0c5hN7Lx7IQ9SphLE1ICdwko420purEWQuywN3pqxgcw2+WwAtU1GzoqiLZNwZBvMAIcO8y3YKUO8mkbmjPzjK9E0TUPjBoeyLAS0usjLAAAAAElFTkSuQmCC";
+Neo.ToolTip.line = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAU0lEQVRIx+2UQQ4AIAjD8P+PxivRGDQC47C+oN1hIgTLQAt4qIga2c23XYAVPkm3CVhlb4ShAa/rQgMi1i0NyFg3LaBq3bAA1LpfAd7/EkIIIR2YXFYSCpWS8w8AAAAASUVORK5CYII=";
+Neo.ToolTip.merge = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XQQrAQAgDx9Lv9JF9+e6h54IINlgyZ4UMOYgwmAXXmRxc3WECorJ3dAfrJtXAC7c6PPygAQuosYAaC6hJ3YHqlfyC8Q1YQI0F1IwXCHg+G3WQKhvwgwUFmFyYbwAAAABJRU5ErkJggg==";
+Neo.ToolTip.pen = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAK0lEQVRIx+3OsQkAMAwDQXn/oe3WfSAEctd9I5TA32pHJ/3AoTpfAQCAGwaa5AICJLKWSQAAAABJRU5ErkJggg==";
+Neo.ToolTip.rect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQElEQVRIx+3TMQ4AIAhD0WK8/5VxdcIYY8rw3wok7YAEr6iGKaU74BY0ro+6FKhyDHe4VxRwm6eFLn8AAADwwQIwTQgGo9ZMywAAAABJRU5ErkJggg==";
+Neo.ToolTip.rectfill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANElEQVRIx+3PIQ4AIBADwcL//3xYBMEgLiQztmab0GvcxkqqO3ALPbbO7rBXDnRzAADgYwvqDwIMJlGb5QAAAABJRU5ErkJggg==";
+Neo.ToolTip.text = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAcUlEQVRIx+2VwQ7AIAhDy7L//2V2WmIYg+ky2KEv8aCCqYQqQMgrJNpUQMXEKKDmAPHyspgSrBBvLZu3cQqZEdwhfusq0KdkVR5HlFfBvpI0mtIzeusFot7vFPqYuzZYMXUFlzc+qrIn7tf/ACGEkIwDlEQ94YZjzcgAAAAASUVORK5CYII=";
+Neo.ToolTip.tone = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAO0lEQVRIx+3PIQ4AMAgEwaP//zNVVZUELiQ7CgWstFy8IaVsPhT1Lb/T+fQEAtwIcCPAjQC39QEAgJIL6DQCFhAqsRkAAAAASUVORK5CYII=";
+
+/*
+-------------------------------------------------------------------------
+ PenTip
+-------------------------------------------------------------------------
+*/
+
+Neo.penTip;
+
+Neo.PenTip = function() {};
+Neo.PenTip.prototype = new Neo.ToolTip();
+
+Neo.PenTip.prototype.toolStrings = ["Lapiz", "Acuarela", "Texto"];
+Neo.PenTip.prototype.tools = [Neo.Painter.TOOLTYPE_PEN,
+ Neo.Painter.TOOLTYPE_BRUSH,
+ Neo.Painter.TOOLTYPE_TEXT];
+
+Neo.PenTip.prototype.hasTintImage = true;
+Neo.PenTip.prototype.toolIcons = [Neo.ToolTip.pen,
+ Neo.ToolTip.brush,
+ Neo.ToolTip.text];
+
+Neo.PenTip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.PenTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ if (this.label) {
+ this.label.innerHTML = this.toolStrings[this.mode];
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Pen2Tip
+-------------------------------------------------------------------------
+*/
+
+Neo.pen2Tip;
+
+Neo.Pen2Tip = function() {};
+Neo.Pen2Tip.prototype = new Neo.ToolTip();
+
+Neo.Pen2Tip.prototype.toolStrings = ["Tono",
+ "Gradacion",
+ "Sobreexp.",
+ "Quemar"];
+Neo.Pen2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_TONE,
+ Neo.Painter.TOOLTYPE_BLUR,
+ Neo.Painter.TOOLTYPE_DODGE,
+ Neo.Painter.TOOLTYPE_BURN];
+
+Neo.Pen2Tip.prototype.hasTintImage = true;
+Neo.Pen2Tip.prototype.toolIcons = [Neo.ToolTip.tone,
+ Neo.ToolTip.blur,
+ Neo.ToolTip.burn,
+ Neo.ToolTip.burn];
+
+Neo.Pen2Tip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.Pen2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ switch (this.tools[this.mode]) {
+ case Neo.Painter.TOOLTYPE_TONE:
+ this.drawTone(Neo.painter.foregroundColor);
+ break;
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ this.draw(0xffc0c0c0);
+ break;
+
+ case Neo.Painter.TOOLTYPE_BURN:
+ this.draw(0xff404040);
+ break;
+
+ default:
+ this.draw(Neo.painter.foregroundColor);
+ break;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.Pen2Tip.prototype.drawTone = function() {
+ var ctx = this.canvas.getContext("2d");
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var c = Neo.painter.getColor() | 0xff000000;
+ var a = Math.floor(Neo.painter.alpha * 255);
+ var toneData = Neo.painter.getToneData(a);
+
+ for (var j = 0; j < 18; j++) {
+ for (var i = 0; i < 46; i++) {
+ if (j >= 1 && j < 12 &&
+ i >= 2 && i < 26 &&
+ toneData[(i%4) + (j%4) * 4]) {
+ buf32[j * 46 + i] = c;
+
+ } else {
+ buf32[j * 46 + i] = 0;
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ this.prevMode = this.mode;
+};
+
+
+/*
+-------------------------------------------------------------------------
+ EraserTip
+-------------------------------------------------------------------------
+*/
+
+Neo.eraserTip;
+
+Neo.EraserTip = function() {};
+Neo.EraserTip.prototype = new Neo.ToolTip();
+
+Neo.EraserTip.prototype.toolStrings = ["Goma", "Goma", "Borrar"];
+Neo.EraserTip.prototype.tools = [Neo.Painter.TOOLTYPE_ERASER,
+ Neo.Painter.TOOLTYPE_ERASERECT,
+ Neo.Painter.TOOLTYPE_ERASEALL];
+
+Neo.EraserTip.prototype.init = function(name, params) {
+ this.drawOnce = false;
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EraserTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ if (this.drawOnce == false) {
+ this.draw();
+ this.drawOnce = true;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.EraserTip.prototype.draw = function() {
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ var img = new Image();
+
+ img.src = Neo.ToolTip.eraser;
+ img.onload = function() {
+ ctx.drawImage(img, 0, 0);
+ };
+};
+
+/*
+-------------------------------------------------------------------------
+ EffectTip
+-------------------------------------------------------------------------
+*/
+
+Neo.effectTip;
+
+Neo.EffectTip = function() {};
+Neo.EffectTip.prototype = new Neo.ToolTip();
+
+Neo.EffectTip.prototype.toolStrings = ["Cuadrado", "Cuadrado", "Circulo", "Circulo"];
+Neo.EffectTip.prototype.tools = [Neo.Painter.TOOLTYPE_RECTFILL,
+ Neo.Painter.TOOLTYPE_RECT,
+ Neo.Painter.TOOLTYPE_ELLIPSEFILL,
+ Neo.Painter.TOOLTYPE_ELLIPSE];
+
+Neo.EffectTip.prototype.hasTintImage = true;
+Neo.EffectTip.prototype.toolIcons = [Neo.ToolTip.rectfill,
+ Neo.ToolTip.rect,
+ Neo.ToolTip.ellipsefill,
+ Neo.ToolTip.ellipse];
+
+Neo.EffectTip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EffectTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+-------------------------------------------------------------------------
+ Effect2Tip
+-------------------------------------------------------------------------
+*/
+
+Neo.effect2Tip;
+
+Neo.Effect2Tip = function() {};
+Neo.Effect2Tip.prototype = new Neo.ToolTip();
+
+Neo.Effect2Tip.prototype.toolStrings = ["Copiar", "Unir",
+ "Cortar",
+ "Inv. Izq/Der", "Inv. Arr/Aba", "Inclinar"];
+Neo.Effect2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_COPY,
+ Neo.Painter.TOOLTYPE_MERGE,
+ Neo.Painter.TOOLTYPE_BLURRECT,
+ Neo.Painter.TOOLTYPE_FLIP_H,
+ Neo.Painter.TOOLTYPE_FLIP_V,
+ Neo.Painter.TOOLTYPE_TURN];
+
+Neo.Effect2Tip.prototype.hasTintImage = true;
+Neo.Effect2Tip.prototype.toolIcons = [Neo.ToolTip.copy,
+ Neo.ToolTip.merge,
+ Neo.ToolTip.blurrect,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip];
+
+Neo.Effect2Tip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+
+ this.img = document.createElement("img");
+ this.img.src = Neo.ToolTip.copy2;
+ this.element.appendChild(this.img);
+ return this;
+};
+
+Neo.Effect2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+-------------------------------------------------------------------------
+ MaskTip
+-------------------------------------------------------------------------
+*/
+
+Neo.maskTip;
+
+Neo.MaskTip = function() {};
+Neo.MaskTip.prototype = new Neo.ToolTip();
+
+Neo.MaskTip.prototype.toolStrings = ["Normal", "Masc.", "Masc. Inv.", "Adicion", "Substrac"];
+
+Neo.MaskTip.prototype.init = function(name, params) {
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.MaskTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ Neo.painter.maskColor = Neo.painter.foregroundColor;
+
+ } else {
+ var length = this.toolStrings.length;
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ Neo.painter.maskType = this.mode;
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.MaskTip.prototype.update = function() {
+ this.draw(Neo.painter.maskColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.MaskTip.prototype.draw = function(c) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ ctx.fillStyle = c;
+ ctx.fillRect(1, 1, 43, 9);
+};
+
+/*
+-------------------------------------------------------------------------
+ DrawTip
+-------------------------------------------------------------------------
+*/
+
+Neo.drawTip;
+
+Neo.DrawTip = function() {};
+Neo.DrawTip.prototype = new Neo.ToolTip();
+
+Neo.DrawTip.prototype.toolStrings = ["Libre", "Linea", "Curva"];
+
+Neo.DrawTip.prototype.hasTintImage = true;
+Neo.DrawTip.prototype.toolIcons = [Neo.ToolTip.freehand,
+ Neo.ToolTip.line,
+ Neo.ToolTip.bezier];
+
+Neo.DrawTip.prototype.init = function(name, params) {
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.DrawTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ var length = this.toolStrings.length;
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ Neo.painter.drawType = this.mode;
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.DrawTip.prototype.update = function() {
+ this.mode = Neo.painter.drawType;
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+-------------------------------------------------------------------------
+ ColorSlider
+-------------------------------------------------------------------------
+*/
+
+Neo.sliders = [];
+
+Neo.ColorSlider = function() {};
+
+Neo.ColorSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = 0;
+ this.type = this.params.type;
+
+ this.element.className = "colorSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>";
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED:
+ this.prefix = "R";
+ this.slider.style.backgroundColor = "#fa9696";
+ break;
+ case Neo.SLIDERTYPE_GREEN:
+ this.prefix = "G";
+ this.slider.style.backgroundColor = "#82f238";
+ break;
+ case Neo.SLIDERTYPE_BLUE:
+ this.prefix = "B";
+ this.slider.style.backgroundColor = "#8080ff";
+ break;
+ case Neo.SLIDERTYPE_ALPHA:
+ this.prefix = "A";
+ this.slider.style.backgroundColor = "#aaaaaa";
+ this.value = 255;
+ break;
+ }
+
+ this.update();
+ return this;
+};
+
+Neo.ColorSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.slide(x, y);
+ }
+};
+
+Neo.ColorSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+};
+
+Neo.ColorSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.ColorSlider.prototype.shift = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+
+ value = Math.max(Math.min(v, 255), min);
+ if (this.value > value || this.value == 255) {
+ this.value--;
+ } else {
+ this.value++;
+ }
+ this.value = Math.max(Math.min(this.value, 255), min);
+ this.value0 = this.value;
+ this.x0 = x;
+ }
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+
+ Neo.painter.setColor(r<<16 | g<<8 | b);
+ Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.slide = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ value = Math.round(v / 5) * 5;
+
+ this.value0 = value;
+ this.x0 = x;
+
+ } else {
+ var d = (x - this.x0) / 3.0;
+ value = this.value0 + d;
+ }
+
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+ this.value = Math.max(Math.min(value, 255), min);
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+
+ Neo.painter.setColor(r<<16 | g<<8 | b);
+// Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.update = function() {
+ var color = Neo.painter.getColor();
+ var alpha = Neo.painter.alpha * 255;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED: this.value = (color & 0x0000ff); break;
+ case Neo.SLIDERTYPE_GREEN: this.value = (color & 0x00ff00) >> 8; break;
+ case Neo.SLIDERTYPE_BLUE: this.value = (color & 0xff0000) >> 16; break;
+ case Neo.SLIDERTYPE_ALPHA: this.value = alpha; break;
+ }
+
+ var width = this.value * 49.0 / 255.0;
+ width = Math.max(Math.min(48, width), 1);
+
+ this.slider.style.width = width.toFixed(2) + "px";
+ this.label.innerHTML = this.prefix + this.value.toFixed(0);
+};
+
+/*
+-------------------------------------------------------------------------
+ SizeSlider
+-------------------------------------------------------------------------
+*/
+
+Neo.SizeSlider = function() {};
+
+Neo.SizeSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = this.value0 = 1;
+
+ this.element.className = "sizeSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>"
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+ this.update();
+ return this;
+};
+
+Neo.SizeSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.value0 = this.value;
+ this.y0 = y;
+ this.slide(x, y);
+ }
+};
+
+Neo.SizeSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+};
+
+Neo.SizeSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.SizeSlider.prototype.shift = function(x, y) {
+ var value0 = Neo.painter.lineWidth;
+ var value;
+
+ if (!Neo.painter.tool.alt) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+
+ value = Math.max(Math.min(v, 30), 1);
+ if (value0 > value || value0 == 30) {
+ value0--;
+ } else {
+ value0++;
+ }
+ this.setSize(value0);
+ }
+};
+
+Neo.SizeSlider.prototype.slide = function(x, y) {
+ var value;
+ if (!Neo.painter.tool.alt) {
+ if (x >= 0 && x < 48 && y >= 0 && y < 41) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+ value = v;
+
+ this.value0 = value;
+ this.y0 = y;
+
+ } else {
+ var d = (y - this.y0) / 7.0;
+ value = this.value0 + d;
+ }
+ } else {
+ // Ctrl+Alt+ドラッグでサイズ変更するとき
+ var d = y - this.y0;
+ value = this.value0 + d;
+ }
+
+ value = Math.max(Math.min(value, 30), 1);
+ this.setSize(value);
+};
+
+Neo.SizeSlider.prototype.setSize = function(value) {
+ value = Math.round(value);
+ Neo.painter.lineWidth = Math.max(Math.min(30, value), 1);
+
+ var tool = Neo.painter.getCurrentTool();
+ if (tool) {
+ if (tool.type == Neo.Painter.TOOLTYPE_BRUSH) {
+ Neo.painter.alpha = tool.getAlpha();
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA].update();
+
+ } else if (tool.type == Neo.Painter.TOOLTYPE_TEXT) {
+ Neo.painter.updateInputText();
+ }
+ }
+ this.update();
+};
+
+Neo.SizeSlider.prototype.update = function() {
+ this.value = Neo.painter.lineWidth;
+
+ var height = this.value * 33.0 / 30.0;
+ height = Math.max(Math.min(34, height), 1);
+
+ this.slider.style.height = height.toFixed(2) + "px";
+ this.label.innerHTML = this.value + "px";
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+};
+
+/*
+-------------------------------------------------------------------------
+ LayerControl
+-------------------------------------------------------------------------
+*/
+
+Neo.LayerControl = function() {};
+Neo.LayerControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+
+ var ref = this;
+
+ var mousedown = (window.PointerEvent) ? "onpointerdown" : "onmousedown";
+ this.element[mousedown] = function(e) { ref._mouseDownHandler(e); }
+ this.element.className = "layerControl";
+ this.element.innerHTML = "<div class='bg'></div><div class='label0'>Capa0</div><div class='label1'>Capa1</div><div class='line1'></div><div class='line0'></div>";
+
+ this.bg = this.element.getElementsByClassName('bg')[0];
+ this.label0 = this.element.getElementsByClassName('label0')[0];
+ this.label1 = this.element.getElementsByClassName('label1')[0];
+ this.line0 = this.element.getElementsByClassName('line0')[0];
+ this.line1 = this.element.getElementsByClassName('line1')[0];
+
+ this.line0.style.display = "none";
+ this.line1.style.display = "none";
+ this.label1.style.display = "none";
+
+ this.update();
+ return this;
+};
+
+Neo.LayerControl.prototype._mouseDownHandler = function(e) {
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ var visible = Neo.painter.visible[Neo.painter.current];
+ Neo.painter.visible[Neo.painter.current] = (visible) ? false : true;
+
+ } else {
+ var current = Neo.painter.current;
+ Neo.painter.current = (current) ? 0 : 1
+ }
+ Neo.painter.updateDestCanvas(0, 0, Neo.painter.canvasWidth, Neo.painter.canvasHeight);
+ if (Neo.painter.tool.type == Neo.Painter.TOOLTYPE_PASTE) {
+ Neo.painter.tool.drawCursor(Neo.painter);
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.LayerControl.prototype.update = function() {
+ this.label0.style.display = (Neo.painter.current == 0) ? "block" : "none";
+ this.label1.style.display = (Neo.painter.current == 1) ? "block" : "none";
+ this.line0.style.display = (Neo.painter.visible[0]) ? "none" : "block";
+ this.line1.style.display = (Neo.painter.visible[1]) ? "none" : "block";
+};
+
+/*
+-------------------------------------------------------------------------
+ ReserveControl
+-------------------------------------------------------------------------
+*/
+Neo.reserveControls = [];
+
+Neo.ReserveControl = function() {};
+Neo.ReserveControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ var ref = this;
+
+ var mousedown = (window.PointerEvent) ? "onpointerdown" : "onmousedown";
+ this.element[mousedown] = function(e) { ref._mouseDownHandler(e); }
+ this.element.className = "reserve";
+
+ var index = parseInt(this.name.slice(7)) - 1;
+ this.element.style.top = "1px";
+ this.element.style.left = (index * 15 + 2) + "px";
+
+ this.reserve = Neo.clone(Neo.config.reserves[index]);
+ this.update();
+
+ Neo.reserveControls.push(this);
+ return this;
+};
+
+Neo.ReserveControl.prototype._mouseDownHandler = function(e) {
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.save();
+ } else {
+ this.load();
+ }
+ this.update();
+};
+
+Neo.ReserveControl.prototype.load = function() {
+ Neo.painter.setToolByType(this.reserve.tool)
+ Neo.painter.foregroundColor = this.reserve.color;
+ Neo.painter.lineWidth = this.reserve.size;
+ Neo.painter.alpha = this.reserve.alpha;
+
+ switch (this.reserve.tool) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ Neo.painter.drawType = this.reserve.drawType;
+ };
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.save = function() {
+ this.reserve.color = Neo.painter.foregroundColor;
+ this.reserve.size = Neo.painter.lineWidth;
+ this.reserve.drawType = Neo.painter.drawType;
+ this.reserve.alpha = Neo.painter.alpha;
+ this.reserve.tool = Neo.painter.tool.getType();
+ this.element.style.backgroundColor = this.reserve.color;
+ this.update();
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.update = function() {
+ this.element.style.backgroundColor = this.reserve.color;
+};
+
+/*
+-------------------------------------------------------------------------
+ ScrollBarButton
+-------------------------------------------------------------------------
+*/
+
+Neo.scrollH;
+Neo.scrollV;
+
+Neo.ScrollBarButton = function() {};
+Neo.ScrollBarButton.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.element.innerHTML = "<div></div>";
+ this.barButton = this.element.getElementsByTagName("div")[0];
+ this.element['data-bar'] = true;
+ this.barButton['data-bar'] = true;
+
+ if (name == "scrollH") Neo.scrollH = this;
+ if (name == "scrollV") Neo.scrollV = this;
+ return this;
+};
+
+Neo.ScrollBarButton.prototype.update = function(oe) {
+ if (this.name == "scrollH") {
+ var a = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var barWidth = Math.ceil(oe.destCanvas.width * a);
+ var barX = (oe.scrollBarX) * (oe.destCanvas.width - barWidth);
+ this.barButton.style.width = (Math.ceil(barWidth) - 4) + "px";
+ this.barButton.style.left = Math.floor(barX) + "px";
+
+ } else {
+ var a = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barHeight = Math.ceil(oe.destCanvas.height * a);
+ var barY = (oe.scrollBarY) * (oe.destCanvas.height - barHeight);
+ this.barButton.style.height = (Math.ceil(barHeight) - 4) + "px";
+ this.barButton.style.top = Math.floor(barY) + "px";
+ }
+};
+
diff --git a/static/js/paintbbs/PaintBBS-1.3.4.css b/static/js/paintbbs/PaintBBS-1.3.4.css
new file mode 100644
index 0000000..2e5b4f7
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.3.4.css
@@ -0,0 +1,547 @@
+.NEO {
+ margin:0;
+ line-height:18px;
+
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+
+ touch-callout: none;
+ -webkit-touch-callout: none;
+}
+
+.NEO *:active,
+.NEO *:hover {
+ cursor: default;
+}
+
+.NEO #container{
+ width: 100%;
+ height: 100%;
+ position: relative;
+ border: 1px dotted transparent;
+}
+
+.NEO #center{
+ display: table;
+ position: relative;
+ height: 100%;
+ margin: auto;
+}
+
+.NEO #toolsWrapper{
+ width: 52px;
+ display: table;
+ position:absolute;
+ top: 0;
+ right: -3px;
+}
+
+.NEO #tools{
+ width: 52px;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterContainer{
+ display:table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterWrapper{
+ padding: 0 55px 0 0;
+ position: relative;
+
+ float: right; /* なぜかChrome55でずれるので対策 */
+}
+
+.NEO #upper {
+ position: absolute;
+ right: 0;
+
+ height:30px;
+ padding-right: 75px; //20px;
+ text-align:right;
+}
+
+.NEO #lower {
+ height:30px;
+}
+
+.NEO #painter {
+ position: relative;
+ padding: 20px 20px 20px 20px;
+
+ margin-top: 30px;
+}
+
+.NEO #canvas {
+ position: relative;
+ width: 300px;
+ height: 300px;
+ background-color: white;
+}
+
+.NEO #headerButtons {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+}
+
+.NEO #footerButtons {
+ position: absolute;
+ bottom: 5px;
+ left: 5px;
+}
+
+.NEO #window { float: left; }
+
+/*
+-----------------------
+ Modal Window
+-----------------------
+*/
+
+.NEO #pageView{
+ background-color: white;
+}
+
+.NEO #windowView{
+ z-index: 9999;
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ background-color: white;
+}
+
+/*
+-----------------------
+ Controls
+-----------------------
+*/
+
+.NEO #zoomMinus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+ margin-left:1px;
+}
+
+.NEO #zoomPlus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+}
+
+.NEO #zoomMinusWrapper {
+ position: absolute;
+ right: -20px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-align:center;
+}
+
+.NEO #zoomPlusWrapper {
+ position: absolute;
+ left: -21px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-overflow: hidden;
+ text-align:center;
+}
+
+.NEO #scrollH {
+ position: absolute;
+ left: 1px;
+ bottom: -20px;
+ width: calc(100% - 2px);
+ height: 18px;
+}
+
+.NEO #scrollV {
+ position: absolute;
+ right: -20px;
+ top: 1px;
+ width: 18px;
+ height: calc(100% - 2px);
+}
+
+.NEO #scrollH div {
+ position: absolute;
+ width: 50px;
+ height: 16px;
+}
+
+.NEO #scrollV div {
+ position: absolute;
+ width: 16px;
+ height: 50px;
+}
+
+.NEO #scrollH div:hover {}
+.NEO #scrollV div:hover {}
+
+.NEO #neoWarning {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ color: red;
+ pointer-events: none;
+ text-align: left;
+ transition: all 2s;
+}
+
+/*
+-----------------------
+ Widgets
+-----------------------
+*/
+
+.NEO .buttonOff {
+ display: inline-block;
+ border: 1px solid white;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+
+}
+
+.NEO .buttonOff:hover {}
+
+.NEO .buttonOff:active,
+.NEO .buttonOn {
+ display: inline-block;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+}
+
+.NEO #right { display: inline-block; float: right; margin-left: 10px; }
+
+.NEO .toolTipOff,
+.NEO .toolTipFixed {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid #ffffff;
+ border-left: 1px solid #ffffff;
+ border-right: 1px solid #9397b2;
+ border-bottom: 1px solid #9397b2;
+}
+
+.NEO .toolTipOn {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid #ffffff;
+ border-bottom: 1px solid #ffffff;
+}
+
+
+
+.NEO .toolTipOff canvas,
+.NEO .toolTipOn canvas,
+.NEO .toolTipFixed canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.NEO .toolTipOff .label,
+.NEO .toolTipOn .label,
+.NEO .toolTipFixed .label {
+ position: absolute;
+ bottom: -4px;
+ left: 1px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: -1px;
+ overflow: hidden !important;
+}
+
+.NEO .colorTips {
+ position:relative;
+ width: 48px;
+ height: 144px;
+ padding: 0;
+ margin: 0;
+ margin-top: 4px;
+ margin-left: 0px;
+}
+
+.NEO .colorTipOff {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOff img {
+ left: 0;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorTipOn {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOn img {
+ left: -22px;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorSlider {
+ width: 48px;
+ height:13px;
+ position: relative;
+ margin-top: 3px;
+}
+
+.NEO .colorSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .colorSlider .slider {
+ position: absolute;
+ height: 100%;
+ left: 0px;
+ width: 50%;
+ background-color: #fa9696;
+ box-shadow: -1px 0 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .colorSlider .hit {
+ position:absolute;
+ width: 60px;
+ height: 13px;
+ left: -6px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .sizeSlider {
+ width: 48px;
+ height:33px;
+ position: relative;
+ margin-top: 4px;
+}
+
+.NEO .sizeSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .sizeSlider .slider {
+ position: absolute;
+ width: 100%;
+ top: 0px;
+ height: 33%;
+ background-color: #82f238;
+ box-shadow: 0 -1px 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .sizeSlider .hit {
+ position:absolute;
+ width: 48px;
+ height: 41px;
+ top: -4px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .reserveControl {
+ width: 48px;
+ height: 13px;
+ position: relative;
+}
+
+.NEO .reserveControl .reserve {
+ position: absolute;
+ width: 11px;
+ height: 8px;
+ background-color: white;
+}
+
+.NEO .layerControl {
+ width: 48px;
+ height: 20px;
+ position: relative;
+ margin-top: 6px;
+}
+
+.NEO .layerControl .bg {
+ position: absolute;
+ width: 44px;
+ height: 9px;
+ margin: 0;
+
+ top: 0px;
+ left: 2px;
+}
+
+.NEO .layerControl .line1 {
+ position: absolute;
+ width: 50px;
+ height:10px;
+ margin: 0;
+ padding: 0;
+
+ top: 0px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .line0 {
+ position: absolute;
+ width: 50px;
+ height: 10px;
+ margin: 0;
+ padding: 0;
+
+ top: 10px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .label1 {
+ position: absolute;
+ left: 2px;
+ Top: -4px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+.NEO .layerControl .label0 {
+ position: absolute;
+ left: 2px;
+ Top: 6px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+/*
+-----------------------
+ InputText
+-----------------------
+*/
+
+.NEO .inputText {
+ z-index: 100000;
+ position: absolute;
+
+ text-align: left;
+ white-space: nowrap;
+ color: #0000ff;
+
+ font-family: 'Arial';
+ padding: 1px 5px 1px 5px;
+ font-size: 32px;
+
+ line-height: 40px;
+ height: 40px;
+ min-width: 10em;
+
+ bottom: 0px;
+ left: 250px;
+
+ border: 1px solid #aaa;
+ background-color: white;
+}
+
+*[contenteditable] {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto !important;
+}
+
+#testtext {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto;
+}
+
+[contenteditable="true"]:focus {
+ outline: 1px solid #b1d6fd;
+ border: 1px solid #b1d6fd;
+}
+
diff --git a/static/js/paintbbs/PaintBBS-1.3.4.js b/static/js/paintbbs/PaintBBS-1.3.4.js
new file mode 100644
index 0000000..8450a49
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.3.4.js
@@ -0,0 +1,6171 @@
+'use strict';
+
+document.addEventListener("DOMContentLoaded", function() {
+ Neo.init();
+
+ if (!navigator.userAgent.match("Electron")) {
+ Neo.start();
+ }
+});
+
+
+var Neo = function() {};
+
+Neo.version = "1.3.4";
+Neo.painter;
+Neo.fullScreen = false;
+Neo.uploaded = false;
+
+Neo.config = {
+ width: 300,
+ height: 300,
+
+ colors: [
+ "#000000", "#FFFFFF",
+ "#B47575", "#888888",
+ "#FA9696", "#C096C0",
+ "#FFB6FF", "#8080FF",
+ "#25C7C9", "#E7E58D",
+ "#E7962D", "#99CB7B",
+ "#FCECE2", "#F9DDCF"
+ ]
+};
+
+Neo.reservePen = {};
+Neo.reserveEraser = {};
+
+Neo.SLIDERTYPE_RED = 0;
+Neo.SLIDERTYPE_GREEN = 1;
+Neo.SLIDERTYPE_BLUE = 2;
+Neo.SLIDERTYPE_ALPHA = 3;
+Neo.SLIDERTYPE_SIZE = 4;
+
+document.neo = Neo;
+
+Neo.init = function() {
+ var applets = document.getElementsByTagName('applet');
+ if (applets.length == 0) {
+ applets = document.getElementsByTagName('applet-dummy');
+ }
+
+ for (var i = 0; i < applets.length; i++) {
+ var applet = applets[i];
+ var name = applet.attributes.name.value;
+ if (name == "paintbbs") {
+ Neo.applet = applet;
+ Neo.initConfig(applet);
+ Neo.createContainer(applet);
+ Neo.init2();
+ }
+ }
+};
+
+Neo.init2 = function() {
+ var pageview = document.getElementById("pageView");
+ pageview.style.width = Neo.config.applet_width + "px";
+ pageview.style.height = Neo.config.applet_height + "px";
+
+ Neo.canvas = document.getElementById("canvas");
+ Neo.container = document.getElementById("container");
+ Neo.toolsWrapper = document.getElementById("toolsWrapper");
+
+ Neo.painter = new Neo.Painter();
+ Neo.painter.build(Neo.canvas, Neo.config.width, Neo.config.height);
+
+ Neo.container.oncontextmenu = function() {return false;};
+
+ // 続きから描く
+ if (Neo.config.image_canvas) {
+ Neo.painter.loadImage(Neo.config.image_canvas);
+ }
+
+ // 描きかけの画像が見つかったとき
+ Neo.storage = (Neo.isMobile()) ? localStorage : sessionStorage;
+ if (Neo.storage.getItem('timestamp')) {
+ setTimeout(function () {
+ if (confirm(Neo.translate("以前の編集データを復元しますか?"))) {
+ Neo.painter.loadSession();
+ }
+ }, 1);
+ }
+
+ window.addEventListener("pagehide", function(e) {
+ if (!Neo.uploaded) {
+ Neo.painter.saveSession();
+ } else {
+ Neo.painter.clearSession();
+ }
+ }, false);
+}
+
+Neo.initConfig = function(applet) {
+ if (applet) {
+ var name = applet.attributes.name.value || "neo";
+ var appletWidth = applet.attributes.width;
+ var appletHeight = applet.attributes.height;
+ if (appletWidth) Neo.config.applet_width = parseInt(appletWidth.value);
+ if (appletHeight) Neo.config.applet_height = parseInt(appletHeight.value);
+
+ var params = applet.getElementsByTagName('param');
+ for (var i = 0; i < params.length; i++) {
+ var p = params[i];
+ Neo.config[p.name] = Neo.fixConfig(p.value);
+
+ if (p.name == "image_width") Neo.config.width = parseInt(p.value);
+ if (p.name == "image_height") Neo.config.height = parseInt(p.value);
+ }
+
+ var emulationMode = Neo.config.neo_emulation_mode || "2.22_8x";
+ Neo.config.neo_alt_translation = emulationMode.slice(-1).match(/x/i);
+
+ Neo.readStyles();
+ Neo.applyStyle("color_bk", "#ccccff");
+ Neo.applyStyle("color_bk2", "#bbbbff");
+ Neo.applyStyle("color_tool_icon", "#e8dfae");
+ Neo.applyStyle("color_icon", "#ccccff");
+ Neo.applyStyle("color_iconselect", "#ffaaaa");
+ Neo.applyStyle("color_text", "#666699");
+ Neo.applyStyle("color_bar", "#6f6fae");
+ Neo.applyStyle("tool_color_button", "#e8dfae");
+ Neo.applyStyle("tool_color_button2", "#f8daaa");
+ Neo.applyStyle("tool_color_text", "#773333");
+ Neo.applyStyle("tool_color_bar", "#ddddff");
+ Neo.applyStyle("tool_color_frame", "#000000");
+
+ var e = document.getElementById("container");
+ Neo.config.inherit_color = Neo.getInheritColor(e);
+ if (!Neo.config.color_frame) Neo.config.color_frame = Neo.config.color_text;
+ }
+
+ Neo.config.reserves = [
+ { size:1,
+ color:"#000000", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_PEN,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:5,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:10,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ ];
+
+ Neo.reservePen = Neo.clone(Neo.config.reserves[0]);
+ Neo.reserveEraser = Neo.clone(Neo.config.reserves[1]);
+};
+
+Neo.fixConfig = function(value) {
+ // javaでは"#12345"を色として解釈するがjavascriptでは"#012345"に変換しないとだめ
+ if (value.match(/^#[0-9a-fA-F]{5}$/)) {
+ value = "#0" + value.slice(1);
+ }
+ return value;
+};
+
+Neo.initSkin = function() {
+ var sheet = document.styleSheets[0];
+ if (!sheet) {
+ var style = document.createElement("style");
+ document.head.appendChild(style); // must append before you can access sheet property
+ sheet = style.sheet;
+ }
+
+ Neo.styleSheet = sheet;
+
+ var lightBorder = Neo.multColor(Neo.config.color_icon, 1.3);
+ var darkBorder = Neo.multColor(Neo.config.color_icon, 0.7);
+ var lightBar = Neo.multColor(Neo.config.color_bar, 1.3);
+ var darkBar = Neo.multColor(Neo.config.color_bar, 0.7);
+ var bgImage = Neo.backgroundImage();
+
+ Neo.addRule(".NEO #container", "background-image", "url(" + bgImage + ")");
+ Neo.addRule(".NEO .colorSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .sizeSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label1", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label0", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOn .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOff .label", "color", Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO #toolSet", "background-color", Neo.config.color_bk);
+ Neo.addRule(".NEO #tools", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .bg", "border-bottom", "1px solid " + Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO .buttonOn", "color", Neo.config.color_text);
+ Neo.addRule(".NEO .buttonOff", "color", Neo.config.color_text);
+
+ Neo.addRule(".NEO .buttonOff", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-top", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-left", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "box-shadow", "0 0 0 1px " + Neo.config.color_icon + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:hover", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff:hover", "border-top", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "border-left", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "background-color", darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-top", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-left", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+
+ Neo.addRule(".NEO #canvas", "border", "1px solid " + Neo.config.color_frame);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "box-shadow", "0 0 0 1px white" + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "background-color", Neo.config.color_bar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "box-shadow", "0 0 0 1px " + Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH div:hover, .NEO #scrollV div:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-top", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-left", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-right", "1px solid " + darkBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-bottom", "1px solid " + darkBar);
+
+ Neo.addRule(".NEO .toolTipOn", "background-color", Neo.multColor(Neo.config.tool_color_button, 0.7));
+ Neo.addRule(".NEO .toolTipOff", "background-color", Neo.config.tool_color_button);
+ Neo.addRule(".NEO .toolTipFixed", "background-color", Neo.config.tool_color_button2);
+
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .layerControl", "background-color", Neo.config.tool_color_bar);
+
+ Neo.addRule(".NEO .colorTipOn, .NEO .colorTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipOn, .NEO .toolTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipFixed", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .layerControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl .reserve", "border", "1px solid " + Neo.config.tool_color_frame);
+
+ if (navigator.language.indexOf("ja") != 0) {
+ var labels = ["Fixed", "On", "Off"];
+ for (var i = 0; i < labels.length; i++) {
+ var selector = ".NEO .toolTip" + labels[i] + " .label";
+ Neo.addRule(selector, "letter-spacing", "0px !important");
+ }
+ }
+};
+
+Neo.addRule = function(selector, styleName, value, sheet) {
+ if (!sheet) sheet = Neo.styleSheet;
+ if (sheet.addRule) {
+ sheet.addRule(selector, styleName + ":" + value, sheet.rules.length);
+
+ } else if (sheet.insertRule) {
+ var rule = selector + "{" + styleName + ":" + value + "}";
+ var index = sheet.cssRules.length;
+ sheet.insertRule(rule, index);
+ }
+};
+
+Neo.readStyles = function() {
+ Neo.rules = {};
+ for (var i = 0; i < document.styleSheets.length; i++) {
+ Neo.readStyle(document.styleSheets[i]);
+ }
+};
+
+Neo.readStyle = function(sheet) {
+ try {
+ var rules = sheet.cssRules;
+ for (var i = 0; i < rules.length; i++) {
+ var rule = rules[i];
+ if (rule.styleSheet) {
+ Neo.readStyle(rule.styleSheet);
+ continue;
+ }
+
+ var selector = rule.selectorText
+ if (selector) {
+ selector = selector.replace(/^(.NEO\s+)?\./, '')
+
+ var css = rule.cssText || rule.style.cssText;
+ var result = css.match(/color:\s*(.*)\s*;/)
+ if (result) {
+ var hex = Neo.colorNameToHex(result[1]);
+ if (hex) {
+ Neo.rules[selector] = hex;
+ }
+ }
+ }
+ }
+ } catch (e) {}
+};
+
+Neo.applyStyle = function(name, defaultColor) {
+ if (Neo.config[name] == undefined) {
+ Neo.config[name] = Neo.rules[name] || defaultColor;
+ }
+};
+
+Neo.getInheritColor = function(e) {
+ var result = "#000000";
+ while (e && e.style) {
+ if (e.style.color != "") {
+ result = e.style.color;
+ break;
+ }
+ if (e.attributes["text"]) {
+ result = e.attributes["text"].value;
+ break;
+ }
+ e = e.parentNode;
+ }
+ return result;
+};
+
+Neo.backgroundImage = function() {
+ var c1 = Neo.painter.getColor(Neo.config.color_bk) | 0xff000000;
+ var c2 = Neo.painter.getColor(Neo.config.color_bk2) | 0xff000000;
+ var bgCanvas = document.createElement("canvas");
+ bgCanvas.width = 16;
+ bgCanvas.height = 16;
+ var ctx = bgCanvas.getContext("2d");
+ var imageData = ctx.getImageData(0, 0, 16, 16);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ for (var y = 0; y < 16; y++) {
+ for (var x = 0; x < 16; x++) {
+ buf32[index++] = (x == 14 || y == 14) ? c2 : c1;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+ return bgCanvas.toDataURL('image/png');
+};
+
+Neo.multColor = function(c, scale) {
+ var r = Math.round(parseInt(c.substr(1, 2), 16) * scale);
+ var g = Math.round(parseInt(c.substr(3, 2), 16) * scale);
+ var b = Math.round(parseInt(c.substr(5, 2), 16) * scale);
+ r = ("0" + Math.min(Math.max(r, 0), 255).toString(16)).substr(-2);
+ g = ("0" + Math.min(Math.max(g, 0), 255).toString(16)).substr(-2);
+ b = ("0" + Math.min(Math.max(b, 0), 255).toString(16)).substr(-2);
+ return '#' + r + g + b;
+};
+
+Neo.colorNameToHex = function(name) {
+ var colors = {"aliceblue":"#f0f8ff", "antiquewhite":"#faebd7", "aqua":"#00ffff","aquamarine":"#7fffd4", "azure":"#f0ffff", "beige":"#f5f5dc", "bisque":"#ffe4c4", "black":"#000000", "blanchedalmond":"#ffebcd", "blue":"#0000ff", "blueviolet":"#8a2be2", "brown":"#a52a2a", "burlywood":"#deb887", "cadetblue":"#5f9ea0", "chartreuse":"#7fff00", "chocolate":"#d2691e", "coral":"#ff7f50", "cornflowerblue":"#6495ed", "cornsilk":"#fff8dc", "crimson":"#dc143c", "cyan":"#00ffff", "darkblue":"#00008b", "darkcyan":"#008b8b", "darkgoldenrod":"#b8860b", "darkgray":"#a9a9a9", "darkgreen":"#006400", "darkkhaki":"#bdb76b", "darkmagenta":"#8b008b", "darkolivegreen":"#556b2f", "darkorange":"#ff8c00", "darkorchid":"#9932cc", "darkred":"#8b0000", "darksalmon":"#e9967a", "darkseagreen":"#8fbc8f", "darkslateblue":"#483d8b", "darkslategray":"#2f4f4f", "darkturquoise":"#00ced1", "darkviolet":"#9400d3", "deeppink":"#ff1493", "deepskyblue":"#00bfff", "dimgray":"#696969", "dodgerblue":"#1e90ff", "firebrick":"#b22222", "floralwhite":"#fffaf0", "forestgreen":"#228b22", "fuchsia":"#ff00ff", "gainsboro":"#dcdcdc", "ghostwhite":"#f8f8ff", "gold":"#ffd700", "goldenrod":"#daa520", "gray":"#808080", "green":"#008000", "greenyellow":"#adff2f", "honeydew":"#f0fff0", "hotpink":"#ff69b4", "indianred ":"#cd5c5c", "indigo":"#4b0082", "ivory":"#fffff0", "khaki":"#f0e68c", "lavender":"#e6e6fa", "lavenderblush":"#fff0f5", "lawngreen":"#7cfc00", "lemonchiffon":"#fffacd", "lightblue":"#add8e6", "lightcoral":"#f08080", "lightcyan":"#e0ffff", "lightgoldenrodyellow":"#fafad2", "lightgrey":"#d3d3d3", "lightgreen":"#90ee90", "lightpink":"#ffb6c1", "lightsalmon":"#ffa07a", "lightseagreen":"#20b2aa", "lightskyblue":"#87cefa", "lightslategray":"#778899", "lightsteelblue":"#b0c4de", "lightyellow":"#ffffe0", "lime":"#00ff00", "limegreen":"#32cd32", "linen":"#faf0e6", "magenta":"#ff00ff", "maroon":"#800000", "mediumaquamarine":"#66cdaa", "mediumblue":"#0000cd", "mediumorchid":"#ba55d3", "mediumpurple":"#9370d8", "mediumseagreen":"#3cb371", "mediumslateblue":"#7b68ee", "mediumspringgreen":"#00fa9a", "mediumturquoise":"#48d1cc", "mediumvioletred":"#c71585", "midnightblue":"#191970", "mintcream":"#f5fffa", "mistyrose":"#ffe4e1", "moccasin":"#ffe4b5", "navajowhite":"#ffdead", "navy":"#000080", "oldlace":"#fdf5e6", "olive":"#808000", "olivedrab":"#6b8e23", "orange":"#ffa500", "orangered":"#ff4500", "orchid":"#da70d6", "palegoldenrod":"#eee8aa", "palegreen":"#98fb98", "paleturquoise":"#afeeee", "palevioletred":"#d87093", "papayawhip":"#ffefd5", "peachpuff":"#ffdab9", "peru":"#cd853f", "pink":"#ffc0cb", "plum":"#dda0dd", "powderblue":"#b0e0e6", "purple":"#800080", "rebeccapurple":"#663399", "red":"#ff0000", "rosybrown":"#bc8f8f", "royalblue":"#4169e1", "saddlebrown":"#8b4513", "salmon":"#fa8072", "sandybrown":"#f4a460", "seagreen":"#2e8b57", "seashell":"#fff5ee", "sienna":"#a0522d", "silver":"#c0c0c0", "skyblue":"#87ceeb", "slateblue":"#6a5acd", "slategray":"#708090", "snow":"#fffafa", "springgreen":"#00ff7f", "steelblue":"#4682b4", "tan":"#d2b48c", "teal":"#008080", "thistle":"#d8bfd8", "tomato":"#ff6347", "turquoise":"#40e0d0", "violet":"#ee82ee", "wheat":"#f5deb3", "white":"#ffffff", "whitesmoke":"#f5f5f5", "yellow":"#ffff00", "yellowgreen":"#9acd32"};
+
+ var rgb = name.toLowerCase().match(/rgb\((.*),(.*),(.*)\)/);
+ if (rgb) {
+ var r = ("0" + parseInt(rgb[1]).toString(16)).slice(-2)
+ var g = ("0" + parseInt(rgb[2]).toString(16)).slice(-2)
+ var b = ("0" + parseInt(rgb[3]).toString(16)).slice(-2)
+ return "#" + r + g + b
+ }
+
+ if (typeof colors[name.toLowerCase()] != 'undefined') {
+ return colors[name.toLowerCase()];
+ }
+ return false;
+};
+
+Neo.initComponents = function() {
+ document.getElementById("copyright").innerHTML += "v" + Neo.version;
+
+ // アプレットのborderの動作をエミュレート
+ if (navigator.userAgent.search("FireFox") > -1) {
+ var container = document.getElementById("container");
+ container.addEventListener("mousedown", function(e) {
+ container.style.borderColor = Neo.config.inherit_color;
+ e.stopPropagation();
+ }, false);
+ document.addEventListener("mousedown", function(e) {
+ container.style.borderColor = 'transparent';
+ }, false);
+ }
+
+ // ドラッグしたまま画面外に移動した時
+ document.addEventListener("mouseup", function(e) {
+ if (Neo.painter && !Neo.painter.isContainer(e.target)) {
+ Neo.painter.cancelTool(e.target);
+ }
+ }, false);
+
+ // 投稿に失敗する可能性があるときは警告を表示する
+ Neo.showWarning();
+
+ if (Neo.styleSheet) {
+ Neo.addRule("*", "user-select", "none");
+ Neo.addRule("*", "-webkit-user-select", "none");
+ Neo.addRule("*", "-ms-user-select", "none");
+ }
+}
+
+Neo.initButtons = function() {
+ new Neo.Button().init("undo").onmouseup = function() {
+ new Neo.UndoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("redo").onmouseup = function () {
+ new Neo.RedoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("window").onmouseup = function() {
+ new Neo.WindowCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("submit").onmouseup = function() {
+ new Neo.SubmitCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("copyright").onmouseup = function() {
+ new Neo.CopyrightCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomPlus").onmouseup = function() {
+ new Neo.ZoomPlusCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomMinus").onmouseup = function() {
+ new Neo.ZoomMinusCommand(Neo.painter).execute();
+ };
+
+ Neo.fillButton = new Neo.FillButton().init("fill");
+ Neo.rightButton = new Neo.RightButton().init("right");
+
+ if (Neo.isMobile()) {
+ Neo.rightButton.element.style.display = "block";
+ }
+
+ // toolTip
+ Neo.penTip = new Neo.PenTip().init("pen");
+ Neo.pen2Tip = new Neo.Pen2Tip().init("pen2");
+ Neo.effectTip = new Neo.EffectTip().init("effect");
+ Neo.effect2Tip = new Neo.Effect2Tip().init("effect2");
+ Neo.eraserTip = new Neo.EraserTip().init("eraser");
+ Neo.drawTip = new Neo.DrawTip().init("draw");
+ Neo.maskTip = new Neo.MaskTip().init("mask");
+
+ Neo.toolButtons = [Neo.fillButton,
+ Neo.penTip,
+ Neo.pen2Tip,
+ Neo.effectTip,
+ Neo.effect2Tip,
+ Neo.drawTip,
+ Neo.eraserTip];
+
+ // colorTip
+ for (var i = 1; i <= 14; i++) {
+ new Neo.ColorTip().init("color" + i, {index:i});
+ };
+
+ // colorSlider
+ Neo.sliders[Neo.SLIDERTYPE_RED] = new Neo.ColorSlider().init(
+ "sliderRed", {type:Neo.SLIDERTYPE_RED});
+ Neo.sliders[Neo.SLIDERTYPE_GREEN] = new Neo.ColorSlider().init(
+ "sliderGreen", {type:Neo.SLIDERTYPE_GREEN});
+ Neo.sliders[Neo.SLIDERTYPE_BLUE] = new Neo.ColorSlider().init(
+ "sliderBlue", {type:Neo.SLIDERTYPE_BLUE});
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA] = new Neo.ColorSlider().init(
+ "sliderAlpha", {type:Neo.SLIDERTYPE_ALPHA});
+
+ // sizeSlider
+ Neo.sliders[Neo.SLIDERTYPE_SIZE] = new Neo.SizeSlider().init(
+ "sliderSize", {type:Neo.SLIDERTYPE_SIZE});
+
+ // reserveControl
+ for (var i = 1; i <= 3; i++) {
+ new Neo.ReserveControl().init("reserve" + i, {index:i});
+ };
+
+ new Neo.LayerControl().init("layerControl");
+ new Neo.ScrollBarButton().init("scrollH");
+ new Neo.ScrollBarButton().init("scrollV");
+};
+
+Neo.start = function(isApp) {
+ if (!Neo.painter) return;
+
+ Neo.initSkin();
+ Neo.initComponents();
+ Neo.initButtons();
+
+ Neo.isApp = isApp;
+ if (Neo.applet) {
+ var name = Neo.applet.attributes.name.value || "paintbbs";
+ Neo.applet.outerHTML = "";
+ document[name] = Neo;
+
+ Neo.resizeCanvas();
+ Neo.container.style.visibility = "visible";
+
+ if (Neo.isApp) {
+ var ipc = require('electron').ipcRenderer;
+ ipc.sendToHost('neo-status', 'ok');
+
+ } else {
+ if (document.paintBBSCallback) {
+ document.paintBBSCallback('start');
+ }
+ }
+ }
+};
+
+Neo.isIE = function() {
+ var ms = false;
+ if (/MSIE 10/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 10
+ }
+ if (/MSIE 9/i.test(navigator.userAgent) ||
+ /rv:11.0/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 9 or 11
+ }
+ return ms
+};
+
+Neo.isMobile = function() {
+ return navigator.userAgent.match(/Android|iPhone|iPad|iPod/i);
+};
+
+Neo.showWarning = function() {
+ var futaba = location.hostname.match(/2chan.net/i);
+ var samplebbs = location.hostname.match(/neo.websozai.jp/i);
+
+ var chrome = navigator.userAgent.match(/Chrome\/(\d+)/i);
+ if (chrome && chrome.length > 1) chrome = chrome[1];
+
+ var edge = navigator.userAgent.match(/Edge\/(\d+)/i);
+ if (edge && edge.length > 1) edge = edge[1];
+
+ var ms = Neo.isIE();
+
+ var str = "";
+ if (futaba || samplebbs) {
+ if (ms || (edge && edge < 15)) {
+ str = Neo.translate("このブラウザでは<br>投稿に失敗することがあります<br>");
+ }
+ }
+
+ // もし<PARAM NAME="neo_warning" VALUE="...">があれば表示する
+ if (Neo.config.neo_warning) {
+ str += Neo.config.neo_warning;
+ }
+
+ var warning = document.getElementById("neoWarning")
+ warning.innerHTML = str;
+ setTimeout(function() { warning.style.opacity = "0"; }, 15000);
+};
+
+/*
+ -----------------------------------------------------------------------
+ UIの更新
+ -----------------------------------------------------------------------
+*/
+
+Neo.updateUI = function() {
+ var current = Neo.painter.tool.getToolButton();
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ if (current) {
+ if (current == toolTip) {
+ toolTip.setSelected(true);
+ toolTip.update();
+ } else {
+ toolTip.setSelected(false);
+ }
+ }
+ }
+ if (Neo.drawTip) {
+ Neo.drawTip.update();
+ }
+
+ Neo.updateUIColor(true, false);
+}
+
+Neo.updateUIColor = function(updateSlider, updateColorTip) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.update();
+ }
+
+ if (updateSlider) {
+ for (var i = 0; i < Neo.sliders.length; i++) {
+ var slider = Neo.sliders[i];
+ slider.update();
+ }
+ }
+
+ // パレットを変更するとき
+ if (updateColorTip) {
+ var colorTip = Neo.ColorTip.getCurrent();
+ if (colorTip) {
+ colorTip.setColor(Neo.painter.foregroundColor);
+ }
+ }
+};
+
+/*
+ -----------------------------------------------------------------------
+ リサイズ対応
+ -----------------------------------------------------------------------
+*/
+
+Neo.updateWindow = function() {
+ if (Neo.fullScreen) {
+ document.getElementById("windowView").style.display = "block";
+ document.getElementById("windowView").appendChild(Neo.container);
+
+ } else {
+ document.getElementById("windowView").style.display = "none";
+ document.getElementById("pageView").appendChild(Neo.container);
+ }
+ Neo.resizeCanvas();
+};
+
+Neo.resizeCanvas = function() {
+ var appletWidth = Neo.container.clientWidth;
+ var appletHeight = Neo.container.clientHeight;
+
+ var canvasWidth = Neo.painter.canvasWidth;
+ var canvasHeight = Neo.painter.canvasHeight;
+
+ var width0 = canvasWidth * Neo.painter.zoom;
+ var height0 = canvasHeight * Neo.painter.zoom;
+
+ var width = (width0 < appletWidth - 100) ? width0 : appletWidth - 100;
+ var height = (height0 < appletHeight - 120) ? height0 : appletHeight - 120;
+
+ //width, heightは偶数でないと誤差が出るため
+ width = Math.floor(width / 2) * 2;
+ height = Math.floor(height / 2) * 2;
+
+ Neo.painter.destWidth = width;
+ Neo.painter.destHeight = height;
+
+ Neo.painter.destCanvas.width = width;
+ Neo.painter.destCanvas.height = height;
+ Neo.painter.destCanvasCtx = Neo.painter.destCanvas.getContext("2d");
+ Neo.painter.destCanvasCtx.imageSmoothingEnabled = false;
+ Neo.painter.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ Neo.canvas.style.width = width + "px";
+ Neo.canvas.style.height = height + "px";
+
+ var top = (Neo.container.clientHeight - toolsWrapper.clientHeight) / 2;
+ Neo.toolsWrapper.style.top = ((top > 0) ? top : 0) + "px";
+
+ if (top < 0) {
+ var s = Neo.container.clientHeight / toolsWrapper.clientHeight;
+ Neo.toolsWrapper.style.transform =
+ "translate(0, " + top + "px) scale(1," + s + ")";
+ } else {
+ Neo.toolsWrapper.style.transform = "";
+ }
+
+ Neo.painter.setZoom(Neo.painter.zoom);
+ Neo.painter.updateDestCanvas(0, 0, canvasWidth, canvasHeight);
+};
+
+/*
+ -----------------------------------------------------------------------
+ 投稿
+ -----------------------------------------------------------------------
+*/
+
+Neo.clone = function(src) {
+ var dst = {};
+ for (var k in src) {
+ dst[k] = src[k];
+ }
+ return dst;
+};
+
+Neo.getSizeString = function(len) {
+ var result = String(len);
+ while (result.length < 8) {
+ result = "0" + result;
+ }
+ return result;
+};
+
+Neo.openURL = function(url) {
+ if (Neo.isApp) {
+ require('electron').shell.openExternal(url);
+
+ } else {
+ window.open(url, '_blank');
+ }
+};
+
+Neo.submit = function(board, blob, thumbnail, thumbnail2) {
+ var url = Neo.config.url_save;
+ var headerString = Neo.str_header || "";
+ console.log("submit url=" + url + " header=" + headerString);
+
+ if (document.paintBBSCallback) {
+ var result = document.paintBBSCallback('check')
+ if (result == 0 || result == "false") {
+ return;
+ }
+
+ result = document.paintBBSCallback('header')
+ if (result && typeof result == "string") {
+ headerString == result;
+ }
+ }
+ if (!headerString) headerString = Neo.config.send_header || "";
+
+ var imageType = Neo.config.send_header_image_type;
+ if (imageType && imageType == "true") {
+ headerString = "image_type=png&" + headerString
+ console.log("header=" + headerString);
+ }
+
+ var header = new Blob([headerString]);
+ var headerLength = this.getSizeString(header.size);
+ var imgLength = this.getSizeString(blob.size);
+
+ var array = ['P', // PaintBBS
+ headerLength,
+ header,
+ imgLength,
+ '\r\n',
+ blob];
+
+ if (thumbnail) {
+ var thumbnailLength = this.getSizeString(thumbnail.size);
+ array.push(thumbnailLength, thumbnail);
+ }
+ if (thumbnail2) {
+ var thumbnail2Length = this.getSizeString(thumbnail2.size);
+ array.push(thumbnail2Length, thumbnail2);
+ }
+
+ var body = new Blob(array, {type: 'application/octet-binary'}); //これが必要!!
+
+ var request = new XMLHttpRequest();
+ request.open("POST", url, true);
+
+ request.onload = function(e) {
+ console.log(request.response);
+ Neo.uploaded = true;
+
+ /*var url = Neo.config.url_exit;
+ if (url[0] == '/') {
+ url = url.replace(/^.*\//, ''); //よくわかんないけどとりあえず
+ }
+
+ // ふたばのpaintpost.phpは、画像投稿に成功するとresponseに
+ // "./futaba.php?mode=paintcom&amp;painttmp=.png"
+ // という文字列を返します。
+ //
+ // NEOでは、responseに文字列"painttmp="が含まれる場合は
+ // <PARAM>で指定されたurl_exitを無視して、このURLにジャンプします。
+ var responseURL = request.response.replace(/&amp;/g, '&');
+ if (responseURL.match(/painttmp=/)) {
+ url = responseURL;
+ }
+ var exitURL = url;
+
+ // しぃちゃんのドキュメントをよく見たら
+ // responseが "URL:〜" の形だった場合はそこへ飛ばすって書いてありました。
+ // こっちを使うべきでした……
+ if (responseURL.match(/^URL:/)) {
+ exitURL = responseURL.replace(/^URL:/, '');
+ }
+
+ location.href = exitURL;*/
+ location.href = Neo.config.url_exit;
+ };
+ request.onerror = function(e) {
+ console.log("error");
+ };
+ request.onabort = function(e) {
+ console.log("abort");
+ };
+ request.ontimeout = function(e) {
+ console.log("timeout");
+ };
+
+ request.send(body);
+};
+
+/*
+ -----------------------------------------------------------------------
+ LiveConnect
+ -----------------------------------------------------------------------
+*/
+
+Neo.getColors = function() {
+ console.log("getColors")
+ console.log("defaultColors==", Neo.config.colors.join('\n'));
+ var array = []
+ for (var i = 0; i < 14; i++) {
+ array.push(Neo.colorTips[i].color)
+ }
+ return array.join('\n');
+ // return Neo.config.colors.join('\n');
+};
+
+Neo.setColors = function(colors) {
+ console.log("setColors");
+ var array = colors.split('\n');
+ for (var i = 0; i < 14; i++) {
+ var color = array[i];
+ Neo.config.colors[i] = color;
+ Neo.colorTips[i].setColor(color);
+ }
+};
+
+
+Neo.pExit = function() {
+ new Neo.SubmitCommand(Neo.painter).execute();
+};
+
+Neo.str_header = "";
+
+/*
+ -----------------------------------------------------------------------
+ DOMツリーの作成
+ -----------------------------------------------------------------------
+*/
+
+Neo.createContainer = function(applet) {
+ var neo = document.createElement("div");
+ neo.className = "NEO";
+ neo.id = "NEO";
+ var html = (function() {/*
+
+<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
+
+<div id="pageView" style="width:450px; height:470px; margin:auto;">
+<div id="container" style="visibility:hidden;" class="o">
+<div id="center" class="o">
+<div id="painterContainer" class="o">
+<div id="painterWrapper" class="o">
+<div id="upper" class="o">
+<div id="redo">[やり直し]</div>
+<div id="undo">[元に戻す]</div>
+<div id="fill">[塗り潰し]</div>
+<div id="right" style="display:none;">[右]</div>
+</div>
+<div id="painter">
+<div id="canvas"> <!-- class="o">-->
+<div id="scrollH"></div>
+<div id="scrollV"></div>
+<div id="zoomPlusWrapper">
+<div id="zoomPlus">+</div>
+</div>
+<div id="zoomMinusWrapper">
+<div id="zoomMinus">-</div>
+</div>
+<div id="neoWarning"></div>
+</div>
+</div>
+<div id="lower" class="o">
+</div>
+</div>
+<div id="toolsWrapper">
+<div id="tools">
+<div id="toolSet">
+<div id="pen"></div>
+<div id="pen2"></div>
+<div id="effect"></div>
+<div id="effect2"></div>
+<div id="eraser"></div>
+<div id="draw"></div>
+<div id="mask"></div>
+
+<div class="colorTips">
+<div id="color2"></div><div id="color1"></div><br>
+<div id="color4"></div><div id="color3"></div><br>
+<div id="color6"></div><div id="color5"></div><br>
+<div id="color8"></div><div id="color7"></div><br>
+<div id="color10"></div><div id="color9"></div><br>
+<div id="color12"></div><div id="color11"></div><br>
+<div id="color14"></div><div id="color13"></div>
+</div>
+
+<div id="sliderRed"></div>
+<div id="sliderGreen"></div>
+<div id="sliderBlue"></div>
+<div id="sliderAlpha"></div>
+<div id="sliderSize"></div>
+
+<div class="reserveControl" style="margin-top:4px;">
+<div id="reserve1"></div>
+<div id="reserve2"></div>
+<div id="reserve3"></div>
+</div>
+<div id="layerControl" style="margin-top:6px;"></div>
+
+<!--<div id="toolPad" style="height:20px;"></div>-->
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="headerButtons">
+<div id="window">[窓]</div>
+</div>
+<div id="footerButtons">
+<div id="submit">[投稿]</div>
+<div id="copyright">[(C)しぃちゃん PaintBBS NEO]</div>
+</div>
+</div>
+</div>
+
+<div id="windowView" style="display: none;">
+
+</div>
+
+
+ */}).toString().match(/\/\*([^]*)\*\//)[1];
+
+ neo.innerHTML = html.replace(/\[(.*?)\]/g, function(match, str) {
+ return Neo.translate(str)
+ })
+
+ var parent = applet.parentNode;
+ parent.appendChild(neo);
+ parent.insertBefore(neo, applet);
+
+ // applet.style.display = "none";
+
+ // NEOを組み込んだURLをアプリ版で開くとDOMツリーが2重にできて格好悪いので消しておく
+ setTimeout(function() {
+ var tmp = document.getElementsByClassName("NEO");
+ if (tmp.length > 1) {
+ for (var i = 1; i < tmp.length; i++) {
+ tmp[i].style.display = "none";
+ }
+ }
+ }, 0);
+};
+
+
+'use strict';
+
+Neo.dictionary = {
+ "ja": {},
+ "en": {
+ "やり直し": "Redo",
+ "元に戻す": "Undo",
+ "塗り潰し": "Paint",
+ "窓": "F&nbsp;",
+ "投稿": "Send",
+ "(C)しぃちゃん PaintBBS NEO": "(C)shi-chan PaintBBS NEO",
+ "鉛筆": "Solid",
+ "水彩": "WaterC",
+ "テキスト": "Text",
+ "トーン": "Tone",
+ "ぼかし": "ShadeOff",
+ "覆い焼き": "HLight",
+ "焼き込み": "Dark",
+ "消しペン": "White",
+ "消し四角": "WhiteRect",
+ "全消し": "Clear",
+ "四角": "Rect",
+ "線四角": "LineRect",
+ "楕円": "Oval",
+ "線楕円": "LineOval",
+ "コピー": "Copy",
+ "レイヤ結合": "lay-unif",
+ "角取り": "Antialias",
+ "左右反転": "reverseL",
+ "上下反転": "reverseU",
+ "傾け": "lie",
+ "通常": "Normal",
+ "マスク": "Mask",
+ "逆マスク": "ReMask",
+ "加算": "And",
+ "逆加算": "Div",
+ "手書き": "FreeLine",
+ "直線": "Straight",
+ "BZ曲線": "Bezie",
+ "ページビュー?": "Page view?",
+ "ウィンドウビュー?": "Window view?",
+ "以前の編集データを復元しますか?": "Restore session?",
+ "右": "Right Click",
+
+ "PaintBBS NEOは、お絵描きしぃ掲示板 PaintBBS (©2000-2004 しぃちゃん) をhtml5化するプロジェクトです。\n\nPaintBBS NEOのホームページを表示しますか?": "PaintBBS NEO is an HTML5 port of Oekaki Shi-BBS PaintBBS (©2000-2004 shi-chan). Show the project page?",
+ "このブラウザでは<br>投稿に失敗することがあります<br>": "This browser may fail to send your picture.<br>",
+ },
+ "enx": {
+ "やり直し": "Redo",
+ "元に戻す": "Undo",
+ "塗り潰し": "Fill",
+ "窓": "Float",
+ "投稿": "Send",
+ "(C)しぃちゃん PaintBBS NEO": "&copy;shi-cyan PaintBBS NEO",
+ "鉛筆": "Solid",
+ "水彩": "WaterCo",
+ "テキスト": "Text",
+ "トーン": "Halftone",
+ "ぼかし": "Blur",
+ "覆い焼き": "Light",
+ "焼き込み": "Dark",
+ "消しペン": "White",
+ "消し四角": "WhiteRe",
+ "全消し": "Clear",
+ "四角": "Rect",
+ "線四角": "LineRect",
+ "楕円": "Oval",
+ "線楕円": "LineOval",
+ "コピー": "Copy",
+ "レイヤ結合": "layerUnit",
+ "角取り": "antiAlias",
+ "左右反転": "flipHorita",
+ "上下反転": "flipVertic",
+ "傾け": "rotate",
+ "通常": "Normal",
+ "マスク": "Mask",
+ "逆マスク": "ReMask",
+ "加算": "And",
+ "逆加算": "Divide",
+ "手書き": "Freehan",
+ "直線": "Line",
+ "BZ曲線": "Bezier",
+ "Layer0": "LayerBG",
+ "Layer1": "LayerFG",
+ "ページビュー?": "Page view?",
+ "ウィンドウビュー?": "Window view?",
+ "以前の編集データを復元しますか?": "Restore session?",
+ "右": "Right Click",
+
+ "PaintBBS NEOは、お絵描きしぃ掲示板 PaintBBS (©2000-2004 しぃちゃん) をhtml5化するプロジェクトです。\n\nPaintBBS NEOのホームページを表示しますか?": "PaintBBS NEO is an HTML5 port of Oekaki Shi-BBS PaintBBS (©2000-2004 shi-chan). Show the project page?",
+ "このブラウザでは<br>投稿に失敗することがあります<br>": "This browser may fail to send your picture.<br>",
+ },
+ "es": {
+ "やり直し": "Rehacer",
+ "元に戻す": "Deshacer",
+ "塗り潰し": "Llenar",
+ "窓": "Ventana",
+ "投稿": "Enviar",
+ "(C)しぃちゃん PaintBBS NEO": "&copy;shi-cyan PaintBBS NEO",
+ "鉛筆": "Lápiz",
+ "水彩": "Acuarela",
+ "テキスト": "Texto",
+ "トーン": "Tono",
+ "ぼかし": "Gradación",
+ "覆い焼き": "Sobreexp.",
+ "焼き込み": "Quemar",
+ "消しペン": "Goma",
+ "消し四角": "GomaRect",
+ "全消し": "Borrar",
+ "四角": "Rect",
+ "線四角": "LíneaRect",
+ "楕円": "Óvalo",
+ "線楕円": "LíneaÓvalo",
+ "コピー": "Copiar",
+ "レイヤ結合": "UnirCapa",
+ "角取り": "Antialias",
+ "左右反転": "Inv.Izq/Der",
+ "上下反転": "Inv.Arr/Aba",
+ "傾け": "Inclinar",
+ "通常": "Normal",
+ "マスク": "Masc.",
+ "逆マスク": "Masc.Inv",
+ "加算": "Adición",
+ "逆加算": "Subtrac",
+ "手書き": "Libre",
+ "直線": "Línea",
+ "BZ曲線": "Curva",
+ "Layer0": "Capa0",
+ "Layer1": "Capa1",
+ "ページビュー?": "¿Vista de página?",
+ "ウィンドウビュー?": "¿Vista de ventana?",
+ "以前の編集データを復元しますか?": "¿Restaurar sesión anterior?",
+ "右": "Clic derecho",
+
+ "PaintBBS NEOは、お絵描きしぃ掲示板 PaintBBS (©2000-2004 しぃちゃん) をhtml5化するプロジェクトです。\n\nPaintBBS NEOのホームページを表示しますか?":
+ "PaintBBS NEO es una versión para HTML5 de Oekaki Shi-BBS PaintBBS (© 2000-2004 shi-chan). ¿Mostrar la página del proyecto?",
+ "このブラウザでは<br>投稿に失敗することがあります<br>": "Este navegador podría no enviar su imagen.<br>",
+ },
+};
+
+Neo.translate = function () {
+ var language = (window.navigator.languages && window.navigator.languages[0]) ||
+ window.navigator.language ||
+ window.navigator.userLanguage ||
+ window.navigator.browserLanguage;
+
+ var lang = "en";
+ for (var key in Neo.dictionary) {
+ if (language.indexOf(key) == 0) {
+ lang = key;
+ break;
+ }
+ }
+
+ return function(string) {
+ if (Neo.config.neo_alt_translation) {
+ if (lang == "en") lang = "enx"
+ } else {
+ if (lang != "ja") lang = "en"
+ }
+ return Neo.dictionary[lang][string] || string;
+ }
+}();
+
+
+'use strict';
+
+Neo.Painter = function() {
+ this._undoMgr = new Neo.UndoManager(50);
+};
+
+Neo.Painter.prototype.container;
+Neo.Painter.prototype._undoMgr;
+Neo.Painter.prototype.tool;
+Neo.Painter.prototype.inputText;
+
+//Canvas Info
+Neo.Painter.prototype.canvasWidth;
+Neo.Painter.prototype.canvasHeight;
+Neo.Painter.prototype.canvas = [];
+Neo.Painter.prototype.canvasCtx = [];
+Neo.Painter.prototype.visible = [];
+Neo.Painter.prototype.current = 0;
+
+//Temp Canvas Info
+Neo.Painter.prototype.tempCanvas;
+Neo.Painter.prototype.tempCanvasCtx;
+Neo.Painter.prototype.tempX = 0;
+Neo.Painter.prototype.tempY = 0;
+
+//Destination Canvas for display
+Neo.Painter.prototype.destCanvas;
+Neo.Painter.prototype.destCanvasCtx;
+
+
+Neo.Painter.prototype.backgroundColor = "#ffffff";
+Neo.Painter.prototype.foregroundColor = "#000000";
+
+Neo.Painter.prototype.lineWidth = 1;
+Neo.Painter.prototype.alpha = 1;
+Neo.Painter.prototype.zoom = 1;
+Neo.Painter.prototype.zoomX = 0;
+Neo.Painter.prototype.zoomY = 0;
+
+Neo.Painter.prototype.isMouseDown;
+Neo.Painter.prototype.isMouseDownRight;
+Neo.Painter.prototype.prevMouseX;
+Neo.Painter.prototype.prevMouseY;
+Neo.Painter.prototype.mouseX;
+Neo.Painter.prototype.mouseY;
+
+Neo.Painter.prototype.slowX = 0;
+Neo.Painter.prototype.slowY = 0;
+Neo.Painter.prototype.stab = null;
+
+Neo.Painter.prototype.isShiftDown = false;
+Neo.Painter.prototype.isCtrlDown = false;
+Neo.Painter.prototype.isAltDown = false;
+
+//Neo.Painter.prototype.touchModifier = null;
+Neo.Painter.prototype.virtualRight = false;
+Neo.Painter.prototype.virtualShift = false;
+
+//Neo.Painter.prototype.onUpdateCanvas;
+Neo.Painter.prototype._roundData = [];
+Neo.Painter.prototype._toneData = [];
+Neo.Painter.prototype.toolStack = [];
+
+Neo.Painter.prototype.maskType = 0;
+Neo.Painter.prototype.drawType = 0;
+Neo.Painter.prototype.maskColor = "#000000";
+Neo.Painter.prototype._currentColor = [];
+Neo.Painter.prototype._currentMask = [];
+
+Neo.Painter.prototype.aerr;
+
+Neo.Painter.LINETYPE_NONE = 0;
+Neo.Painter.LINETYPE_PEN = 1;
+Neo.Painter.LINETYPE_ERASER = 2;
+Neo.Painter.LINETYPE_BRUSH = 3;
+Neo.Painter.LINETYPE_TONE = 4;
+Neo.Painter.LINETYPE_DODGE = 5;
+Neo.Painter.LINETYPE_BURN = 6;
+
+Neo.Painter.MASKTYPE_NONE = 0;
+Neo.Painter.MASKTYPE_NORMAL = 1;
+Neo.Painter.MASKTYPE_REVERSE = 2;
+Neo.Painter.MASKTYPE_ADD = 3;
+Neo.Painter.MASKTYPE_SUB = 4;
+
+Neo.Painter.DRAWTYPE_FREEHAND = 0;
+Neo.Painter.DRAWTYPE_LINE = 1;
+Neo.Painter.DRAWTYPE_BEZIER = 2;
+
+Neo.Painter.ALPHATYPE_NONE = 0;
+Neo.Painter.ALPHATYPE_PEN = 1;
+Neo.Painter.ALPHATYPE_FILL = 2;
+Neo.Painter.ALPHATYPE_BRUSH = 3;
+
+Neo.Painter.TOOLTYPE_NONE = 0;
+Neo.Painter.TOOLTYPE_PEN = 1;
+Neo.Painter.TOOLTYPE_ERASER = 2;
+Neo.Painter.TOOLTYPE_HAND = 3;
+Neo.Painter.TOOLTYPE_SLIDER = 4;
+Neo.Painter.TOOLTYPE_FILL = 5;
+Neo.Painter.TOOLTYPE_MASK = 6;
+Neo.Painter.TOOLTYPE_ERASEALL = 7;
+Neo.Painter.TOOLTYPE_ERASERECT = 8;
+Neo.Painter.TOOLTYPE_COPY = 9;
+Neo.Painter.TOOLTYPE_PASTE = 10;
+Neo.Painter.TOOLTYPE_MERGE = 11;
+Neo.Painter.TOOLTYPE_FLIP_H = 12;
+Neo.Painter.TOOLTYPE_FLIP_V = 13;
+
+Neo.Painter.TOOLTYPE_BRUSH = 14;
+Neo.Painter.TOOLTYPE_TEXT = 15;
+Neo.Painter.TOOLTYPE_TONE = 16;
+Neo.Painter.TOOLTYPE_BLUR = 17;
+Neo.Painter.TOOLTYPE_DODGE = 18;
+Neo.Painter.TOOLTYPE_BURN = 19;
+Neo.Painter.TOOLTYPE_RECT = 20;
+Neo.Painter.TOOLTYPE_RECTFILL = 21;
+Neo.Painter.TOOLTYPE_ELLIPSE = 22;
+Neo.Painter.TOOLTYPE_ELLIPSEFILL = 23;
+Neo.Painter.TOOLTYPE_BLURRECT = 24;
+Neo.Painter.TOOLTYPE_TURN = 25;
+
+Neo.Painter.prototype.build = function(div, width, height)
+{
+ this.container = div;
+ this._initCanvas(div, width, height);
+ this._initRoundData();
+ this._initToneData();
+ this._initInputText();
+
+ this.setTool(new Neo.PenTool());
+
+};
+
+Neo.Painter.prototype.setTool = function(tool) {
+ if (this.tool && this.tool.saveStates) this.tool.saveStates();
+
+ if (this.tool && this.tool.kill) {
+ this.tool.kill();
+ }
+ this.tool = tool;
+ tool.init();
+ if (this.tool && this.tool.loadStates) this.tool.loadStates();
+};
+
+Neo.Painter.prototype.pushTool = function(tool) {
+ this.toolStack.push(this.tool);
+ this.tool = tool;
+ tool.init();
+};
+
+Neo.Painter.prototype.popTool = function() {
+ var tool = this.tool;
+ if (tool && tool.kill) {
+ tool.kill();
+ }
+ this.tool = this.toolStack.pop();
+};
+
+Neo.Painter.prototype.getCurrentTool = function() {
+ if (this.tool) {
+ var tool = this.tool;
+ if (tool && tool.type == Neo.Painter.TOOLTYPE_SLIDER) {
+ var stack = this.toolStack;
+ if (stack.length > 0) {
+ tool = stack[stack.length - 1];
+ }
+ }
+ return tool;
+ }
+ return null;
+};
+
+Neo.Painter.prototype.setToolByType = function(toolType) {
+ switch (parseInt(toolType)) {
+ case Neo.Painter.TOOLTYPE_PEN: this.setTool(new Neo.PenTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASER: this.setTool(new Neo.EraserTool()); break;
+ case Neo.Painter.TOOLTYPE_HAND: this.setTool(new Neo.HandTool()); break;
+ case Neo.Painter.TOOLTYPE_FILL: this.setTool(new Neo.FillTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASEALL: this.setTool(new Neo.EraseAllTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASERECT: this.setTool(new Neo.EraseRectTool()); break;
+
+ case Neo.Painter.TOOLTYPE_COPY: this.setTool(new Neo.CopyTool()); break;
+ case Neo.Painter.TOOLTYPE_PASTE: this.setTool(new Neo.PasteTool()); break;
+ case Neo.Painter.TOOLTYPE_MERGE: this.setTool(new Neo.MergeTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_H: this.setTool(new Neo.FlipHTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_V: this.setTool(new Neo.FlipVTool()); break;
+
+ case Neo.Painter.TOOLTYPE_BRUSH: this.setTool(new Neo.BrushTool()); break;
+ case Neo.Painter.TOOLTYPE_TEXT: this.setTool(new Neo.TextTool()); break;
+ case Neo.Painter.TOOLTYPE_TONE: this.setTool(new Neo.ToneTool()); break;
+ case Neo.Painter.TOOLTYPE_BLUR: this.setTool(new Neo.BlurTool()); break;
+ case Neo.Painter.TOOLTYPE_DODGE: this.setTool(new Neo.DodgeTool()); break;
+ case Neo.Painter.TOOLTYPE_BURN: this.setTool(new Neo.BurnTool()); break;
+
+ case Neo.Painter.TOOLTYPE_RECT: this.setTool(new Neo.RectTool()); break;
+ case Neo.Painter.TOOLTYPE_RECTFILL: this.setTool(new Neo.RectFillTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSE: this.setTool(new Neo.EllipseTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:this.setTool(new Neo.EllipseFillTool()); break;
+ case Neo.Painter.TOOLTYPE_BLURRECT: this.setTool(new Neo.BlurRectTool()); break;
+ case Neo.Painter.TOOLTYPE_TURN: this.setTool(new Neo.TurnTool()); break;
+
+ default:
+ console.log("unknown toolType " + toolType);
+ break;
+ }
+};
+
+Neo.Painter.prototype._initCanvas = function(div, width, height) {
+ width = parseInt(width);
+ height = parseInt(height);
+ var destWidth = parseInt(div.clientWidth);
+ var destHeight = parseInt(div.clientHeight);
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.canvasWidth = width;
+ this.canvasHeight = height;
+ this.zoomX = width * 0.5;
+ this.zoomY = height * 0.5;
+
+ for (var i = 0; i < 2; i++) {
+ this.canvas[i] = document.createElement("canvas");
+ this.canvas[i].width = width;
+ this.canvas[i].height = height;
+ this.canvasCtx[i] = this.canvas[i].getContext("2d");
+
+ this.canvas[i].style.imageRendering = "pixelated";
+ this.canvasCtx[i].imageSmoothingEnabled = false;
+ this.canvasCtx[i].mozImageSmoothingEnabled = false;
+ this.visible[i] = true;
+ }
+
+ this.tempCanvas = document.createElement("canvas");
+ this.tempCanvas.width = width;
+ this.tempCanvas.height = height;
+ this.tempCanvasCtx = this.tempCanvas.getContext("2d");
+ this.tempCanvas.style.position = "absolute";
+ this.tempCanvas.enabled = false;
+
+ var array = this.container.getElementsByTagName("canvas");
+ if (array.length > 0) {
+ this.destCanvas = array[0];
+ } else {
+ this.destCanvas = document.createElement("canvas");
+ this.container.appendChild(this.destCanvas);
+ }
+
+ this.destCanvasCtx = this.destCanvas.getContext("2d");
+ this.destCanvas.width = destWidth;
+ this.destCanvas.height = destHeight;
+
+ this.destCanvas.style.imageRendering = "pixelated";
+ this.destCanvasCtx.imageSmoothingEnabled = false;
+ this.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ var ref = this;
+
+ var container = document.getElementById("container");
+
+ container.onmousedown = function(e) {ref._mouseDownHandler(e)};
+ container.onmousemove = function(e) {ref._mouseMoveHandler(e)};
+ container.onmouseup = function(e) {ref._mouseUpHandler(e)};
+ container.onmouseover = function(e) {ref._rollOverHandler(e)};
+ container.onmouseout = function(e) {ref._rollOutHandler(e)};
+ container.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ }, false);
+ container.addEventListener("touchmove", function(e) {
+ ref._mouseMoveHandler(e);
+ }, false);
+ container.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, false);
+
+ document.onkeydown = function(e) {ref._keyDownHandler(e)};
+ document.onkeyup = function(e) {ref._keyUpHandler(e)};
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype._initRoundData = function() {
+ for (var r = 1; r <= 30; r++) {
+ this._roundData[r] = new Uint8Array(r * r);
+ var mask = this._roundData[r];
+ var d = Math.floor(r / 2.0);
+ var index = 0;
+ for (var x = 0; x < r; x++) {
+ for (var y = 0; y < r; y++) {
+ var xx = x + 0.5 - r/2.0;
+ var yy = y + 0.5 - r/2.0;
+ mask[index++] = (xx*xx + yy*yy <= r*r/4) ? 1 : 0;
+ }
+ }
+ }
+ this._roundData[3][0] = 0;
+ this._roundData[3][2] = 0;
+ this._roundData[3][6] = 0;
+ this._roundData[3][8] = 0;
+
+ this._roundData[5][1] = 0;
+ this._roundData[5][3] = 0;
+ this._roundData[5][5] = 0;
+ this._roundData[5][9] = 0;
+ this._roundData[5][15] = 0;
+ this._roundData[5][19] = 0;
+ this._roundData[5][21] = 0;
+ this._roundData[5][23] = 0;
+};
+
+Neo.Painter.prototype._initToneData = function() {
+ var pattern = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
+
+ for (var i = 0; i < 16; i++) {
+ this._toneData[i] = new Uint8Array(16);
+ for (var j = 0; j < 16; j++) {
+ this._toneData[i][j] = (i >= pattern[j]) ? 1 : 0;
+ }
+ }
+};
+
+Neo.Painter.prototype.getToneData = function(alpha) {
+ var alphaTable = [23,
+ 47,
+ 69,
+ 92,
+ 114,
+ 114,
+ 114,
+ 138,
+ 161,
+ 184,
+ 184,
+ 207,
+ 230,
+ 230,
+ 253,
+ ];
+
+ for (var i = 0; i < alphaTable.length; i++) {
+ if (alpha < alphaTable[i]) {
+ return this._toneData[i];
+ }
+ }
+ return this._toneData[i];
+};
+
+Neo.Painter.prototype._initInputText = function() {
+ var text = document.getElementById("inputtext");
+ if (!text) {
+ text = document.createElement("div");
+ }
+
+ text.id = "inputext";
+ text.setAttribute("contentEditable", true);
+ text.spellcheck = false;
+ text.className = "inputText";
+ text.innerHTML = "";
+
+ text.style.display = "none";
+// text.style.userSelect = "none";
+ Neo.painter.container.appendChild(text);
+ this.inputText = text;
+
+ this.updateInputText();
+};
+
+Neo.Painter.prototype.hideInputText = function() {
+ var text = this.inputText;
+ text.blur();
+ text.style.display = "none";
+};
+
+Neo.Painter.prototype.updateInputText = function() {
+ var text = this.inputText;
+ var d = this.lineWidth;
+ var fontSize = Math.round(d * 55/28 + 7);
+ var height = Math.round(d * 68/28 + 12);
+
+ text.style.fontSize = fontSize + "px";
+ text.style.lineHeight = fontSize + "px";
+ text.style.height = fontSize + "px";
+ text.style.marginTop = -fontSize + "px";
+};
+
+/*
+-----------------------------------------------------------------------
+ Mouse Event Handling
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype._keyDownHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = true;
+
+ if (!this.isShiftDown && this.isCtrlDown) {
+ if (!this.isAltDown) {
+ if (e.keyCode == 90 || e.keyCode == 85) this.undo(); //Ctrl+Z,Ctrl.U
+ if (e.keyCode == 89) this.redo(); //Ctrl+Y
+ } else {
+ if (e.keyCode == 90) this.redo(); //Ctrl+Alt+Z
+ }
+ }
+
+ if (!this.isShiftDown && !this.isCtrlDown && !this.isAltDown) {
+ if (e.keyCode == 107) new Neo.ZoomPlusCommand(this).execute(); // +
+ if (e.keyCode == 109) new Neo.ZoomMinusCommand(this).execute(); // -
+ }
+
+ if (this.tool.keyDownHandler) {
+ this.tool.keyDownHandler(e);
+ }
+
+ //スペース・Shift+スペースででスクロールしないように
+ if (document.activeElement != this.inputText) e.preventDefault();
+};
+
+Neo.Painter.prototype._keyUpHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = false;
+
+ if (this.tool.keyUpHandler) {
+ this.tool.keyUpHandler(oe);
+ }
+};
+
+Neo.Painter.prototype._rollOverHandler = function(e) {
+ if (this.tool.rollOverHandler) {
+ this.tool.rollOverHandler(this);
+ }
+};
+
+Neo.Painter.prototype._rollOutHandler = function(e) {
+ if (this.tool.rollOutHandler) {
+ this.tool.rollOutHandler(this);
+ }
+};
+
+Neo.Painter.prototype._mouseDownHandler = function(e) {
+ if (e.target == Neo.painter.destCanvas) {
+ //よくわからないがChromeでドラッグの時カレットが出るのを防ぐ
+ //http://stackoverflow.com/questions/2745028/chrome-sets-cursor-to-text-while-dragging-why
+ e.preventDefault();
+ }
+
+ if (e.type == "touchstart" && e.touches.length > 1) return;
+
+ if (e.button == 2 || this.virtualRight) {
+ this.isMouseDownRight = true;
+
+ } else {
+ if (!e.shiftKey && e.ctrlKey && e.altKey) {
+ this.isMouseDown = true;
+
+ } else {
+ if (e.ctrlKey || e.altKey) {
+ this.isMouseDownRight = true;
+ } else {
+ this.isMouseDown = true;
+ }
+ }
+ }
+
+ this._updateMousePosition(e);
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+
+ if (this.isMouseDownRight) {
+ this.isMouseDownRight = false;
+ if (!this.isWidget(e.target)) {
+ this.pickColor(this.mouseX, this.mouseY);
+ return;
+ }
+ }
+
+ if (!this.isUIPaused()) {
+ if (e.target['data-bar']) {
+ this.pushTool(new Neo.HandTool());
+
+ } else if (this.isSpaceDown && document.activeElement != this.inputText) {
+ this.pushTool(new Neo.HandTool());
+ this.tool.reverse = true;
+
+ } else if (e.target['data-slider'] != undefined) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = e.target;
+
+ } else if (e.ctrlKey && e.altKey && !e.shiftKey) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = Neo.sliders[Neo.SLIDERTYPE_SIZE].element;
+ this.tool.alt = true;
+
+ } else if (this.isWidget(e.target)) {
+ this.isMouseDown = false;
+ this.pushTool(new Neo.DummyTool());
+
+ }
+ }
+
+// console.warn("down -" + e.target.id + e.target.className)
+ if (!(e.target.className == "o" && e.type == "touchdown")) {
+ this.tool.downHandler(this);
+ }
+
+// var ref = this;
+// document.onmouseup = function(e) {
+// ref._mouseUpHandler(e)
+// };
+};
+
+Neo.Painter.prototype._mouseUpHandler = function(e) {
+ this.isMouseDown = false;
+ this.isMouseDownRight = false;
+ this.tool.upHandler(this);
+// document.onmouseup = undefined;
+
+ if (e.target.id != "right") {
+ this.virtualRight = false;
+ Neo.RightButton.clear();
+ }
+
+// if (e.changedTouches) {
+// for (var i = 0; i < e.changedTouches.length; i++) {
+// var touch = e.changedTouches[i];
+// if (touch.identifier == this.touchModifier) {
+// this.touchModifier = null;
+// }
+// }
+// }
+};
+
+Neo.Painter.prototype._mouseMoveHandler = function(e) {
+ this._updateMousePosition(e);
+
+ if (e.type == "touchmove" && e.touches.length > 1) return;
+
+ if (this.isMouseDown || this.isMouseDownRight) {
+ this.tool.moveHandler(this);
+
+ } else {
+ if (this.tool.upMoveHandler) {
+ this.tool.upMoveHandler(this);
+ }
+ }
+
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+
+ // 画面外をタップした時スクロール可能にするため
+// console.warn("move -" + e.target.id + e.target.className)
+ if (!(e.target.className == "o" && e.type == "touchmove")) {
+ e.preventDefault();
+ }
+};
+
+
+Neo.Painter.prototype.getPosition = function(e) {
+ if (e.clientX !== undefined) {
+ return {x: e.clientX, y: e.clientY, e: e.type};
+
+ } else {
+ var touch = e.changedTouches[0];
+ return {x: touch.clientX, y: touch.clientY, e: e.type};
+
+// for (var i = 0; i < e.changedTouches.length; i++) {
+// var touch = e.changedTouches[i];
+// if (!this.touchModifier || this.touchModifier != touch.identifier) {
+// return {x: touch.clientX, y: touch.clientY, e: e.type};
+// }
+// }
+// console.log("getPosition error");
+// return {x:0, y:0};
+ }
+}
+
+Neo.Painter.prototype._updateMousePosition = function(e) {
+ var rect = this.destCanvas.getBoundingClientRect();
+// var x = (e.clientX !== undefined) ? e.clientX : e.touches[0].clientX;
+// var y = (e.clientY !== undefined) ? e.clientY : e.touches[0].clientY;
+ var pos = this.getPosition(e);
+ var x = pos.x;
+ var y = pos.y;
+
+ if (this.zoom <= 0) this.zoom = 1; //なぜか0になることがあるので
+
+ this.mouseX = (x - rect.left) / this.zoom
+ + this.zoomX
+ - this.destCanvas.width * 0.5 / this.zoom;
+ this.mouseY = (y - rect.top) / this.zoom
+ + this.zoomY
+ - this.destCanvas.height * 0.5 / this.zoom;
+
+ if (isNaN(this.prevMouseX)) {
+ this.prevMouseX = this.mouseX;
+ }
+ if (isNaN(this.prevMouseY)) {
+ this.prevMosueY = this.mouseY;
+ }
+
+ this.slowX = this.slowX * 0.8 + this.mouseX * 0.2;
+ this.slowY = this.slowY * 0.8 + this.mouseY * 0.2;
+ var now = new Date().getTime();
+ if (this.stab) {
+ var pause = this.stab[3];
+ if (pause) {
+ // ポーズ中
+ if (now > pause) {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ } else {
+ // ポーズされていないとき
+ var prev = this.stab[2];
+ if (now - prev > 150) { // 150ms以上止まっていたらポーズをオンにする
+ this.stab[3] = now + 200 // 200msペンの位置を固定
+
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+ }
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ this.rawMouseX = x;
+ this.rawMouseY = y;
+ this.clipMouseX = Math.max(Math.min(this.canvasWidth, this.mouseX), 0);
+ this.clipMouseY = Math.max(Math.min(this.canvasHeight, this.mouseY), 0);
+};
+
+Neo.Painter.prototype._beforeUnloadHandler = function(e) {
+ // quick save
+};
+
+Neo.Painter.prototype.getStabilized = function() {
+ return this.stab;
+};
+
+/*
+-------------------------------------------------------------------------
+ Undo
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.undo = function() {
+ var undoItem = this._undoMgr.popUndo();
+ if (undoItem) {
+ this._pushRedo();
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.redo = function() {
+ var undoItem = this._undoMgr.popRedo();
+ if (undoItem) {
+ this._pushUndo(0,0,this.canvasWidth, this.canvasHeight, true);
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.hasUndo = function() {
+ return true;
+};
+
+Neo.Painter.prototype._pushUndo = function(x, y, w, h, holdRedo) {
+ x = (x === undefined) ? 0 : x;
+ y = (y === undefined) ? 0 : y;
+ w = (w === undefined) ? this.canvasWidth : w;
+ h = (h === undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushUndo(undoItem, holdRedo);
+};
+
+Neo.Painter.prototype._pushRedo = function(x, y, w, h) {
+ x = (x === undefined) ? 0 : x;
+ y = (y === undefined) ? 0 : y;
+ w = (w === undefined) ? this.canvasWidth : w;
+ h = (h === undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushRedo(undoItem);
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Data Cache for Undo / Redo
+-------------------------------------------------------------------------
+*/
+
+Neo.UndoManager = function(_maxStep){
+ this._maxStep = _maxStep;
+ this._undoItems = [];
+ this._redoItems = [];
+}
+Neo.UndoManager.prototype._maxStep;
+Neo.UndoManager.prototype._redoItems;
+Neo.UndoManager.prototype._undoItems;
+
+//アクションをしてUndo情報を更新
+Neo.UndoManager.prototype.pushUndo = function(undoItem, holdRedo) {
+ this._undoItems.push(undoItem);
+ if (this._undoItems.length > this._maxStep) {
+ this._undoItems.shift();
+ }
+
+ if (!holdRedo == true) {
+ this._redoItems = [];
+ }
+};
+
+Neo.UndoManager.prototype.popUndo = function() {
+ return this._undoItems.pop();
+}
+
+Neo.UndoManager.prototype.pushRedo = function(undoItem) {
+ this._redoItems.push(undoItem);
+}
+
+Neo.UndoManager.prototype.popRedo = function() {
+ return this._redoItems.pop();
+}
+
+
+Neo.UndoItem = function() {}
+Neo.UndoItem.prototype.data;
+Neo.UndoItem.prototype.x;
+Neo.UndoItem.prototype.y;
+Neo.UndoItem.prototype.width;
+Neo.UndoItem.prototype.height;
+
+/*
+-------------------------------------------------------------------------
+ Zoom Controller
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.setZoom = function(value) {
+ this.zoom = value;
+
+ var container = document.getElementById("container");
+ var width = this.canvasWidth * this.zoom;
+ var height = this.canvasHeight * this.zoom;
+ if (width > container.clientWidth - 100) width = container.clientWidth - 100;
+ if (height > container.clientHeight - 130) height = container.clientHeight - 130;
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight, false);
+ this.setZoomPosition(this.zoomX, this.zoomY);
+};
+
+Neo.Painter.prototype.setZoomPosition = function(x, y) {
+ var minx = (this.destCanvas.width / this.zoom) * 0.5;
+ var maxx = this.canvasWidth - minx;
+ var miny = (this.destCanvas.height / this.zoom) * 0.5;
+ var maxy = this.canvasHeight - miny;
+
+
+ x = Math.round(Math.max(Math.min(maxx,x),minx));
+ y = Math.round(Math.max(Math.min(maxy,y),miny));
+
+ this.zoomX = x;
+ this.zoomY = y;
+ this.updateDestCanvas(0,0,this.canvasWidth,this.canvasHeight,false);
+
+ this.scrollBarX = (maxx == minx) ? 0 : (x - minx) / (maxx - minx);
+ this.scrollBarY = (maxy == miny) ? 0 : (y - miny) / (maxy - miny);
+ this.scrollWidth = maxx - minx;
+ this.scrollHeight = maxy - miny;
+
+ if (Neo.scrollH) Neo.scrollH.update(this);
+ if (Neo.scrollV) Neo.scrollV.update(this);
+
+ this.hideInputText();
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Drawing Helper
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.submit = function(board) {
+ var thumbnail = null;
+ var thumbnail2 = null;
+
+ if (this.useThumbnail()) {
+ thumbnail = this.getThumbnail(Neo.config.thumbnail_type || "png");
+ if (Neo.config.thumbnail_type2) {
+ thumbnail2 = this.getThumbnail(Neo.config.thumbnail_type2);
+ }
+ }
+ Neo.submit(board, this.getPNG(), thumbnail2, thumbnail);
+};
+
+Neo.Painter.prototype.useThumbnail = function() {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth && thumbnailHeight) {
+ if (thumbnailWidth < this.canvasWidth ||
+ thumbnailHeight < this.canvasHeight) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.dataURLtoBlob = function(dataURL) {
+ var byteString;
+ if (dataURL.split(',')[0].indexOf('base64') >= 0) {
+ byteString = atob(dataURL.split(',')[1]);
+ } else {
+ byteString = unescape(dataURL.split(',')[1]);
+ }
+
+ // write the bytes of the string to a typed array
+ var ia = new Uint8Array(byteString.length);
+ for (var i = 0; i < byteString.length; i++) {
+ ia[i] = byteString.charCodeAt(i);
+ }
+ return new Blob([ia], {type:'image/png'});
+};
+
+Neo.Painter.prototype.getImage = function(imageWidth, imageHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ imageWidth = imageWidth || width;
+ imageHeight = imageHeight || height;
+
+ var pngCanvas = document.createElement("canvas");
+ pngCanvas.width = imageWidth;
+ pngCanvas.height = imageHeight;
+ var pngCanvasCtx = pngCanvas.getContext("2d");
+ pngCanvasCtx.fillStyle = "#ffffff";
+ pngCanvasCtx.fillRect(0, 0, imageWidth, imageHeight);
+
+ if (this.visible[0]) {
+ pngCanvasCtx.drawImage(this.canvas[0],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ if (this.visible[1]) {
+ pngCanvasCtx.drawImage(this.canvas[1],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ return pngCanvas;
+};
+
+Neo.Painter.prototype.getPNG = function() {
+ var image = this.getImage();
+ var dataURL = image.toDataURL('image/png');
+ return this.dataURLtoBlob(dataURL);
+};
+
+Neo.Painter.prototype.getThumbnail = function(type) {
+ if (type != "animation") {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth || thumbnailHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ if (thumbnailWidth == 0) {
+ thumbnailWidth = thumbnailHeight * width / height;
+ }
+ if (thumbnailHeight == 0) {
+ thumbnailHeight = thumbnailWidth * height / width;
+ }
+ } else {
+ thumbnailWidth = thumbnailHeight = null;
+ }
+
+ console.log("get thumbnail", thumbnailWidth, thumbnailHeight);
+
+ var image = this.getImage(thumbnailWidth, thumbnailHeight);
+ var dataURL = image.toDataURL('image/' + type);
+ return this.dataURLtoBlob(dataURL);
+
+ } else {
+ return new Blob([]); //animationには対応していないのでダミーデータを返す
+ }
+};
+
+Neo.Painter.prototype.getThumbnailWidth = function() {
+ var width = Neo.config.thumbnail_width;
+ if (width) {
+ if (width.match(/%$/)) {
+ return Math.floor(this.canvasWidth * (parseInt(width) / 100.0));
+ } else {
+ return parseInt(width);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.getThumbnailHeight = function() {
+ var height = Neo.config.thumbnail_height;
+ if (height) {
+ if (height.match(/%$/)) {
+ return Math.floor(this.canvasHeight * (parseInt(height) / 100.0));
+ } else {
+ return parseInt(height);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.clearCanvas = function(doConfirm) {
+ if (!doConfirm || confirm("全消しします")) {
+ //Register undo first;
+ this._pushUndo();
+
+ this.canvasCtx[0].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.canvasCtx[1].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+ }
+};
+
+Neo.Painter.prototype.updateDestCanvas = function(x, y, width, height, useTemp) {
+ var canvasWidth = this.canvasWidth;
+ var canvasHeight = this.canvasHeight;
+ var updateAll = false;
+ if (x == 0 && y == 0 && width == canvasWidth && height == canvasHeight) {
+ updateAll = true;
+ };
+
+ if (x + width > this.canvasWidth) width = this.canvasWidth - x;
+ if (y + height > this.canvasHeight) height = this.canvasHeight - y;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (width <= 0 || height <= 0) return;
+
+ var ctx = this.destCanvasCtx;
+ ctx.save();
+ ctx.fillStyle = "#ffffff";
+
+ var fillWidth = width
+ var fillHeight = height
+
+ if (updateAll) {
+ ctx.fillRect(0, 0, this.destCanvas.width, this.destCanvas.height);
+
+ } else {
+ //カーソルの描画ゴミが残るのをごまかすため
+ if (x + width == this.canvasWidth) fillWidth = width + 1;
+ if (y + height == this.canvasHeight) fillHeight = height + 1;
+ }
+
+ ctx.translate(this.destCanvas.width*.5, this.destCanvas.height*.5);
+ ctx.scale(this.zoom, this.zoom);
+ ctx.translate(-this.zoomX, -this.zoomY);
+ ctx.globalAlpha = 1.0;
+ ctx.msImageSmoothingEnabled = 0;
+
+ if (!updateAll) {
+ ctx.fillRect(x, y, fillWidth, fillHeight);
+ }
+
+ if (this.visible[0]) {
+ ctx.drawImage(this.canvas[0],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (this.visible[1]) {
+ ctx.drawImage(this.canvas[1],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (useTemp) {
+ ctx.globalAlpha = 1.0; //this.alpha;
+ ctx.drawImage(this.tempCanvas,
+ x, y, width, height,
+ x + this.tempX, y + this.tempY, width, height);
+ }
+ ctx.restore();
+};
+
+Neo.Painter.prototype.getBound = function(x0, y0, x1, y1, r) {
+ var left = Math.floor((x0 < x1) ? x0 : x1);
+ var top = Math.floor((y0 < y1) ? y0 : y1);
+ var width = Math.ceil(Math.abs(x0 - x1));
+ var height = Math.ceil(Math.abs(y0 - y1));
+ r = Math.ceil(r + 1);
+
+ if (!r) {
+ width += 1;
+ height += 1;
+
+ } else {
+ left -= r;
+ top -= r;
+ width += r * 2;
+ height += r * 2;
+ }
+ return [left, top, width, height];
+};
+
+Neo.Painter.prototype.getColor = function(c) {
+ if (!c) c = this.foregroundColor;
+ var r = parseInt(c.substr(1, 2), 16);
+ var g = parseInt(c.substr(3, 2), 16);
+ var b = parseInt(c.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+ return a <<24 | b<<16 | g<<8 | r;
+};
+
+Neo.Painter.prototype.getColorString = function(c) {
+ var rgb = ("000000" + (c & 0xffffff).toString(16)).substr(-6);
+ return '#' + rgb;
+};
+
+Neo.Painter.prototype.setColor = function(c) {
+ if (typeof c != "string") c = this.getColorString(c);
+ this.foregroundColor = c;
+
+ Neo.updateUI();
+};
+
+Neo.Painter.prototype.getAlpha = function(type) {
+ var a1 = this.alpha;
+
+ switch (type) {
+ case Neo.Painter.ALPHATYPE_PEN:
+ if (a1 > 0.5) {
+ a1 = 1.0/16 + (a1 - 0.5) * 30.0/16;
+ } else {
+ a1 = Math.sqrt(2 * a1) / 16.0;
+ }
+ a1 = Math.min(1, Math.max(0, a1));
+ break;
+
+ case Neo.Painter.ALPHATYPE_FILL:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1 * 10));
+ break;
+
+ case Neo.Painter.ALPHATYPE_BRUSH:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1));
+ break;
+ }
+
+ // アルファが小さい時は適当に点を抜いて見た目の濃度を合わせる
+ if (a1 < 1.0/255) {
+ this.aerr += a1;
+ a1 = 0;
+ while (this.aerr > 1.0/255) {
+ a1 = 1.0/255;
+ this.aerr -= 1.0/255;
+ }
+ }
+ return a1;
+};
+
+Neo.Painter.prototype.prepareDrawing = function () {
+ var r = parseInt(this.foregroundColor.substr(1, 2), 16);
+ var g = parseInt(this.foregroundColor.substr(3, 2), 16);
+ var b = parseInt(this.foregroundColor.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+
+ var maskR = parseInt(this.maskColor.substr(1, 2), 16);
+ var maskG = parseInt(this.maskColor.substr(3, 2), 16);
+ var maskB = parseInt(this.maskColor.substr(5, 2), 16);
+
+ this._currentColor = [r, g, b, a];
+ this._currentMask = [maskR, maskG, maskB];
+};
+
+Neo.Painter.prototype.isMasked = function (buf8, index) {
+ var r = this._currentMask[0];
+ var g = this._currentMask[1];
+ var b = this._currentMask[2];
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3];
+
+ if (a0 == 0) {
+ r0 = 0xff;
+ g0 = 0xff;
+ b0 = 0xff;
+ }
+
+ var type = this.maskType;
+
+ //TODO
+ //いろいろ試したのですが半透明で描画するときの加算・逆加算を再現する方法がわかりません。
+ //とりあえず単純に無視しています。
+ if (type == Neo.Painter.MASKTYPE_ADD ||
+ type == Neo.Painter.MASKTYPE_SUB) {
+ if (this._currentColor[3] < 250) {
+ type = Neo.Painter.MASKTYPE_NONE;
+ }
+ }
+
+ switch (type) {
+ case Neo.Painter.MASKTYPE_NONE:
+ return;
+
+ case Neo.Painter.MASKTYPE_NORMAL:
+ return (r0 == r &&
+ g0 == g &&
+ b0 == b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_REVERSE:
+ return (r0 != r ||
+ g0 != g ||
+ b0 != b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_ADD:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] < this._currentColor[c]) return true;
+ }
+ return false;
+
+ } else {
+ return false;
+ }
+
+ case Neo.Painter.MASKTYPE_SUB:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] > this._currentColor[c]) return true;
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+};
+
+Neo.Painter.prototype.setPoint = function(buf8, bufWidth, x0, y0, left, top, type) {
+ var x = x0 - left;
+ var y = y0 - top;
+
+ switch (type) {
+ case Neo.Painter.LINETYPE_PEN:
+ this.setPenPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BRUSH:
+ this.setBrushPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_TONE:
+ this.setTonePoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_ERASER:
+ this.setEraserPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BLUR:
+ this.setBlurPoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_DODGE:
+ this.setDodgePoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BURN:
+ this.setBurnPoint(buf8, bufWidth, x, y);
+ break;
+
+ default:
+ break;
+ }
+};
+
+
+Neo.Painter.prototype.setPenPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_PEN);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0 * (1 - a1x)) / a;
+ var g = (g1 * a1x + g0 * a0 * (1 - a1x)) / a;
+ var b = (b1 * a1x + b0 * a0 * (1 - a1x)) / a;
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBrushPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0) / (a0 + a1x);
+ var g = (g1 * a1x + g0 * a0) / (a0 + a1x);
+ var b = (b1 * a1x + b0 * a0) / (a0 + a1x);
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setTonePoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+
+ x -= r0;
+ y -= r0;
+ x0 -= r0;
+ y0 -= r0;
+// x -= r0;
+// y -= r0;
+// if (r0%2) { x0++; y0++; } //なぜか模様がずれるので
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+
+ var r = this._currentColor[0];
+ var g = this._currentColor[1];
+ var b = this._currentColor[2];
+ var a = this._currentColor[3];
+
+ var toneData = this.getToneData(a);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ if (toneData[((y0+i)%4) + (((x0+j)%4) * 4)]) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = 255;
+ }
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setEraserPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+ var a = Math.floor(this.alpha * 255);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var k = (buf8[index + 3] / 255.0) * (1.0 - (a / 255.0));
+
+ buf8[index + 3] -= a / (d * (255.0 - a) / 255.0);
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBlurPoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var height = buf8.length / (width * 4);
+
+// var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ var a1 = this.alpha / 12;
+ if (a1 == 0) return;
+ var blur = a1;
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) {
+ tmp[i] = buf8[i];
+ }
+
+ var left = x0 - x - r0;
+ var top = y0 - y - r0;
+
+ var xstart = 0, xend = d;
+ var ystart = 0, yend = d;
+ if (xstart > left) xstart = -left;
+ if (ystart > top) ystart = -top;
+ if (xend > this.canvasWidth - left) xend = this.canvasWidth - left;
+ if (yend > this.canvasHeight - top) yend = this.canvasHeight - top;
+
+ for (var j = ystart; j < yend; j++) {
+ var index = (j * width + xstart) * 4;
+ for (var i = xstart; i < xend; i++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+ if (i > xstart) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < xend - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > ystart) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < yend - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.round((rgba[3] / rgba[4]) * 255.0);
+ }
+ index += 4;
+ }
+ }
+};
+
+Neo.Painter.prototype.setDodgePoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = r0 * 255 / (255 - a1);
+ var g1 = g0 * 255 / (255 - a1);
+ var b1 = b0 * 255 / (255 - a1);
+ } else {
+ var r1 = 255.0;
+ var g1 = 255.0;
+ var b1 = 255.0;
+ }
+
+ var r = Math.ceil(r1);
+ var g = Math.ceil(g1);
+ var b = Math.ceil(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBurnPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = 255 - (255 - r0) * 255 / (255 - a1);
+ var g1 = 255 - (255 - g0) * 255 / (255 - a1);
+ var b1 = 255 - (255 - b0) * 255 / (255 - a1);
+ } else {
+ var r1 = 0;
+ var g1 = 0;
+ var b1 = 0;
+ }
+
+ var r = Math.floor(r1);
+ var g = Math.floor(g1);
+ var b = Math.floor(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+
+Neo.Painter.prototype.xorPixel = function(buf32, bufWidth, x, y, c) {
+ var index = y * bufWidth + x;
+ if (!c) c = 0xffffff;
+ buf32[index] ^= c;
+};
+
+Neo.Painter.prototype.getBezierPoint = function(t, x0, y0, x1, y1, x2, y2, x3, y3) {
+ var a0 = (1 - t) * (1 - t) * (1 - t);
+ var a1 = (1 - t) * (1 - t) * t * 3;
+ var a2 = (1 - t) * t * t * 3;
+ var a3 = t * t * t;
+
+ var x = x0 * a0 + x1 * a1 + x2 * a2 + x3 * a3;
+ var y = y0 * a0 + y1 * a1 + y2 * a2 + y3 * a3;
+ return [x, y];
+};
+
+var nmax = 1;
+
+Neo.Painter.prototype.drawBezier = function(ctx, x0, y0, x1, y1, x2, y2, x3, y3, type) {
+ var xmax = Math.max(x0, x1, x2, x3);
+ var xmin = Math.min(x0, x1, x2, x3);
+ var ymax = Math.max(y0, y1, y2, y3);
+ var ymin = Math.min(y0, y1, y2, y3);
+ var n = Math.ceil(((xmax - xmin) + (ymax - ymin)) * 2.5);
+
+ if (n > nmax) {
+ n = (n < nmax * 2) ? n : nmax * 2;
+ nmax = n;
+ }
+
+ for (var i = 0; i < n; i++) {
+ var t = i * 1.0 / n;
+ var p = this.getBezierPoint(t, x0, y0, x1, y1, x2, y2, x3, y3);
+ this.drawPoint(ctx, p[0], p[1], type);
+ }
+};
+
+Neo.Painter.prototype.prevLine = null; // 始点または終点が2度プロットされることがあるので
+Neo.Painter.prototype.drawLine = function(ctx, x0, y0, x1, y1, type) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+ var prev = [x0, y0, x1, y1];
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+ var r = Math.ceil(this.lineWidth / 2);
+
+ var left = ((x0 < x1) ? x0 : x1) - r;
+ var top = ((y0 < y1) ? y0 : y1) - r;
+
+ var imageData = ctx.getImageData(left, top, width + r*2, height + r*2);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+ this.aerr = 0;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+ this.setPoint(buf8, imageData.width, x0, y0, left, top, type);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+
+ this.prevLine = prev;
+};
+
+Neo.Painter.prototype.drawPoint = function(ctx, x, y, type) {
+ this.drawLine(ctx, x, y, x, y, type);
+};
+
+Neo.Painter.prototype.xorRect = function(buf32, bufWidth, x, y, width, height, c) {
+ var index = y * bufWidth + x;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ buf32[index] ^= c;
+ index++;
+ }
+ index += width - bufWidth;
+ }
+};
+
+Neo.Painter.prototype.drawXORRect = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ if (!c) c = 0xffffff;
+
+ if (isFill) {
+ this.xorRect(buf32, width, 0, 0, width, height, c);
+
+ } else {
+ for (var i = 0; i < width; i++) { //top
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ if (height > 1) {
+ index = width;
+ for (var i = 1; i < height; i++) { //left
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ if (width > 1) {
+ index = width * 2 - 1;
+ for (var i = 1; i < height - 1; i++) { //right
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ index = width * (height - 1) + 1;
+ for (var i = 1; i < width; i++) { // bottom
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXOREllipse = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+ if (!c) c = 0xffffff;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+
+ var a = width-1, b = height-1, b1 = b&1; /* values of diameter */
+ var dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
+ var err = dx+dy+b1*a*a, e2; /* error of 1.step */
+
+ var x0 = x;
+ var y0 = y;
+ var x1 = x0+a;
+ var y1 = y0+b;
+
+ if (x0 > x1) { x0 = x1; x1 += a; }
+ if (y0 > y1) y0 = y1;
+ y0 += Math.floor((b+1)/2); y1 = y0-b1; /* starting pixel */
+ a *= 8*a; b1 = 8*b*b;
+ var ymin = y0 - 1;
+
+ do {
+ if (isFill) {
+ if (ymin < y0) {
+ this.xorRect(buf32, width, x0-x, y0 - y, x1 - x0, 1, c);
+ if (y0 != y1) {
+ this.xorRect(buf32, width, x0-x, y1 - y, x1 - x0, 1, c);
+ }
+ ymin = y0;
+ }
+ } else {
+ this.xorPixel(buf32, width, x1-x, y0-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x0-x, y0-y, c);
+ }
+ if (y0 != y1) {
+ this.xorPixel(buf32, width, x0-x, y1-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x1-x, y1-y, c);
+ }
+ }
+ }
+ e2 = 2*err;
+ if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
+ if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
+ } while (x0 <= x1);
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXORLine = function(ctx, x0, y0, x1, y1, c) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+
+ var left = ((x0 < x1) ? x0 : x1);
+ var top = ((y0 < y1) ? y0 : y1);
+// console.log("left:"+left+" top:"+top+" width:"+width+" height:"+height);
+
+ var imageData = ctx.getImageData(left, top, width + 1, height + 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+
+ this.xorPixel(buf32, imageData.width, x0 - left, y0 - top, c);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+};
+
+
+Neo.Painter.prototype.eraseRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var a = 1.0 - this.alpha;
+ if (a != 0) {
+ a = Math.ceil(2.0 / a);
+ } else {
+ a = 255;
+ }
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (!this.isMasked(buf8, index)) {
+ buf8[index + 3] -= a;
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipH = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(width / 2);
+ for (var j = 0; j < height; j++) {
+ var index = j * width;
+ var index2 = index + (width - 1);
+ for (var i = 0; i < half; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 -i];
+ buf32[index2 - i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipV = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(height / 2);
+ for (var j = 0; j < half; j++) {
+ var index = j * width;
+ var index2 = (height - 1 - j) * width;
+ for (var i = 0; i < width; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 + i];
+ buf32[index2 + i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.merge = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = [];
+ var buf32 = [];
+ var buf8 = [];
+ for (var i = 0; i < 2; i++) {
+ imageData[i] = this.canvasCtx[i].getImageData(x, y, width, height);
+ buf32[i] = new Uint32Array(imageData[i].data.buffer);
+ buf8[i] = new Uint8ClampedArray(imageData[i].data.buffer);
+ }
+
+ var dst = this.current;
+ var src = (dst == 1) ? 0 : 1;
+ var size = width * height;
+ var index = 0;
+ for (var i = 0; i < size; i++) {
+ var r0 = buf8[0][index + 0];
+ var g0 = buf8[0][index + 1];
+ var b0 = buf8[0][index + 2];
+ var a0 = buf8[0][index + 3] / 255.0;
+ var r1 = buf8[1][index + 0];
+ var g1 = buf8[1][index + 1];
+ var b1 = buf8[1][index + 2];
+ var a1 = buf8[1][index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var r = Math.floor((r1 * a1 + r0 * a0 * (1 - a1)) / a + 0.5);
+ var g = Math.floor((g1 * a1 + g0 * a0 * (1 - a1)) / a + 0.5);
+ var b = Math.floor((b1 * a1 + b0 * a0 * (1 - a1)) / a + 0.5);
+ }
+ buf8[src][index + 0] = 0;
+ buf8[src][index + 1] = 0;
+ buf8[src][index + 2] = 0;
+ buf8[src][index + 3] = 0;
+ buf8[dst][index + 0] = r;
+ buf8[dst][index + 1] = g;
+ buf8[dst][index + 2] = b;
+ buf8[dst][index + 3] = Math.floor(a * 255 + 0.5);
+ index += 4;
+ }
+
+ for (var i = 0; i < 2; i++) {
+ imageData[i].data.set(buf8[i]);
+ this.canvasCtx[i].putImageData(imageData[i], x, y);
+ }
+};
+
+Neo.Painter.prototype.blurRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) tmp[i] = buf8[i];
+
+ var index = 0;
+ var a1 = this.alpha / 12;
+ var blur = a1;
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+
+ if (i > 0) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < width - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > 0) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < height - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ var w = rgba[4];
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.ceil((rgba[3] / w) * 255.0);
+
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.addBlur = function(buffer, index, a, rgba) {
+ var r0 = rgba[0];
+ var g0 = rgba[1];
+ var b0 = rgba[2];
+ var a0 = rgba[3];
+ var r1 = buffer[index + 0];
+ var g1 = buffer[index + 1];
+ var b1 = buffer[index + 2];
+ var a1 = (buffer[index + 3] / 255.0) * a;
+ rgba[4] += a;
+
+ var a = a0 + a1;
+ if (a > 0) {
+ rgba[0] = (r1 * a1 + r0 * a0) / (a0 + a1);
+ rgba[1] = (g1 * a1 + g0 * a0) / (a0 + a1);
+ rgba[2] = (b1 * a1 + b0 * a0) / (a0 + a1);
+ rgba[3] = a;
+ }
+};
+
+Neo.Painter.prototype.pickColor = function(x, y) {
+ var r = 0xff, g = 0xff, b = 0xff, a;
+
+ x = Math.floor(x);
+ y = Math.floor(y);
+ if (x >= 0 && x < this.canvasWidth &&
+ y >= 0 && y < this.canvasHeight) {
+
+ for (var i = 0; i < 2; i++) {
+ if (this.visible[i]) {
+ var ctx = this.canvasCtx[i];
+ var imageData = ctx.getImageData(x, y, 1, 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var a = buf8[3] / 255.0;
+ r = r * (1.0 - a) + buf8[2] * a;
+ g = g * (1.0 - a) + buf8[1] * a;
+ b = b * (1.0 - a) + buf8[0] * a;
+ }
+ }
+ r = Math.max(Math.min(Math.round(r), 255), 0);
+ g = Math.max(Math.min(Math.round(g), 255), 0);
+ b = Math.max(Math.min(Math.round(b), 255), 0);
+ var result = r | g<<8 | b<<16;
+ }
+ this.setColor(result);
+
+
+ if (this.current > 0) {
+ if (a == 0 && (result == 0xffffff || this.getEmulationMode() < 2.16)) {
+ this.setToolByType(Neo.eraserTip.tools[Neo.eraserTip.mode]);
+
+ } else {
+ if (Neo.eraserTip.selected) {
+ this.setToolByType(Neo.penTip.tools[Neo.penTip.mode]);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.fillHorizontalLine = function(buf32, x0, x1, y) {
+ var index = y * this.canvasWidth + x0;
+ var fillColor = this.getColor();
+ for (var x = x0; x <= x1; x++) {
+ buf32[index++] = fillColor;
+ }
+};
+
+Neo.Painter.prototype.scanLine = function(x0, x1, y, baseColor, buf32, stack) {
+ var width = this.canvasWidth;
+ for (var x = x0; x <= x1; x++) {
+ stack.push({x:x, y: y})
+ }
+/*
+ while (x0 <= x1) {
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] == baseColor) break;
+ }
+ if (x1 < x0) break;
+
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] != baseColor) break;
+ }
+ stack.push({x:x0 - 1, y: y})
+ }
+*/
+};
+
+Neo.Painter.prototype.fill = function(x, y, ctx) {
+ x = Math.round(x);
+ y = Math.round(y);
+
+ if (x < 0 || x >= this.canvasWidth || y < 0 || y >= this.canvasHeight) {
+ return;
+ }
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var width = imageData.width;
+ var stack = [{x: x, y: y}];
+
+ var baseColor = buf32[y * width + x];
+ var fillColor = this.getColor();
+
+ if ((baseColor & 0xff000000) == 0 || (baseColor != fillColor)) {
+ while (stack.length > 0) {
+ if (stack.length > 1000000) {
+ console.log('too much stack')
+ break;
+ }
+ var point = stack.pop();
+ var x = point.x;
+ var y = point.y;
+ var x0 = x;
+ var x1 = x;
+ if (buf32[y * width + x] == fillColor) continue;
+ if (buf32[y * width + x] != baseColor) continue;
+
+ for (; 0 < x0; x0--) {
+ if (buf32[y * width + (x0 - 1)] != baseColor) break;
+ }
+ for (; x1 < this.canvasWidth - 1; x1++) {
+ if (buf32[y * width + (x1 + 1)] != baseColor) break;
+ }
+ this.fillHorizontalLine(buf32, x0, x1, y);
+
+ if (y + 1 < this.canvasHeight) {
+ this.scanLine(x0, x1, y + 1, baseColor, buf32, stack);
+ }
+ if (y - 1 >= 0) {
+ this.scanLine(x0, x1, y - 1, baseColor, buf32, stack);
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.copy = function(x, y, width, height) {
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+
+ var imageData = this.canvasCtx[this.current].getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ this.temp = new Uint32Array(buf32.length);
+ for (var i = 0; i < buf32.length; i++) {
+ this.temp[i] = buf32[i];
+ }
+
+ //tempCanvasに乗せる画像を作る
+ imageData = this.tempCanvasCtx.getImageData(x, y, width, height);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ if (this.temp[i] >> 24) {
+ buf32[i] = this.temp[i] | 0xff000000;
+ } else {
+ buf32[i] = 0xffffffff;
+ }
+ }
+ imageData.data.set(buf8);
+ this.tempCanvasCtx.putImageData(imageData, x, y);
+};
+
+
+Neo.Painter.prototype.paste = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+// console.log(this.tempX, this.tempY);
+
+ var imageData = ctx.getImageData(x + this.tempX, y + this.tempY, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ buf32[i] = this.temp[i];
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x + this.tempX, y + this.tempY);
+
+ this.temp = null;
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.turn = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+
+ // 傾けツールのバグを再現するため一番上のラインで対象領域を埋める
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var temp = new Uint32Array(buf32.length);
+
+ var index = 0;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ temp[index] = buf32[index];
+ if (index >= width) {
+ buf32[index] = buf32[index % width];
+ }
+ index++;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+
+ // 90度回転させて貼り付け
+ imageData = ctx.getImageData(x, y, height, width);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ index = 0;
+ for (var j = height - 1; j >= 0; j--) {
+ for (var i = 0; i < width; i++) {
+ buf32[i * height + j] = temp[index++];
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.doFill = function(ctx, x, y, width, height, maskFunc) {
+ if (Math.round(x) != x) console.log("*");
+ if (Math.round(width) != width) console.log("*");
+ if (Math.round(height) != height) console.log("*");
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.ALPHATYPE_FILL);
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (maskFunc && maskFunc.call(this, i, j, width, height)) {
+ //なぜか加算逆加算は適用されない
+ if (this.maskType >= Neo.Painter.MASKTYPE_ADD ||
+ !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+
+ if (a > 0) {
+ var a1x = a1;
+ var ax = 1 + a0 * (1 - a1x);
+
+ var r = (r1 + r0 * a0 * (1 - a1x)) / ax;
+ var g = (g1 + g0 * a0 * (1 - a1x)) / ax;
+ var b = (b1 + b0 * a0 * (1 - a1x)) / ax
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+ }
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.rectFillMask = function(x, y, width, height) {
+ return true;
+};
+
+Neo.Painter.prototype.rectMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ return (x < d || x > width - 1 - d ||
+ y < d || y > height - 1 - d) ? true : false;
+};
+
+Neo.Painter.prototype.ellipseFillMask = function(x, y, width, height) {
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ return ((x * x) + (y * y) < 1) ? true : false;
+}
+
+Neo.Painter.prototype.ellipseMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+
+ if (cx <= d || cy <= d) return this.ellipseFillMask(x, y, width, height);
+
+ var x2 = (x - cx) / (cx - d + 1);
+ var y2 = (y - cy) / (cy - d + 1);
+
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ if ((x * x) + (y * y) < 1) {
+ if ((x2 * x2) + (y2 * y2) >= 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.getDestCanvasPosition = function(mx, my, isClip, isCenter) {
+ var mx = Math.floor(mx); //Math.round(mx);
+ var my = Math.floor(my); //Math.round(my);
+ if (isCenter) {
+ mx += 0.499;
+ my += 0.499;
+ }
+ var x = (mx - this.zoomX + this.destCanvas.width * 0.5 / this.zoom) * this.zoom;
+ var y = (my - this.zoomY + this.destCanvas.height * 0.5 / this.zoom) * this.zoom;
+
+ if (isClip) {
+ x = Math.max(Math.min(x, this.destCanvas.width), 0);
+ y = Math.max(Math.min(y, this.destCanvas.height), 0);
+ }
+ return {x:x, y:y};
+};
+
+Neo.Painter.prototype.isWidget = function(element) {
+ while (1) {
+ if (element == null ||
+ element.id == "canvas" ||
+ element.id == "container") break;
+
+ if (element.id == "tools" ||
+ element.className == "buttonOn" ||
+ element.className == "buttonOff" ||
+ element.className == "inputText") {
+ return true;
+ }
+ element = element.parentNode;
+ }
+ return false;
+};
+
+Neo.Painter.prototype.isContainer = function(element) {
+ while (1) {
+ if (element == null) break;
+ if (element.id == "container") return true;
+ element = element.parentNode;
+ }
+ return false;
+};
+
+Neo.Painter.prototype.cancelTool = function(e) {
+ if (this.tool) {
+ this.isMouseDown = false;
+ this.tool.upHandler(this);
+
+// switch (this.tool.type) {
+// case Neo.Painter.TOOLTYPE_HAND:
+// case Neo.Painter.TOOLTYPE_SLIDER:
+// this.isMouseDown = false;
+// this.tool.upHandler(this);
+// }
+ }
+};
+
+Neo.Painter.prototype.loadImage = function (filename) {
+ console.log("loadImage " + filename);
+ var img = new Image();
+ img.src = filename;
+ img.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].drawImage(img, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ };
+};
+
+Neo.Painter.prototype.loadSession = function (filename) {
+ if (Neo.storage) {
+ var img0 = new Image();
+ img0.src = Neo.storage.getItem('layer0');
+ img0.onload = function() {
+ var img1 = new Image();
+ img1.src = Neo.storage.getItem('layer1');
+ img1.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[1].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[0].drawImage(img0, 0, 0);
+ oe.canvasCtx[1].drawImage(img1, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.saveSession = function() {
+ if (Neo.storage) {
+ Neo.storage.setItem('timestamp', +(new Date()));
+ Neo.storage.setItem('layer0', this.canvas[0].toDataURL('image/png'));
+ Neo.storage.setItem('layer1', this.canvas[1].toDataURL('image/png'));
+ }
+};
+
+Neo.Painter.prototype.clearSession = function() {
+ if (Neo.storage) {
+ Neo.storage.removeItem('timestamp');
+ Neo.storage.removeItem('layer0');
+ Neo.storage.removeItem('layer1');
+ }
+};
+
+Neo.Painter.prototype.sortColor = function(r0, g0, b0) {
+ var min = (r0 < g0) ? ((r0 < b0) ? 0 : 2) : ((g0 < b0) ? 1 : 2);
+ var max = (r0 > g0) ? ((r0 > b0) ? 0 : 2) : ((g0 > b0) ? 1 : 2);
+ var mid = (min + max == 1) ? 2 : ((min + max == 2) ? 1 : 0);
+ return [min, mid, max];
+};
+
+Neo.Painter.prototype.doText = function(x, y, string, fontSize) {
+ //テキスト描画
+ //描画位置がずれるので適当に調整
+ var offset = parseInt(fontSize, 10);
+// y -= Math.round((5.0 + offset/8) / this.zoom);
+// x += Math.round(2.0 / this.zoom);
+
+ var ctx = this.tempCanvasCtx;
+ ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ ctx.save();
+ ctx.translate(x, y);
+// ctx.scale(1/this.zoom, 1/this.zoom);
+
+ var fontFamily = Neo.painter.inputText.style.fontFamily || "Arial";
+ ctx.font = fontSize + " " + fontFamily;
+
+ ctx.fillStyle = 0;
+ ctx.fillText(string, 0, 0);
+ ctx.restore();
+
+ // 適当に二値化
+ var c = this.getColor();
+ var r = c & 0xff;
+ var g = (c & 0xff00) >> 8;
+ var b = (c & 0xff0000) >> 16;
+ var a = Math.round(this.alpha * 255.0);
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var length = this.canvasWidth * this.canvasHeight;
+ var index = 0;
+ for (var i = 0; i < length; i++) {
+ if (buf8[index + 3] >= 0x60) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ } else {
+ buf8[index + 0] = 0;
+ buf8[index + 1] = 0;
+ buf8[index + 2] = 0;
+ buf8[index + 3] = 0;
+ }
+ index += 4;
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ //キャンバスに貼り付け
+ ctx = this.canvasCtx[this.current];
+ ctx.globalAlpha = 1.0;
+ ctx.drawImage(this.tempCanvas,
+ 0, 0, this.canvasWidth, this.canvasHeight,
+ 0, 0, this.canvasWidth, this.canvasHeight);
+
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.isUIPaused = function() {
+ if (this.drawType == Neo.Painter.DRAWTYPE_BEZIER) {
+ if (this.tool.step && this.tool.step > 0) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.getEmulationMode = function() {
+ return parseFloat(Neo.config.neo_emulation_mode || 2.22)
+};
+
+'use strict';
+
+Neo.ToolBase = function() {};
+
+Neo.ToolBase.prototype.startX;
+Neo.ToolBase.prototype.startY;
+Neo.ToolBase.prototype.init = function(oe) {}
+Neo.ToolBase.prototype.kill = function(oe) {}
+Neo.ToolBase.prototype.lineType = Neo.Painter.LINETYPE_NONE;
+
+Neo.ToolBase.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+};
+
+Neo.ToolBase.prototype.upHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.moveHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.transformForZoom = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ ctx.translate(oe.canvasWidth * 0.5, oe.canvasHeight * 0.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+};
+
+Neo.ToolBase.prototype.getType = function() {
+ return this.type;
+};
+
+Neo.ToolBase.prototype.getToolButton = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TEXT:
+ return Neo.penTip;
+
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ return Neo.pen2Tip;
+
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.effectTip;
+
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+ case Neo.Painter.TOOLTYPE_FLIP_H:
+ case Neo.Painter.TOOLTYPE_FLIP_V:
+ case Neo.Painter.TOOLTYPE_TURN:
+ return Neo.effect2Tip;
+
+ case Neo.Painter.TOOLTYPE_ERASER:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ return Neo.eraserTip;
+
+ case Neo.Painter.TOOLTYPE_FILL:
+ return Neo.fillButton;
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.getReserve = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_ERASER:
+ return Neo.reserveEraser;
+
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_FIP_H:
+ case Neo.Painter.TOOLTYPE_FIP_V:
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+
+ case Neo.Painter.TOOLTYPE_TEXT:
+ case Neo.Painter.TOOLTYPE_TURN:
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.reservePen;
+
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.updateUI();
+ }
+};
+
+Neo.ToolBase.prototype.saveStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ reserve.size = Neo.painter.lineWidth;
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ DrawToolBase(描画ツールのベースクラス)
+ -------------------------------------------------------------------------
+*/
+
+Neo.DrawToolBase = function() {};
+Neo.DrawToolBase.prototype = new Neo.ToolBase();
+Neo.DrawToolBase.prototype.isUpMove = false;
+Neo.DrawToolBase.prototype.step = 0;
+
+Neo.DrawToolBase.prototype.init = function() {
+ this.step = 0;
+ this.isUpMove = true;
+};
+
+Neo.DrawToolBase.prototype.downHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierDownHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.moveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upMoveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.keyDownHandler = function(e) {
+ switch (Neo.painter.drawType) {
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierKeyDownHandler(e); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.rollOverHandler= function(oe) {};
+Neo.DrawToolBase.prototype.rollOutHandler= function(oe) {
+ if (!oe.isMouseDown && !oe.isMouseDownRight){
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+
+/* FreeHand (手書き) */
+
+Neo.DrawToolBase.prototype.freeHandDownHandler = function(oe) {
+ //Register undo first;
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ this.isUpMove = false;
+ var ctx = oe.canvasCtx[oe.current];
+ if (oe.alpha >= 1 || this.lineType != Neo.Painter.LINETYPE_BRUSH) {
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, x0, y0, this.lineType);
+ }
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ if (oe.alpha >= 1) {
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.mouseX, oe.mouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ }
+};
+
+Neo.DrawToolBase.prototype.freeHandUpHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ // oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ // this.drawCursor(oe);
+ oe.prevLine = null;
+};
+
+Neo.DrawToolBase.prototype.freeHandMoveHandler = function(oe) {
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ var x1 = Math.floor(oe.prevMouseX);
+ var y1 = Math.floor(oe.prevMouseY);
+ oe.drawLine(ctx, x0, y0, x1, y1, this.lineType);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.prevMouseX, oe.prevMouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+};
+
+Neo.DrawToolBase.prototype.freeHandUpMoveHandler = function(oe) {
+ this.isUpMove = true;
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+ this.drawCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.drawCursor = function(oe) {
+ if (oe.lineWidth <= 8) return;
+ var mx = oe.mouseX;
+ var my = oe.mouseY;
+ var d = oe.lineWidth;
+
+ var x = (mx - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y = (my - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var r = d * 0.5 * oe.zoom;
+
+ if (!(x > -r &&
+ y > -r &&
+ x < oe.destCanvas.width + r &&
+ y < oe.destCanvas.height + r)) return;
+
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var c = (this.type == Neo.Painter.TOOLTYPE_ERASER) ? 0x0000ff : 0xffff7f;
+ oe.drawXOREllipse(ctx, x-r, y-r, r*2, r*2, false, c);
+
+ ctx.restore();
+ oe.cursorRect = oe.getBound(mx, my, mx, my, Math.ceil(d / 2));
+}
+
+
+/* Line (直線) */
+
+Neo.DrawToolBase.prototype.lineDownHandler = function(oe) {
+ this.isUpMove = false;
+ this.startX = Math.floor(oe.mouseX);
+ this.startY = Math.floor(oe.mouseY);
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.lineUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+
+ oe._pushUndo();
+ oe.prepareDrawing();
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, this.startX, this.startY, this.lineType);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.lineMoveHandler = function(oe) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.drawLineCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.lineUpMoveHandler = function(oe) {
+};
+
+Neo.DrawToolBase.prototype.drawLineCursor = function(oe, mx, my) {
+ if (!mx) mx = Math.floor(oe.mouseX);
+ if (!my) my = Math.floor(oe.mouseY);
+ var nx = this.startX;
+ var ny = this.startY;
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var x0 = (mx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y0 = (my +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var x1 = (nx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y1 = (ny +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ oe.drawXORLine(ctx, x0, y0, x1, y1);
+
+ ctx.restore();
+};
+
+
+/* Bezier (BZ曲線) */
+
+Neo.DrawToolBase.prototype.bezierDownHandler = function(oe) {
+ this.isUpMove = false;
+
+ if (this.step == 0) {
+ this.startX = this.x0 = Math.floor(oe.mouseX);
+ this.startY = this.y0 = Math.floor(oe.mouseY);
+ }
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.bezierUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+ }
+
+ this.step++;
+ switch (this.step) {
+ case 1:
+ oe.prepareDrawing();
+ this.x3 = Math.floor(oe.mouseX);
+ this.y3 = Math.floor(oe.mouseY);
+ break;
+
+ case 2:
+ this.x1 = Math.floor(oe.mouseX);
+ this.y1 = Math.floor(oe.mouseY);
+ break;
+
+ case 3:
+ this.x2 = Math.floor(oe.mouseX);
+ this.y2 = Math.floor(oe.mouseY);
+
+ oe._pushUndo();
+ oe.drawBezier(oe.canvasCtx[oe.current],
+ this.x0, this.y0, this.x1, this.y1,
+ this.x2, this.y2, this.x3, this.y3, this.lineType);
+
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.step = 0;
+ break;
+
+ default:
+ this.step = 0;
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierMoveHandler = function(oe) {
+ switch (this.step) {
+ case 0:
+ if (!this.isUpMove) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawLineCursor(oe);
+ }
+ break;
+ case 1:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor1(oe);
+ break;
+
+ case 2:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor2(oe);
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierUpMoveHandler = function(oe) {
+ this.bezierMoveHandler(oe);
+};
+
+Neo.DrawToolBase.prototype.bezierKeyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escでキャンセル
+ this.step = 0;
+
+ var oe = Neo.painter;
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+
+Neo.DrawToolBase.prototype.drawBezierCursor1 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ // var x = oe.mouseX; //Math.floor(oe.mouseX);
+ // var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(x, y, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p0.x, p0.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ x, y,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ ctx.restore();
+};
+
+Neo.DrawToolBase.prototype.drawBezierCursor2 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ // var x = oe.mouseX; //Math.floor(oe.mouseX);
+ // var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(oe.mouseX, oe.mouseY, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p1 = oe.getDestCanvasPosition(this.x1, this.y1, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p3.x, p3.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXORLine(ctx, p0.x, p0.y, p1.x, p1.y);
+ oe.drawXOREllipse(ctx, p1.x - 4, p1.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ this.x1, this.y1,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+ ctx.restore();
+};
+
+/*
+ -------------------------------------------------------------------------
+ Pen(鉛筆)
+ -------------------------------------------------------------------------
+*/
+
+Neo.PenTool = function() {};
+Neo.PenTool.prototype = new Neo.DrawToolBase();
+Neo.PenTool.prototype.type = Neo.Painter.TOOLTYPE_PEN;
+Neo.PenTool.prototype.lineType = Neo.Painter.LINETYPE_PEN;
+
+Neo.PenTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+}
+
+/*
+ -------------------------------------------------------------------------
+ Brush(水彩)
+ -------------------------------------------------------------------------
+*/
+
+Neo.BrushTool = function() {};
+Neo.BrushTool.prototype = new Neo.DrawToolBase();
+Neo.BrushTool.prototype.type = Neo.Painter.TOOLTYPE_BRUSH;
+Neo.BrushTool.prototype.lineType = Neo.Painter.LINETYPE_BRUSH;
+
+Neo.BrushTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.getAlpha();
+ Neo.updateUI();
+ }
+};
+
+Neo.BrushTool.prototype.getAlpha = function() {
+ var alpha = 241 - Math.floor(Neo.painter.lineWidth / 2) * 6;
+ return alpha / 255.0;
+};
+
+/*
+ -------------------------------------------------------------------------
+ Tone(トーン)
+ -------------------------------------------------------------------------
+*/
+
+Neo.ToneTool = function() {};
+Neo.ToneTool.prototype = new Neo.DrawToolBase();
+Neo.ToneTool.prototype.type = Neo.Painter.TOOLTYPE_TONE;
+Neo.ToneTool.prototype.lineType = Neo.Painter.LINETYPE_TONE;
+
+Neo.ToneTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 23 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Eraser(消しペン)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EraserTool = function() {};
+Neo.EraserTool.prototype = new Neo.DrawToolBase();
+Neo.EraserTool.prototype.type = Neo.Painter.TOOLTYPE_ERASER;
+Neo.EraserTool.prototype.lineType = Neo.Painter.LINETYPE_ERASER;
+
+
+/*
+ -------------------------------------------------------------------------
+ Blur(ぼかし)
+ -------------------------------------------------------------------------
+*/
+
+Neo.BlurTool = function() {};
+Neo.BlurTool.prototype = new Neo.DrawToolBase();
+Neo.BlurTool.prototype.type = Neo.Painter.TOOLTYPE_BLUR;
+Neo.BlurTool.prototype.lineType = Neo.Painter.LINETYPE_BLUR;
+
+Neo.BlurTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Dodge(覆い焼き)
+ -------------------------------------------------------------------------
+*/
+
+Neo.DodgeTool = function() {};
+Neo.DodgeTool.prototype = new Neo.DrawToolBase();
+Neo.DodgeTool.prototype.type = Neo.Painter.TOOLTYPE_DODGE;
+Neo.DodgeTool.prototype.lineType = Neo.Painter.LINETYPE_DODGE;
+
+Neo.DodgeTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Burn(焼き込み)
+ -------------------------------------------------------------------------
+*/
+
+Neo.BurnTool = function() {};
+Neo.BurnTool.prototype = new Neo.DrawToolBase();
+Neo.BurnTool.prototype.type = Neo.Painter.TOOLTYPE_BURN;
+Neo.BurnTool.prototype.lineType = Neo.Painter.LINETYPE_BURN;
+
+Neo.BurnTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Hand(スクロール)
+ -------------------------------------------------------------------------
+*/
+
+Neo.HandTool = function() {};
+Neo.HandTool.prototype = new Neo.ToolBase();
+Neo.HandTool.prototype.type = Neo.Painter.TOOLTYPE_HAND;
+Neo.HandTool.prototype.isUpMove = false;
+Neo.HandTool.prototype.reverse = false;
+
+Neo.HandTool.prototype.downHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ this.isDrag = true;
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+};
+
+Neo.HandTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+};
+
+Neo.HandTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var dx = this.startX - oe.rawMouseX;
+ var dy = this.startY - oe.rawMouseY;
+
+ var ax = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var ay = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barWidth = oe.destCanvas.width * ax;
+ var barHeight = oe.destCanvas.height * ay;
+ var scrollWidthInScreen = oe.destCanvas.width - barWidth - 2;
+ var scrollHeightInScreen = oe.destCanvas.height - barHeight - 2;
+
+ dx *= oe.scrollWidth / scrollWidthInScreen;
+ dy *= oe.scrollHeight / scrollHeightInScreen;
+
+ if (this.reverse) {
+ dx *= -1;
+ dy *= -1;
+ }
+
+ oe.setZoomPosition(oe.zoomX - dx, oe.zoomY - dy);
+
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+ }
+};
+
+Neo.HandTool.prototype.upMoveHandler = function(oe) {}
+Neo.HandTool.prototype.rollOverHandler= function(oe) {}
+Neo.HandTool.prototype.rollOutHandler= function(oe) {};
+
+/*
+ -------------------------------------------------------------------------
+ Slider(色やサイズのスライダを操作している時)
+ -------------------------------------------------------------------------
+*/
+
+Neo.SliderTool = function() {};
+Neo.SliderTool.prototype = new Neo.ToolBase();
+Neo.SliderTool.prototype.type = Neo.Painter.TOOLTYPE_SLIDER;
+Neo.SliderTool.prototype.isUpMove = false;
+Neo.SliderTool.prototype.alt = false;
+
+Neo.SliderTool.prototype.downHandler = function(oe) {
+ if (!oe.isShiftDown) this.isDrag = true;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].downHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].upHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].moveHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+ }
+};
+
+Neo.SliderTool.prototype.upMoveHandler = function(oe) {}
+Neo.SliderTool.prototype.rollOverHandler= function(oe) {}
+Neo.SliderTool.prototype.rollOutHandler= function(oe) {}
+
+/*
+ -------------------------------------------------------------------------
+ Fill(塗り潰し)
+ -------------------------------------------------------------------------
+*/
+
+Neo.FillTool = function() {};
+Neo.FillTool.prototype = new Neo.ToolBase();
+Neo.FillTool.prototype.type = Neo.Painter.TOOLTYPE_FILL;
+Neo.FillTool.prototype.isUpMove = false;
+
+Neo.FillTool.prototype.downHandler = function(oe) {
+ var x = Math.floor(oe.mouseX);
+ var y = Math.floor(oe.mouseY);
+ oe._pushUndo();
+ oe.fill(x, y, oe.canvasCtx[oe.current]);
+};
+
+Neo.FillTool.prototype.upHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.rollOutHandler= function(oe) {};
+Neo.FillTool.prototype.upMoveHandler = function(oe) {}
+Neo.FillTool.prototype.rollOverHandler= function(oe) {}
+
+
+/*
+ -------------------------------------------------------------------------
+ EraseAll(全消し)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EraseAllTool = function() {};
+Neo.EraseAllTool.prototype = new Neo.ToolBase();
+Neo.EraseAllTool.prototype.type = Neo.Painter.TOOLTYPE_ERASEALL;
+Neo.EraseAllTool.prototype.isUpMove = false;
+
+Neo.EraseAllTool.prototype.downHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ oe.canvasCtx[oe.current].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.EraseAllTool.prototype.upHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.rollOutHandler= function(oe) {};
+Neo.EraseAllTool.prototype.upMoveHandler = function(oe) {};
+Neo.EraseAllTool.prototype.rollOverHandler= function(oe) {};
+
+
+/*
+ -------------------------------------------------------------------------
+ EffectToolBase(エフェックトツールのベースクラス)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EffectToolBase = function() {};
+Neo.EffectToolBase.prototype = new Neo.ToolBase();
+Neo.EffectToolBase.prototype.isUpMove = false;
+
+Neo.EffectToolBase.prototype.downHandler = function(oe) {
+ this.isUpMove = false;
+
+ this.startX = this.endX = oe.clipMouseX;
+ this.startY = this.endY = oe.clipMouseY;
+};
+
+Neo.EffectToolBase.prototype.upHandler = function(oe) {
+ if (this.isUpMove) return;
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+ var ctx = oe.canvasCtx[oe.current];
+
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (x + width > oe.canvasWidth) width = oe.canvasWidth - x;
+ if (y + height > oe.canvasHeight) height = oe.canvasHeight - y;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.prepareDrawing();
+ this.doEffect(oe, x, y, width, height);
+ }
+
+ if (oe.tool.type != Neo.Painter.TOOLTYPE_PASTE) {
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.EffectToolBase.prototype.moveHandler = function(oe) {
+ this.endX = oe.clipMouseX;
+ this.endY = oe.clipMouseY;
+
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ this.drawCursor(oe);
+};
+
+Neo.EffectToolBase.prototype.rollOutHandler= function(oe) {};
+Neo.EffectToolBase.prototype.upMoveHandler = function(oe) {};
+Neo.EffectToolBase.prototype.rollOverHandler= function(oe) {};
+
+Neo.EffectToolBase.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.startX, this.startY, true);
+ var end = oe.getDestCanvasPosition(this.endX, this.endY, true);
+
+ var x = (start.x < end.x) ? start.x : end.x;
+ var y = (start.y < end.y) ? start.y : end.y;
+ var width = Math.abs(start.x - end.x) + oe.zoom;
+ var height = Math.abs(start.y - end.y) + oe.zoom;
+
+ if (this.isEllipse) {
+ oe.drawXOREllipse(ctx, x, y, width, height, this.isFill);
+
+ } else {
+ oe.drawXORRect(ctx, x, y, width, height, this.isFill);
+ }
+ ctx.restore();
+};
+
+Neo.EffectToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.defaultAlpha || 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+ -------------------------------------------------------------------------
+ EraseRect(消し四角)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EraseRectTool = function() {};
+Neo.EraseRectTool.prototype = new Neo.EffectToolBase();
+Neo.EraseRectTool.prototype.type = Neo.Painter.TOOLTYPE_ERASERECT;
+
+Neo.EraseRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.eraseRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ FlipH(左右反転)
+ -------------------------------------------------------------------------
+*/
+
+Neo.FlipHTool = function() {};
+Neo.FlipHTool.prototype = new Neo.EffectToolBase();
+Neo.FlipHTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_H;
+
+Neo.FlipHTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipH(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ FlipV(上下反転)
+ -------------------------------------------------------------------------
+*/
+
+Neo.FlipVTool = function() {};
+Neo.FlipVTool.prototype = new Neo.EffectToolBase();
+Neo.FlipVTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_V;
+
+Neo.FlipVTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipV(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ DodgeRect(角取り)
+ -------------------------------------------------------------------------
+*/
+
+Neo.BlurRectTool = function() {};
+Neo.BlurRectTool.prototype = new Neo.EffectToolBase();
+Neo.BlurRectTool.prototype.type = Neo.Painter.TOOLTYPE_BLURRECT;
+
+Neo.BlurRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.blurRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.BlurRectTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 0.5;
+ Neo.updateUI();
+ };
+}
+
+/*
+ -------------------------------------------------------------------------
+ Turn(傾け)
+ -------------------------------------------------------------------------
+*/
+
+Neo.TurnTool = function() {};
+Neo.TurnTool.prototype = new Neo.EffectToolBase();
+Neo.TurnTool.prototype.type = Neo.Painter.TOOLTYPE_TURN;
+
+Neo.TurnTool.prototype.upHandler = function(oe) {
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.turn(x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Merge(レイヤー結合)
+ -------------------------------------------------------------------------
+*/
+
+Neo.MergeTool = function() {};
+Neo.MergeTool.prototype = new Neo.EffectToolBase();
+Neo.MergeTool.prototype.type = Neo.Painter.TOOLTYPE_MERGE;
+
+Neo.MergeTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.merge(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Copy(コピー)
+ -------------------------------------------------------------------------
+*/
+
+Neo.CopyTool = function() {};
+Neo.CopyTool.prototype = new Neo.EffectToolBase();
+Neo.CopyTool.prototype.type = Neo.Painter.TOOLTYPE_COPY;
+
+Neo.CopyTool.prototype.doEffect = function(oe, x, y, width, height) {
+ oe.copy(x, y, width, height);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_PASTE);
+ oe.tool.x = x;
+ oe.tool.y = y;
+ oe.tool.width = width;
+ oe.tool.height = height;
+};
+
+/*
+ -------------------------------------------------------------------------
+ Paste(ペースト)
+ -------------------------------------------------------------------------
+*/
+
+Neo.PasteTool = function() {};
+Neo.PasteTool.prototype = new Neo.ToolBase();
+Neo.PasteTool.prototype.type = Neo.Painter.TOOLTYPE_PASTE;
+
+Neo.PasteTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+ this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.upHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.paste(this.x, this.y, this.width, this.height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+};
+
+Neo.PasteTool.prototype.moveHandler = function(oe) {
+ var dx = Math.floor(oe.mouseX - this.startX);
+ var dy = Math.floor(oe.mouseY - this.startY);
+ oe.tempX = dx;
+ oe.tempY = dy;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ // this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escでキャンセル
+ var oe = Neo.painter;
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+ }
+};
+
+Neo.PasteTool.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.x, this.y, true);
+ var end = oe.getDestCanvasPosition(this.x + this.width, this.y + this.height, true);
+
+ var x = start.x + oe.tempX * oe.zoom;
+ var y = start.y + oe.tempY * oe.zoom;
+ var width = Math.abs(start.x - end.x);
+ var height = Math.abs(start.y - end.y);
+ oe.drawXORRect(ctx, x, y, width, height);
+ ctx.restore();
+};
+
+/*
+ -------------------------------------------------------------------------
+ Rect(線四角)
+ -------------------------------------------------------------------------
+*/
+
+Neo.RectTool = function() {};
+Neo.RectTool.prototype = new Neo.EffectToolBase();
+Neo.RectTool.prototype.type = Neo.Painter.TOOLTYPE_RECT;
+
+Neo.RectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ RectFill(四角)
+ -------------------------------------------------------------------------
+*/
+
+Neo.RectFillTool = function() {};
+Neo.RectFillTool.prototype = new Neo.EffectToolBase();
+Neo.RectFillTool.prototype.type = Neo.Painter.TOOLTYPE_RECTFILL;
+
+Neo.RectFillTool.prototype.isFill = true;
+Neo.RectFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Ellipse(線楕円)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EllipseTool = function() {};
+Neo.EllipseTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSE;
+Neo.EllipseTool.prototype.isEllipse = true;
+Neo.EllipseTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ EllipseFill(楕円)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EllipseFillTool = function() {};
+Neo.EllipseFillTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseFillTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSEFILL;
+Neo.EllipseFillTool.prototype.isEllipse = true;
+Neo.EllipseFillTool.prototype.isFill = true;
+Neo.EllipseFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Text(テキスト)
+ -------------------------------------------------------------------------
+*/
+
+Neo.TextTool = function() {};
+Neo.TextTool.prototype = new Neo.ToolBase();
+Neo.TextTool.prototype.type = Neo.Painter.TOOLTYPE_TEXT;
+Neo.TextTool.prototype.isUpMove = false;
+
+Neo.TextTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+
+ if (Neo.painter.inputText) {
+ Neo.painter.updateInputText();
+
+ var rect = oe.container.getBoundingClientRect();
+ var text = Neo.painter.inputText;
+ var x = oe.rawMouseX - rect.left - 5;
+ var y = oe.rawMouseY - rect.top - 5;
+
+ text.style.left = x + "px";
+ text.style.top = y + "px";
+ text.style.display = "block";
+ text.focus();
+ }
+};
+
+Neo.TextTool.prototype.upHandler = function(oe) {
+};
+
+Neo.TextTool.prototype.moveHandler = function(oe) {};
+Neo.TextTool.prototype.upMoveHandler = function(oe) {};
+Neo.TextTool.prototype.rollOverHandler= function(oe) {};
+Neo.TextTool.prototype.rollOutHandler= function(oe) {};
+
+Neo.TextTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 13) { // Returnで確定
+ e.preventDefault();
+
+ var oe = Neo.painter;
+ var text = oe.inputText;
+ if (text) {
+ oe._pushUndo();
+ this.drawText(oe);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ text.style.display = "none";
+ text.blur();
+ }
+ }
+};
+
+Neo.TextTool.prototype.kill = function(oe) {
+ Neo.painter.hideInputText();
+};
+
+Neo.TextTool.prototype.drawText = function(oe) {
+ var text = oe.inputText;
+
+ // unescape entities
+ //var tmp = document.createElement("textarea");
+ //tmp.innerHTML = text.innerHTML;
+ //var string = tmp.value;
+
+ var string = text.textContent || text.innerText;
+
+ if (string.length <= 0) return;
+ oe.doText(this.startX, this.startY, string, text.style.fontSize);
+};
+
+Neo.TextTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+ -------------------------------------------------------------------------
+ Dummy(何もしない時)
+ -------------------------------------------------------------------------
+*/
+
+Neo.DummyTool = function() {};
+Neo.DummyTool.prototype = new Neo.ToolBase();
+Neo.DummyTool.prototype.type = Neo.Painter.TOOLTYPE_NONE;
+Neo.DummyTool.prototype.isUpMove = false;
+
+Neo.DummyTool.prototype.downHandler = function(oe) {
+};
+
+Neo.DummyTool.prototype.upHandler = function(oe) {
+ oe.popTool();
+};
+
+Neo.DummyTool.prototype.moveHandler = function(oe) {};
+Neo.DummyTool.prototype.upMoveHandler = function(oe) {}
+Neo.DummyTool.prototype.rollOverHandler= function(oe) {}
+Neo.DummyTool.prototype.rollOutHandler= function(oe) {}
+
+'use strict';
+
+Neo.CommandBase = function() {
+};
+Neo.CommandBase.prototype.data;
+Neo.CommandBase.prototype.execute = function() {}
+
+
+/*
+ ---------------------------------------------------
+ ZOOM
+ ---------------------------------------------------
+*/
+Neo.ZoomPlusCommand = function(data) {this.data = data};
+Neo.ZoomPlusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomPlusCommand.prototype.execute = function() {
+ if (this.data.zoom < 12) {
+ this.data.setZoom(this.data.zoom + 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+Neo.ZoomMinusCommand = function(data) {this.data = data};
+Neo.ZoomMinusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomMinusCommand.prototype.execute = function() {
+ if (this.data.zoom >= 2) {
+ this.data.setZoom(this.data.zoom - 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+/*
+ ---------------------------------------------------
+ UNDO
+ ---------------------------------------------------
+*/
+Neo.UndoCommand = function(data) {this.data = data};
+Neo.UndoCommand.prototype = new Neo.CommandBase();
+Neo.UndoCommand.prototype.execute = function() {
+ this.data.undo();
+};
+
+Neo.RedoCommand = function(data) {this.data = data};
+Neo.RedoCommand.prototype = new Neo.CommandBase();
+Neo.RedoCommand.prototype.execute = function() {
+ this.data.redo();
+};
+
+
+Neo.WindowCommand = function(data) {this.data = data};
+Neo.WindowCommand.prototype = new Neo.CommandBase();
+Neo.WindowCommand.prototype.execute = function() {
+ if (Neo.fullScreen) {
+ if (confirm(Neo.translate("ページビュー?"))) {
+ Neo.fullScreen = false;
+ Neo.updateWindow();
+ }
+ } else {
+ if (confirm(Neo.translate("ウィンドウビュー?"))) {
+ Neo.fullScreen = true;
+ Neo.updateWindow();
+ }
+ }
+};
+
+Neo.SubmitCommand = function(data) {this.data = data};
+Neo.SubmitCommand.prototype = new Neo.CommandBase();
+Neo.SubmitCommand.prototype.execute = function() {
+ var board = location.href.replace(/[^/]*$/, '');
+ console.log("submit: " + board);
+ this.data.submit(board);
+};
+
+Neo.CopyrightCommand = function(data) {this.data = data};
+Neo.CopyrightCommand.prototype = new Neo.CommandBase();
+Neo.CopyrightCommand.prototype.execute = function() {
+ var url = "http://github.com/funige/neo/";
+ if (confirm(Neo.translate("PaintBBS NEOは、お絵描きしぃ掲示板 PaintBBS (©2000-2004 しぃちゃん) をhtml5化するプロジェクトです。\n\nPaintBBS NEOのホームページを表示しますか?") + "\n")) {
+ Neo.openURL(url);
+ }
+};
+
+'use strict';
+
+Neo.getModifier = function(e) {
+ if (e.shiftKey) {
+ return 'shift';
+
+ } else if (e.button == 2 || e.ctrlKey || e.altKey || Neo.painter.virtualRight) {
+ return 'right';
+ }
+ return null;
+}
+
+/*
+ -------------------------------------------------------------------------
+ Button
+ -------------------------------------------------------------------------
+*/
+
+Neo.Button = function() {};
+Neo.Button.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.selected = false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+ this.element.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+
+
+ this.element.className = (!this.params.type == "fill") ? "button" : "buttonOff";
+
+ return this;
+};
+
+Neo.Button.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ if ((this.params.type == "fill") && (this.selected == false)) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this.selected) ? false : true);
+ }
+ Neo.painter.setToolByType(Neo.Painter.TOOLTYPE_FILL);
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.Button.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.Button.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.Button.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.Button.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "buttonOn";
+ } else {
+ this.element.className = "buttonOff";
+ }
+ this.selected = selected;
+};
+
+Neo.Button.prototype.update = function() {
+};
+
+/*
+ -------------------------------------------------------------------------
+ Right Button
+ -------------------------------------------------------------------------
+*/
+
+Neo.RightButton;
+
+Neo.RightButton = function() {};
+Neo.RightButton.prototype = new Neo.Button();
+
+Neo.RightButton.prototype.init = function(name, params) {
+ Neo.Button.prototype.init.call(this, name, params);
+ this.params.type = "right";
+ return this;
+}
+
+Neo.RightButton.prototype._mouseDownHandler = function(e) {
+};
+
+Neo.RightButton.prototype._mouseUpHandler = function(e) {
+ this.setSelected(!this.selected)
+};
+
+Neo.RightButton.prototype._mouseOutHandler = function(e) {
+};
+
+Neo.RightButton.prototype.setSelected = function (selected) {
+ if (selected) {
+ this.element.className = "buttonOn";
+ Neo.painter.virtualRight = true;
+ } else {
+ this.element.className = "buttonOff";
+ Neo.painter.virtualRight = false;
+ }
+ this.selected = selected;
+};
+
+Neo.RightButton.clear = function () {
+ var right = Neo.rightButton;
+ right.setSelected(false);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Fill Button
+ -------------------------------------------------------------------------
+*/
+
+Neo.FillButton;
+
+Neo.FillButton = function() {};
+Neo.FillButton.prototype = new Neo.Button();
+
+Neo.FillButton.prototype.init = function(name, params) {
+ Neo.Button.prototype.init.call(this, name, params);
+ this.params.type = "fill";
+ return this;
+}
+
+/*
+ -------------------------------------------------------------------------
+ ColorTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.colorTips = [];
+
+Neo.ColorTip = function() {};
+Neo.ColorTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.selected = (this.name == "color1") ? true : false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+ this.element.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+
+ this.element.className = "colorTipOff";
+
+ var index = parseInt(this.name.slice(5)) - 1;
+ this.element.style.left = (index % 2) ? "0px" : "26px";
+ this.element.style.top = Math.floor(index / 2) * 21 + "px";
+
+ // base64 ColorTip.png
+ this.element.innerHTML = "<img style='max-width:44px;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAASCAYAAAAg9DzcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANklEQVRIx+3OAQkAMADDsO3+Pe8qCj+0Akq6bQFqS2wTCpwE+R4IiyVYsGDBggULfirBgn8HX7BzCRwDx1QeAAAAAElFTkSuQmCC' />"
+
+ this.setColor(Neo.config.colors[params.index - 1]);
+
+ this.setSelected(this.selected);
+ Neo.colorTips.push(this);
+};
+
+Neo.ColorTip.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (this == colorTip) {
+ switch (Neo.getModifier(e)) {
+ case 'shift':
+ this.setColor(Neo.config.colors[this.params.index - 1]);
+ break;
+ case 'right':
+ this.setColor(Neo.painter.foregroundColor);
+ break;
+ }
+
+// if (e.shiftKey) {
+// this.setColor(Neo.config.colors[this.params.index - 1]);
+// } else if (e.button == 2 || e.ctrlKey || e.altKey ||
+// Neo.painter.virtualRight) {
+// this.setColor(Neo.painter.foregroundColor);
+// }
+ }
+ colorTip.setSelected(this == colorTip) ? true : false;
+ }
+ Neo.painter.setColor(this.color);
+ Neo.updateUIColor(true, false);
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.ColorTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ColorTip.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "colorTipOn";
+ } else {
+ this.element.className = "colorTipOff";
+ }
+ this.selected = selected;
+};
+
+Neo.ColorTip.prototype.setColor = function(color) {
+ this.color = color;
+ this.element.style.backgroundColor = color;
+};
+
+Neo.ColorTip.getCurrent = function() {
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (colorTip.selected) return colorTip;
+ }
+ return null;
+};
+
+/*
+ -------------------------------------------------------------------------
+ ToolTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.toolTips = [];
+Neo.toolButtons = [];
+
+Neo.ToolTip = function() {};
+
+Neo.ToolTip.prototype.prevMode = -1;
+
+Neo.ToolTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.params.type = this.element.id;
+ this.name = name;
+ this.mode = 0;
+
+ this.isMouseDown = false;
+
+ var ref = this;
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+ this.element.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+
+ this.selected = (this.params.type == "pen") ? true : false;
+ this.setSelected(this.selected);
+
+ this.element.innerHTML = "<canvas width=46 height=18></canvas><div class='label'></div>";
+ this.canvas = this.element.getElementsByTagName('canvas')[0];
+ this.label = this.element.getElementsByTagName('div')[0];
+
+ this.update();
+ return this;
+};
+
+Neo.ToolTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (this.isTool) {
+ if (this.selected == false) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this == toolTip) ? true : false);
+ }
+
+ } else {
+ var length = this.toolStrings.length;
+ if (Neo.getModifier(e) == "right") {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ }
+ Neo.painter.setToolByType(this.tools[this.mode]);
+ this.update();
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.ToolTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+
+Neo.ToolTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ToolTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ToolTip.prototype.setSelected = function(selected) {
+ if (this.fixed) {
+ this.element.className = "toolTipFixed";
+
+ } else {
+ if (selected) {
+ this.element.className = "toolTipOn";
+ } else {
+ this.element.className = "toolTipOff";
+ }
+ }
+ this.selected = selected;
+};
+
+Neo.ToolTip.prototype.update = function() {};
+
+Neo.ToolTip.prototype.draw = function(c) {
+ if (this.hasTintImage) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+ var ctx = this.canvas.getContext("2d");
+
+ if (this.prevMode != this.mode) {
+ this.prevMode = this.mode;
+
+ var img = new Image();
+ img.src = this.toolIcons[this.mode];
+ img.onload = function() {
+ var ref = this;
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ this.drawTintImage(ctx, img, c, 0, 0);
+ }.bind(this);
+
+ } else {
+ this.tintImage(ctx, c);
+ }
+ }
+};
+
+Neo.ToolTip.prototype.drawTintImage = function(ctx, img, c, x, y) {
+ ctx.drawImage(img, x, y);
+ this.tintImage(ctx, c);
+};
+
+Neo.ToolTip.prototype.tintImage = function(ctx, c) {
+ c = (Neo.painter.getColor(c) & 0xffffff);
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ for (var i = 0; i < buf32.length; i++) {
+ var a = buf32[i] & 0xff000000;
+ if (a) {
+ buf32[i] = buf32[i] & a | c;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+};
+
+Neo.ToolTip.bezier = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAT0lEQVRIx+3SQQoAIAhE0en+h7ZVEEKBZrX5b5sjKknAkRYpNslaMLPq44ZI9wwHs0vMQ/v87u0Kk8xfsaI242jbMdjPi5Y0r/zTAAAAD3UOjRf9jcO4sgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blur = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAASUlEQVRIx+3VMQ4AIAgEQeD/f8bWWBnJYUh2SgtgK82G8/MhzVKwxOtTLgIUx6tDout4laiPIICA0Qj4bXxAy0+8LZP9yACAJwsqkggS55eiZgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blurrect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAX0lEQVRIx+2XQQ4AEAwEt+I7/v+8Org6lJKt6NzLjjYE8DAKtLpYoDeCCCC7tYUd3ru2qQOzDTyndhJzB6KSAmxSgM0fAlGuzBnmlziqxB8jFJkUYJMCbAQYPxt2kF06fvYKgjPBO/IAAAAASUVORK5CYII=";
+Neo.ToolTip.brush = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQUlEQVRIx2NgGOKAEcb4z8CweRA4xpdUPSxofJ8BdP8WcjQxDaCDqQLQY4CsUBgFo2AUjIJRMApGwSgYBaNgZAIA0CoDwDbZu8oAAAAASUVORK5CYII=";
+Neo.ToolTip.burn = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAPklEQVRIx+3PMRIAMAQAQbzM0/0sKZPeiDG57TQ4keH0Htx9VR+MCM1vOezl8xUsv4IAAkYjoBsB3QgAgL9tYXgF19rh9yoAAAAASUVORK5CYII=";
+Neo.ToolTip.copy = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XMQoAIAwDU/E7/v95Orh2KMUSC7m5Qs6AUqAxG1gzOLirwxhgmXOjOlg1oQY8sjf2mvYNSICNBNhIgE3oH/jlzfdo34AE2EiATXsBA+5mww6S5QASDwSGMt8ouwAAAABJRU5ErkJggg==";
+Neo.ToolTip.copy2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAN0lEQVRIx+3PwQkAIBADwdPKt3MtQVCOPNz5B7JV0pNxOwRW9zng+G92n+hmQJoBaQakGSBJf9tyBgQUV/fKCAAAAABJRU5ErkJggg==";
+Neo.ToolTip.ellipse = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAATklEQVRIx+2VMQ4AIAgD6/8fjbOJi1LFmt4OPQ0KIE7LNgggCBLbHkuFM9lM+Om+QwDjpksyb4tT86vlvzgEbYxefQPyv5D8HjDGGGOk6b3jJ+lYubd8AAAAAElFTkSuQmCC";
+Neo.ToolTip.ellipsefill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAVUlEQVRIx+2VURIAEAgFc/9D5waSHpV5+43ZHRMizRnRA1REARLHHq6NCFl01Nail+LeEDMgU34nYhlQQd6K+PsGKkSEZyArBPoK3Y6K/AOEEEJIayZHbhIKjkZrFwAAAABJRU5ErkJggg==";
+Neo.ToolTip.eraser = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAABQElEQVRIx+1WQY7CMAwcI37Cad+yXOgH4Gu8gAt9CtrDirfMHjZJbbcktVSpQnROSeMkY3vsFHhzSG3xfLpz/JVmG0mIqDkIMcc6+7Kejx6fdb0dq7w09rVFkrjejrMOunQ9vg7f/5QEIAd6E1Eo38WF8fF7n8sdALCrLerIzoFI4sI0Vtv1SYZ8CVbeF7tzF7JugIkVkxOauc6CIe8842S+XmMfsq7TN9LRTngZmTmVD4SrnzYaGYhFoxCWgajXuMjYGTuJ3dlwIBIN3U0cUVqLXCs5E7YeVsvAYJul5HWeLUhL3EpstQwooqoOTEHDOebpMn7ngkUsg3RotU8X1MkuVDrYohkIupC0YArX6T+PfX3kcbQLNV/iCKi6EB3xqXdAZ0JKthZ8B0QEl673NIEX/0I/z36Rf6ENGzZ8EP4A8Lp+9e9VWC4AAAAASUVORK5CYII=";
+Neo.ToolTip.flip = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAZklEQVRIx+2XQQoAIAgE1+g7/f95degWHSyTTXDOhTsSiUBgOtCq8mD3DiOA3NxTCVgKaLA0qHiFOsHSnC8ELKQAmxRgE15APQfWv9pzLjwX+CXsjvBPKAXYpACb8AICzM2GHeSWAfVOCIiJuQ9tAAAAAElFTkSuQmCC";
+Neo.ToolTip.freehand = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAdUlEQVRIx+2WUQrAMAhD3dj9r+y+VoSyLhYDynzQv1qiJlCR4hzeAhVRsiC3Jkj0c5hN7Lx7IQ9SphLE1ICdwko420purEWQuywN3pqxgcw2+WwAtU1GzoqiLZNwZBvMAIcO8y3YKUO8mkbmjPzjK9E0TUPjBoeyLAS0usjLAAAAAElFTkSuQmCC";
+Neo.ToolTip.line = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAU0lEQVRIx+2UQQ4AIAjD8P+PxivRGDQC47C+oN1hIgTLQAt4qIga2c23XYAVPkm3CVhlb4ShAa/rQgMi1i0NyFg3LaBq3bAA1LpfAd7/EkIIIR2YXFYSCpWS8w8AAAAASUVORK5CYII=";
+Neo.ToolTip.merge = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XQQrAQAgDx9Lv9JF9+e6h54IINlgyZ4UMOYgwmAXXmRxc3WECorJ3dAfrJtXAC7c6PPygAQuosYAaC6hJ3YHqlfyC8Q1YQI0F1IwXCHg+G3WQKhvwgwUFmFyYbwAAAABJRU5ErkJggg==";
+Neo.ToolTip.pen = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAK0lEQVRIx+3OsQkAMAwDQXn/oe3WfSAEctd9I5TA32pHJ/3AoTpfAQCAGwaa5AICJLKWSQAAAABJRU5ErkJggg==";
+Neo.ToolTip.rect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQElEQVRIx+3TMQ4AIAhD0WK8/5VxdcIYY8rw3wok7YAEr6iGKaU74BY0ro+6FKhyDHe4VxRwm6eFLn8AAADwwQIwTQgGo9ZMywAAAABJRU5ErkJggg==";
+Neo.ToolTip.rectfill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANElEQVRIx+3PIQ4AIBADwcL//3xYBMEgLiQztmab0GvcxkqqO3ALPbbO7rBXDnRzAADgYwvqDwIMJlGb5QAAAABJRU5ErkJggg==";
+Neo.ToolTip.text = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAcUlEQVRIx+2VwQ7AIAhDy7L//2V2WmIYg+ky2KEv8aCCqYQqQMgrJNpUQMXEKKDmAPHyspgSrBBvLZu3cQqZEdwhfusq0KdkVR5HlFfBvpI0mtIzeusFot7vFPqYuzZYMXUFlzc+qrIn7tf/ACGEkIwDlEQ94YZjzcgAAAAASUVORK5CYII=";
+Neo.ToolTip.tone = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAO0lEQVRIx+3PIQ4AMAgEwaP//zNVVZUELiQ7CgWstFy8IaVsPhT1Lb/T+fQEAtwIcCPAjQC39QEAgJIL6DQCFhAqsRkAAAAASUVORK5CYII=";
+
+/*
+ -------------------------------------------------------------------------
+ PenTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.penTip;
+
+Neo.PenTip = function() {};
+Neo.PenTip.prototype = new Neo.ToolTip();
+
+Neo.PenTip.prototype.tools = [Neo.Painter.TOOLTYPE_PEN,
+ Neo.Painter.TOOLTYPE_BRUSH,
+ Neo.Painter.TOOLTYPE_TEXT];
+
+Neo.PenTip.prototype.hasTintImage = true;
+Neo.PenTip.prototype.toolIcons = [Neo.ToolTip.pen,
+ Neo.ToolTip.brush,
+ Neo.ToolTip.text];
+
+Neo.PenTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("鉛筆"),
+ Neo.translate("水彩"),
+ Neo.translate("テキスト")];
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.PenTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ if (this.label) {
+ this.label.innerHTML = this.toolStrings[this.mode];
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Pen2Tip
+ -------------------------------------------------------------------------
+*/
+
+Neo.pen2Tip;
+
+Neo.Pen2Tip = function() {};
+Neo.Pen2Tip.prototype = new Neo.ToolTip();
+
+Neo.Pen2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_TONE,
+ Neo.Painter.TOOLTYPE_BLUR,
+ Neo.Painter.TOOLTYPE_DODGE,
+ Neo.Painter.TOOLTYPE_BURN];
+
+Neo.Pen2Tip.prototype.hasTintImage = true;
+Neo.Pen2Tip.prototype.toolIcons = [Neo.ToolTip.tone,
+ Neo.ToolTip.blur,
+ Neo.ToolTip.burn,
+ Neo.ToolTip.burn];
+
+Neo.Pen2Tip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("トーン"),
+ Neo.translate("ぼかし"),
+ Neo.translate("覆い焼き"),
+ Neo.translate("焼き込み")];
+
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.Pen2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ switch (this.tools[this.mode]) {
+ case Neo.Painter.TOOLTYPE_TONE:
+ this.drawTone(Neo.painter.foregroundColor);
+ break;
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ this.draw(0xffc0c0c0);
+ break;
+
+ case Neo.Painter.TOOLTYPE_BURN:
+ this.draw(0xff404040);
+ break;
+
+ default:
+ this.draw(Neo.painter.foregroundColor);
+ break;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.Pen2Tip.prototype.drawTone = function() {
+ var ctx = this.canvas.getContext("2d");
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var c = Neo.painter.getColor() | 0xff000000;
+ var a = Math.floor(Neo.painter.alpha * 255);
+ var toneData = Neo.painter.getToneData(a);
+
+ for (var j = 0; j < 18; j++) {
+ for (var i = 0; i < 46; i++) {
+ if (j >= 1 && j < 12 &&
+ i >= 2 && i < 26 &&
+ toneData[(i%4) + (j%4) * 4]) {
+ buf32[j * 46 + i] = c;
+
+ } else {
+ buf32[j * 46 + i] = 0;
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ this.prevMode = this.mode;
+};
+
+
+/*
+ -------------------------------------------------------------------------
+ EraserTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.eraserTip;
+
+Neo.EraserTip = function() {};
+Neo.EraserTip.prototype = new Neo.ToolTip();
+
+Neo.EraserTip.prototype.tools = [Neo.Painter.TOOLTYPE_ERASER,
+ Neo.Painter.TOOLTYPE_ERASERECT,
+ Neo.Painter.TOOLTYPE_ERASEALL];
+
+Neo.EraserTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("消しペン"),
+ Neo.translate("消し四角"),
+ Neo.translate("全消し")];
+
+ this.drawOnce = false;
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EraserTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ if (this.drawOnce == false) {
+ this.draw();
+ this.drawOnce = true;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.EraserTip.prototype.draw = function() {
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ var img = new Image();
+
+ img.src = Neo.ToolTip.eraser;
+ img.onload = function() {
+ ctx.drawImage(img, 0, 0);
+ };
+};
+
+/*
+ -------------------------------------------------------------------------
+ EffectTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.effectTip;
+
+Neo.EffectTip = function() {};
+Neo.EffectTip.prototype = new Neo.ToolTip();
+
+Neo.EffectTip.prototype.tools = [Neo.Painter.TOOLTYPE_RECTFILL,
+ Neo.Painter.TOOLTYPE_RECT,
+ Neo.Painter.TOOLTYPE_ELLIPSEFILL,
+ Neo.Painter.TOOLTYPE_ELLIPSE];
+
+Neo.EffectTip.prototype.hasTintImage = true;
+Neo.EffectTip.prototype.toolIcons = [Neo.ToolTip.rectfill,
+ Neo.ToolTip.rect,
+ Neo.ToolTip.ellipsefill,
+ Neo.ToolTip.ellipse];
+
+Neo.EffectTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("四角"),
+ Neo.translate("線四角"),
+ Neo.translate("楕円"),
+ Neo.translate("線楕円")];
+
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EffectTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+ -------------------------------------------------------------------------
+ Effect2Tip
+ -------------------------------------------------------------------------
+*/
+
+Neo.effect2Tip;
+
+Neo.Effect2Tip = function() {};
+Neo.Effect2Tip.prototype = new Neo.ToolTip();
+
+Neo.Effect2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_COPY,
+ Neo.Painter.TOOLTYPE_MERGE,
+ Neo.Painter.TOOLTYPE_BLURRECT,
+ Neo.Painter.TOOLTYPE_FLIP_H,
+ Neo.Painter.TOOLTYPE_FLIP_V,
+ Neo.Painter.TOOLTYPE_TURN];
+
+Neo.Effect2Tip.prototype.hasTintImage = true;
+Neo.Effect2Tip.prototype.toolIcons = [Neo.ToolTip.copy,
+ Neo.ToolTip.merge,
+ Neo.ToolTip.blurrect,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip];
+
+Neo.Effect2Tip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("コピー"),
+ Neo.translate("レイヤ結合"),
+ Neo.translate("角取り"),
+ Neo.translate("左右反転"),
+ Neo.translate("上下反転"),
+ Neo.translate("傾け")];
+
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+
+ this.img = document.createElement("img");
+ this.img.src = Neo.ToolTip.copy2;
+ this.element.appendChild(this.img);
+ return this;
+};
+
+Neo.Effect2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+ -------------------------------------------------------------------------
+ MaskTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.maskTip;
+
+Neo.MaskTip = function() {};
+Neo.MaskTip.prototype = new Neo.ToolTip();
+
+Neo.MaskTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("通常"),
+ Neo.translate("マスク"),
+ Neo.translate("逆マスク"),
+ Neo.translate("加算"),
+ Neo.translate("逆加算")];
+
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.MaskTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (Neo.getModifier(e) == "right") {
+ Neo.painter.maskColor = Neo.painter.foregroundColor;
+
+ } else {
+ var length = this.toolStrings.length;
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ Neo.painter.maskType = this.mode;
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.MaskTip.prototype.update = function() {
+ this.draw(Neo.painter.maskColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.MaskTip.prototype.draw = function(c) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ ctx.fillStyle = c;
+ ctx.fillRect(1, 1, 43, 9);
+};
+
+/*
+ -------------------------------------------------------------------------
+ DrawTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.drawTip;
+
+Neo.DrawTip = function() {};
+Neo.DrawTip.prototype = new Neo.ToolTip();
+
+Neo.DrawTip.prototype.hasTintImage = true;
+Neo.DrawTip.prototype.toolIcons = [Neo.ToolTip.freehand,
+ Neo.ToolTip.line,
+ Neo.ToolTip.bezier];
+
+Neo.DrawTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("手書き"),
+ Neo.translate("直線"),
+ Neo.translate("BZ曲線")];
+
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.DrawTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ var length = this.toolStrings.length;
+
+ if (Neo.getModifier(e) == "right") {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ Neo.painter.drawType = this.mode;
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.DrawTip.prototype.update = function() {
+ this.mode = Neo.painter.drawType;
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+ -------------------------------------------------------------------------
+ ColorSlider
+ -------------------------------------------------------------------------
+*/
+
+Neo.sliders = [];
+
+Neo.ColorSlider = function() {};
+
+Neo.ColorSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = 0;
+ this.type = this.params.type;
+
+ this.element.className = "colorSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>";
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED:
+ this.prefix = "R";
+ this.slider.style.backgroundColor = "#fa9696";
+ break;
+ case Neo.SLIDERTYPE_GREEN:
+ this.prefix = "G";
+ this.slider.style.backgroundColor = "#82f238";
+ break;
+ case Neo.SLIDERTYPE_BLUE:
+ this.prefix = "B";
+ this.slider.style.backgroundColor = "#8080ff";
+ break;
+ case Neo.SLIDERTYPE_ALPHA:
+ this.prefix = "A";
+ this.slider.style.backgroundColor = "#aaaaaa";
+ this.value = 255;
+ break;
+ }
+
+ this.update();
+ return this;
+};
+
+Neo.ColorSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.slide(x, y);
+ }
+};
+
+Neo.ColorSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+ //event.preventDefault();
+};
+
+Neo.ColorSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.ColorSlider.prototype.shift = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+
+ value = Math.max(Math.min(v, 255), min);
+ if (this.value > value || this.value == 255) {
+ this.value--;
+ } else {
+ this.value++;
+ }
+ this.value = Math.max(Math.min(this.value, 255), min);
+ this.value0 = this.value;
+ this.x0 = x;
+ }
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+
+ Neo.painter.setColor(r<<16 | g<<8 | b);
+ Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.slide = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ value = Math.round(v / 5) * 5;
+
+ this.value0 = value;
+ this.x0 = x;
+
+ } else {
+ var d = (x - this.x0) / 3.0;
+ value = this.value0 + d;
+ }
+
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+ this.value = Math.max(Math.min(value, 255), min);
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+ var color = (r<<16 | g<<8 | b);
+
+ var colorTip = Neo.ColorTip.getCurrent()
+ if (colorTip) {
+ colorTip.setColor(Neo.painter.getColorString(color))
+ }
+
+ Neo.painter.setColor(color);
+ // Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.update = function() {
+ var color = Neo.painter.getColor();
+ var alpha = Neo.painter.alpha * 255;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED: this.value = (color & 0x0000ff); break;
+ case Neo.SLIDERTYPE_GREEN: this.value = (color & 0x00ff00) >> 8; break;
+ case Neo.SLIDERTYPE_BLUE: this.value = (color & 0xff0000) >> 16; break;
+ case Neo.SLIDERTYPE_ALPHA: this.value = alpha; break;
+ }
+
+ var width = this.value * 49.0 / 255.0;
+ width = Math.max(Math.min(48, width), 1);
+
+ this.slider.style.width = width.toFixed(2) + "px";
+ this.label.innerHTML = this.prefix + this.value.toFixed(0);
+};
+
+/*
+ -------------------------------------------------------------------------
+ SizeSlider
+ -------------------------------------------------------------------------
+*/
+
+Neo.SizeSlider = function() {};
+
+Neo.SizeSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = this.value0 = 1;
+
+ this.element.className = "sizeSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>"
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+ this.update();
+ return this;
+};
+
+Neo.SizeSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.value0 = this.value;
+ this.y0 = y;
+ this.slide(x, y);
+ }
+};
+
+Neo.SizeSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+ //event.preventDefault();
+};
+
+Neo.SizeSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.SizeSlider.prototype.shift = function(x, y) {
+ var value0 = Neo.painter.lineWidth;
+ var value;
+
+ if (!Neo.painter.tool.alt) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+
+ value = Math.max(Math.min(v, 30), 1);
+ if (value0 > value || value0 == 30) {
+ value0--;
+ } else {
+ value0++;
+ }
+ this.setSize(value0);
+ }
+};
+
+Neo.SizeSlider.prototype.slide = function(x, y) {
+ var value;
+ if (!Neo.painter.tool.alt) {
+ if (x >= 0 && x < 48 && y >= 0 && y < 41) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+ value = v;
+
+ this.value0 = value;
+ this.y0 = y;
+
+ } else {
+ var d = (y - this.y0) / 7.0;
+ value = this.value0 + d;
+ }
+ } else {
+ // Ctrl+Alt+ドラッグでサイズ変更するとき
+ var d = y - this.y0;
+ value = this.value0 + d;
+ }
+
+ value = Math.max(Math.min(value, 30), 1);
+ this.setSize(value);
+};
+
+Neo.SizeSlider.prototype.setSize = function(value) {
+ value = Math.round(value);
+ Neo.painter.lineWidth = Math.max(Math.min(30, value), 1);
+
+ var tool = Neo.painter.getCurrentTool();
+ if (tool) {
+ if (tool.type == Neo.Painter.TOOLTYPE_BRUSH) {
+ Neo.painter.alpha = tool.getAlpha();
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA].update();
+
+ } else if (tool.type == Neo.Painter.TOOLTYPE_TEXT) {
+ Neo.painter.updateInputText();
+ }
+ }
+ this.update();
+};
+
+Neo.SizeSlider.prototype.update = function() {
+ this.value = Neo.painter.lineWidth;
+
+ var height = this.value * 33.0 / 30.0;
+ height = Math.max(Math.min(34, height), 1);
+
+ this.slider.style.height = height.toFixed(2) + "px";
+ this.label.innerHTML = this.value + "px";
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+};
+
+/*
+ -------------------------------------------------------------------------
+ LayerControl
+ -------------------------------------------------------------------------
+*/
+
+Neo.LayerControl = function() {};
+Neo.LayerControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+
+ var ref = this;
+
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+
+ this.element.className = "layerControl";
+
+ var layerStrings = [Neo.translate("Layer0"),
+ Neo.translate("Layer1")];
+
+ this.element.innerHTML =
+ "<div class='bg'></div><div class='label0'>" + layerStrings[0] +
+ "</div><div class='label1'>" + layerStrings[1] +
+ "</div><div class='line1'></div><div class='line0'></div>";
+
+ this.bg = this.element.getElementsByClassName('bg')[0];
+ this.label0 = this.element.getElementsByClassName('label0')[0];
+ this.label1 = this.element.getElementsByClassName('label1')[0];
+ this.line0 = this.element.getElementsByClassName('line0')[0];
+ this.line1 = this.element.getElementsByClassName('line1')[0];
+
+ this.line0.style.display = "none";
+ this.line1.style.display = "none";
+ this.label1.style.display = "none";
+
+ this.update();
+ return this;
+};
+
+Neo.LayerControl.prototype._mouseDownHandler = function(e) {
+ if (Neo.getModifier(e) == "right") {
+ var visible = Neo.painter.visible[Neo.painter.current];
+ Neo.painter.visible[Neo.painter.current] = (visible) ? false : true;
+
+ } else {
+ var current = Neo.painter.current;
+ Neo.painter.current = (current) ? 0 : 1
+ }
+ Neo.painter.updateDestCanvas(0, 0, Neo.painter.canvasWidth, Neo.painter.canvasHeight);
+ if (Neo.painter.tool.type == Neo.Painter.TOOLTYPE_PASTE) {
+ Neo.painter.tool.drawCursor(Neo.painter);
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.LayerControl.prototype.update = function() {
+ this.label0.style.display = (Neo.painter.current == 0) ? "block" : "none";
+ this.label1.style.display = (Neo.painter.current == 1) ? "block" : "none";
+ this.line0.style.display = (Neo.painter.visible[0]) ? "none" : "block";
+ this.line1.style.display = (Neo.painter.visible[1]) ? "none" : "block";
+};
+
+/*
+ -------------------------------------------------------------------------
+ ReserveControl
+ -------------------------------------------------------------------------
+*/
+Neo.reserveControls = [];
+
+Neo.ReserveControl = function() {};
+Neo.ReserveControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ var ref = this;
+
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+
+ this.element.className = "reserve";
+
+ var index = parseInt(this.name.slice(7)) - 1;
+ this.element.style.top = "1px";
+ this.element.style.left = (index * 15 + 2) + "px";
+
+ this.reserve = Neo.clone(Neo.config.reserves[index]);
+ this.update();
+
+ Neo.reserveControls.push(this);
+ return this;
+};
+
+Neo.ReserveControl.prototype._mouseDownHandler = function(e) {
+ if (Neo.getModifier(e) == 'right') {
+ this.save();
+ } else {
+ this.load();
+ }
+ this.update();
+};
+
+Neo.ReserveControl.prototype.load = function() {
+ Neo.painter.setToolByType(this.reserve.tool)
+ Neo.painter.foregroundColor = this.reserve.color;
+ Neo.painter.lineWidth = this.reserve.size;
+ Neo.painter.alpha = this.reserve.alpha;
+
+ switch (this.reserve.tool) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ Neo.painter.drawType = this.reserve.drawType;
+ };
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.save = function() {
+ this.reserve.color = Neo.painter.foregroundColor;
+ this.reserve.size = Neo.painter.lineWidth;
+ this.reserve.drawType = Neo.painter.drawType;
+ this.reserve.alpha = Neo.painter.alpha;
+ this.reserve.tool = Neo.painter.tool.getType();
+ this.element.style.backgroundColor = this.reserve.color;
+ this.update();
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.update = function() {
+ this.element.style.backgroundColor = this.reserve.color;
+};
+
+/*
+ -------------------------------------------------------------------------
+ ScrollBarButton
+ -------------------------------------------------------------------------
+*/
+
+Neo.scrollH;
+Neo.scrollV;
+
+Neo.ScrollBarButton = function() {};
+Neo.ScrollBarButton.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.element.innerHTML = "<div></div>";
+ this.barButton = this.element.getElementsByTagName("div")[0];
+ this.element['data-bar'] = true;
+ this.barButton['data-bar'] = true;
+
+ if (name == "scrollH") Neo.scrollH = this;
+ if (name == "scrollV") Neo.scrollV = this;
+ return this;
+};
+
+Neo.ScrollBarButton.prototype.update = function(oe) {
+ if (this.name == "scrollH") {
+ var a = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var barWidth = Math.ceil(oe.destCanvas.width * a);
+ var barX = (oe.scrollBarX) * (oe.destCanvas.width - barWidth);
+ this.barButton.style.width = (Math.ceil(barWidth) - 4) + "px";
+ this.barButton.style.left = Math.floor(barX) + "px";
+
+ } else {
+ var a = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barHeight = Math.ceil(oe.destCanvas.height * a);
+ var barY = (oe.scrollBarY) * (oe.destCanvas.height - barHeight);
+ this.barButton.style.height = (Math.ceil(barHeight) - 4) + "px";
+ this.barButton.style.top = Math.floor(barY) + "px";
+ }
+};
+