aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar neptune 2022-11-25 17:59:09 -0300
committerLibravatar neptune 2022-11-25 17:59:09 -0300
commitb09e855283b8521caa35e1aa0762cf8e986559d4 (patch)
tree2d1459eba210e2f7415b00d450fbc7cce700ff2f
parent0889034f67f8d8cadc98dcbefcd7021b42a00408 (diff)
downloadweabot-b09e855283b8521caa35e1aa0762cf8e986559d4.tar.gz
weabot-b09e855283b8521caa35e1aa0762cf8e986559d4.tar.xz
weabot-b09e855283b8521caa35e1aa0762cf8e986559d4.zip
Actualizado repo
-rw-r--r--cgi/formatting.py54
-rw-r--r--cgi/framework.py10
-rw-r--r--cgi/manage.py90
-rw-r--r--cgi/oekaki.py2
-rw-r--r--cgi/post.py88
-rw-r--r--cgi/templates/board.html6
-rw-r--r--cgi/templates/board.jp.html6
-rw-r--r--cgi/templates/home.html2
-rw-r--r--cgi/templates/mobile/board.html12
-rw-r--r--cgi/templates/mobile/txt_thread.html2
-rw-r--r--cgi/templates/paint.html8
-rwxr-xr-xcgi/weabot.py51
-rw-r--r--static/js/paintbbs/PaintBBS-1.5.15.css655
-rw-r--r--static/js/paintbbs/PaintBBS-1.5.15.js9111
-rw-r--r--static/js/shobon.js3
15 files changed, 9948 insertions, 152 deletions
diff --git a/cgi/formatting.py b/cgi/formatting.py
index 97f44a6..33495a3 100644
--- a/cgi/formatting.py
+++ b/cgi/formatting.py
@@ -317,12 +317,23 @@ def close_html(message):
"""
Old retarded version of sanitize_html, it just closes open tags.
"""
- import BeautifulSoup
+ #import BeautifulSoup
- message = message.encode('utf-8')
- soup = BeautifulSoup.BeautifulSoup(message)
+ #message = message.encode('utf-8')
+ #soup = BeautifulSoup.BeautifulSoup(message)
+
+ #return str(soup).replace('
', '').encode('utf-8')
- return str(soup).replace('
', '').encode('utf-8')
+ try:
+ l = message.rindex('<')
+ except ValueError:
+ return message
+ test = message[l:]
+ try:
+ r = test.rindex('>')
+ return message
+ except ValueError:
+ return message[:l]
def sanitize_html(message, decode=True):
@@ -375,27 +386,26 @@ def checkWordfilters(message, ip, board):
if wordfilter["boards"]:
boards = str2boards(wordfilter["boards"])
if not wordfilter["boards"] or board in boards:
- if wordfilter['action'] == '0':
+ if wordfilter['action'] == 0:
if not re.search(wordfilter['from'], message, re.DOTALL | re.IGNORECASE) is None:
raise UserError(wordfilter['reason'])
- elif wordfilter['action'] == '1':
+ elif wordfilter['action'] == 1:
message = re.compile(wordfilter['from'], re.DOTALL | re.IGNORECASE).sub(
wordfilter['to'], message)
- elif wordfilter['action'] == '2':
+ elif wordfilter['action'] == 2:
# Ban
if not re.search(wordfilter['from'], message, re.DOTALL | re.IGNORECASE) is None:
- if wordfilter['seconds'] != '0':
- until = str(timestamp() + int(wordfilter['seconds']))
+ if wordfilter['seconds']:
+ until = timestamp() + int(wordfilter['seconds'])
else:
- until = '0'
+ until = 0
- InsertDb("INSERT INTO `bans` (`ip`, `boards`, `added`, `until`, `staff`, `reason`, `note`, `blind`) VALUES (" +
- "INET6_ATON('" + str(ip) + "'), '" + _mysql.escape_string(wordfilter['boards']) +
- "', " + str(timestamp()) + ", " + until + ", 'System', '" + _mysql.escape_string(wordfilter['reason']) +
- "', 'Word Auto-ban', '"+_mysql.escape_string(wordfilter['blind'])+"')")
+ sql_query = "INSERT INTO `bans` (`ipstart`, `ipend`, `ipstr`, `boards`, `added`, `until`, `staff`, `reason`, `note`, `blind`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
+ sql_params = (ip, ip, ip, wordfilter['boards'], timestamp(), until, "System", wordfilter['reason'], "Filter auto-ban", wordfilter['blind'])
+ InsertDb(sql_query, sql_params)
regenerateAccess()
raise UserError(wordfilter['reason'])
- elif wordfilter['action'] == '3':
+ elif wordfilter['action'] == 3:
if not re.search(wordfilter['from'], message, re.DOTALL | re.IGNORECASE) is None:
raise UserError('<meta http-equiv="refresh" content="%s;url=%s" />%s' % (wordfilter['redirect_time'], wordfilter['redirect_url'], wordfilter['reason']))
return message
@@ -426,18 +436,18 @@ def checkNamefilters(name, tripcode, ip, board):
if match:
# do action
- if namefilter['action'] == '0':
+ if namefilter['action'] == 0:
raise UserError(namefilter['reason'])
- elif namefilter['action'] == '1':
+ elif namefilter['action'] == 1:
name = namefilter['to']
tripcode = ''
return name, tripcode
- elif namefilter['action'] == '2':
+ elif namefilter['action'] == 2:
# Ban
- if namefilter['seconds'] != '0':
- until = str(timestamp() + int(namefilter['seconds']))
+ if namefilter['seconds']:
+ until = timestamp() + int(namefilter['seconds'])
else:
- until = '0'
+ until = 0
InsertDb("INSERT INTO `bans` (`ip`, `boards`, `added`, `until`, `staff`, `reason`, `note`, `blind`) VALUES (" +
"'" + _mysql.escape_string(ip) + "', '" + _mysql.escape_string(namefilter['boards']) +
@@ -445,6 +455,6 @@ def checkNamefilters(name, tripcode, ip, board):
"', 'Name Auto-ban', '"+_mysql.escape_string(namefilter['blind'])+"')")
regenerateAccess()
raise UserError(namefilter['reason'])
- elif namefilter['action'] == '3':
+ elif namefilter['action'] == 3:
raise UserError('<meta http-equiv="refresh" content="%s;url=%s" />%s' % (namefilter['redirect_time'], namefilter['redirect_url'], namefilter['reason']))
return name, tripcode
diff --git a/cgi/framework.py b/cgi/framework.py
index 38ba2ad..1a2d78e 100644
--- a/cgi/framework.py
+++ b/cgi/framework.py
@@ -128,6 +128,16 @@ def getCountry(ip):
return "??"
+def clearCache():
+ if Settings._.CONN:
+ Settings._.CONN.close()
+ Settings._.CONN = None
+
+ Settings._.BOARD = None
+ Settings._.IS_TOR = None
+ Settings._.HOST = None
+
+
def getHost(ip):
if Settings._.HOST is None:
try:
diff --git a/cgi/manage.py b/cgi/manage.py
index 02eaf41..93a9921 100644
--- a/cgi/manage.py
+++ b/cgi/manage.py
@@ -274,23 +274,18 @@ def manage(self, path_split):
if not moderator:
return
- try:
- action_taken = True
- member = FetchOne(
- 'SELECT `username` FROM `staff` WHERE `id` = ' + _mysql.escape_string(path_split[4]) + ' LIMIT 1')
- if member:
- UpdateDb('DELETE FROM `staff` WHERE `id` = ' +
- _mysql.escape_string(path_split[4]) + ' LIMIT 1')
- message = 'Staff member deleted.'
- template_filename = "message.html"
- logAction(staff_account['username'], _(
- 'Deleted staff account for %s') % member['username'])
- else:
- message = _(
- 'Unable to locate a staff account with that ID.')
- template_filename = "message.html"
- except:
- pass
+ action_taken = True
+ member = FetchOne('SELECT `username` FROM `staff` WHERE `id` = %s LIMIT 1', (path_split[4],))
+ if member:
+ UpdateDb('DELETE FROM `staff` WHERE `id` = %s LIMIT 1', (path_split[4],))
+ message = 'Staff member deleted.'
+ template_filename = "message.html"
+ logAction(staff_account['username'], _(
+ 'Deleted staff account for %s') % member['username'])
+ else:
+ message = _(
+ 'Unable to locate a staff account with that ID.')
+ template_filename = "message.html"
if not action_taken:
staff = FetchAll('SELECT * FROM `staff` ORDER BY `rights`')
@@ -353,7 +348,7 @@ def manage(self, path_split):
if imageonly:
message = 'Archivo de post /%s/%s eliminado.' % (
board['dir'], post['id'])
- elif permanently or post["parentid"] == '0':
+ elif permanently or post["parentid"] == 0:
message = 'Post /%s/%s eliminado permanentemente.' % (
board['dir'], post['id'])
else:
@@ -384,7 +379,7 @@ def manage(self, path_split):
message = _('Post is not a thread opener.')
template_filename = "message.html"
else:
- if not post['locked']:
+ if post['locked'] == 0:
# Cerrar si esta abierto
setLocked = 1
else:
@@ -392,7 +387,7 @@ def manage(self, path_split):
setLocked = 0
UpdateDb("UPDATE `posts` SET `locked` = %s WHERE `boardid` = %s AND `id` = %s LIMIT 1",
- (setLocked, board["id"], postid))
+ (setLocked, board["id"], post["id"]))
threadUpdated(postid)
if setLocked == 1:
message = _('Thread successfully closed.')
@@ -732,7 +727,7 @@ def manage(self, path_split):
else:
message = _('Ban successfully placed.')
action = 'Banned ' + ip
- if until != '0':
+ if until != 0:
action += ' until ' + \
formatTimestamp(until)
else:
@@ -997,16 +992,16 @@ def manage(self, path_split):
if path_split[4] == 'restore':
board = setBoard(path_split[5])
- post = FetchOne('SELECT `parentid` FROM `posts` WHERE `boardid` = ' +
- board['id'] + ' AND `id` = \'' + _mysql.escape_string(path_split[6]) + '\' LIMIT 1')
+ post = FetchOne('SELECT `parentid` FROM `posts` WHERE `boardid` = %s AND `id` = %s LIMIT 1',
+ (board['id'], path_split[6]))
if not post:
message = _(
'Unable to locate a post with that ID.') + '<br />'
template_filename = "message.html"
else:
- UpdateDb('UPDATE `posts` SET `IS_DELETED` = 0 WHERE `boardid` = ' +
- board['id'] + ' AND `id` = \'' + _mysql.escape_string(path_split[6]) + '\' LIMIT 1')
- if post['parentid'] != '0':
+ UpdateDb('UPDATE `posts` SET `IS_DELETED` = 0 WHERE `boardid` = %s AND `id` = %s LIMIT 1',
+ (board['id'], path_split[6]))
+ if post['parentid'] != 0:
threadUpdated(post['parentid'])
else:
regenerateFrontPages()
@@ -1485,8 +1480,7 @@ def manage(self, path_split):
elif filter_action == 1:
# Change to
if len(self.formdata["changeto"]) > 0:
- filter_to = _mysql.escape_string(
- self.formdata["changeto"])
+ filter_to = self.formdata["changeto"]
sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `to`, `added`, `staff`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
sql_params = (edit_id, where, filter_type, filter_action, filter_from, filter_tripcode, filter_reason, filter_to, timestamp(), staff_account['username'])
else:
@@ -1495,27 +1489,24 @@ def manage(self, path_split):
return
elif filter_action == 2:
# Ban
- filter_seconds = '0'
+ filter_seconds = 0
if len(self.formdata["seconds"]) > 0:
- filter_seconds = _mysql.escape_string(
- self.formdata["seconds"])
- if "blind" in self.formdata and self.formdata["blind"] == '1':
- filter_blind = '1'
+ filter_seconds = int(self.formdata["seconds"])
+ if "blind" in self.formdata and self.formdata["blind"] == 1:
+ filter_blind = 1
else:
- filter_blind = '2'
+ filter_blind = 2
- sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `seconds`, `blind`, `added`, `staff`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')" % \
- (edit_id, where, str(filter_type), str(filter_action), filter_from, filter_tripcode, filter_reason,
- filter_seconds, filter_blind, str(timestamp()), _mysql.escape_string(staff_account['username']))
+ sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `seconds`, `blind`, `added`, `staff`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
+ sql_params = (edit_id, where, filter_type, filter_action, filter_from, filter_tripcode, filter_reason,
+ filter_seconds, filter_blind, timestamp(), staff_account['username'])
elif filter_action == 3:
# Redirect URL
if len(self.formdata['redirect_url']) > 0:
- redirect_url = _mysql.escape_string(
- self.formdata['redirect_url'])
+ redirect_url = self.formdata['redirect_url']
redirect_time = 0
try:
- redirect_time = int(
- self.formdata['redirect_time'])
+ redirect_time = int(self.formdata['redirect_time'])
except:
pass
else:
@@ -1523,20 +1514,17 @@ def manage(self, path_split):
_("You must enter a URL to redirect to."))
return
- sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `redirect_url`, `redirect_time`, `added`, `staff`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')" % \
- (edit_id, where, str(filter_type), str(filter_action), filter_from, filter_tripcode, filter_reason, redirect_url, str(
- redirect_time), str(timestamp()), _mysql.escape_string(staff_account['username']))
+ sql_query = "INSERT INTO `filters` (`id`, `boards`, `type`, `action`, `from`, `from_trip`, `reason`, `redirect_url`, `redirect_time`, `added`, `staff`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
+ sql_params = (edit_id, where, filter_type, filter_action, filter_from, filter_tripcode, filter_reason, redirect_url, redirect_time, timestamp(), staff_account['username'])
# DO QUERY!
if edit_id > 0:
- UpdateDb(
- "DELETE FROM `filters` WHERE `id` = %s" % str(edit_id))
- UpdateDb(sql_query)
+ UpdateDb("DELETE FROM `filters` WHERE `id` = %s", (edit_id,))
+ UpdateDb(sql_query, sql_params)
message = 'Filter edited.'
else:
- filt = FetchOne("SELECT `id` FROM `filters` WHERE `boards` = '%s' AND `type` = '%s' AND `from` = '%s'" % (
- where, str(filter_type), filter_from))
+ filt = FetchOne("SELECT `id` FROM `filters` WHERE `boards` = %s AND `type` = %s AND `from` = %s", (where, filter_type, filter_from))
if not filt:
- UpdateDb(sql_query)
+ UpdateDb(sql_query, sql_params)
message = 'Filter added.'
else:
message = 'This filter already exists here:' + ' <a href="' + \
@@ -1802,7 +1790,7 @@ def manage(self, path_split):
return
# Delete!
- UpdateDb("DELETE FROM `news` WHERE id = '" + _mysql.escape_string(path_split[4]) + "' AND type = '0'")
+ UpdateDb("DELETE FROM `news` WHERE id = %s AND type = '0'", (path_split[4],))
message = _("Deleted successfully.")
template_filename = "message.html"
else:
diff --git a/cgi/oekaki.py b/cgi/oekaki.py
index d12e94e..ab31fb7 100644
--- a/cgi/oekaki.py
+++ b/cgi/oekaki.py
@@ -209,7 +209,7 @@ def write_from_base64(fname, data):
def write_from_shi(fname, fp):
# Check data type
type = fp.read(1)
- if type != 'P':
+ if type != b'P':
return "UNSUPPORTED"
# Read header
diff --git a/cgi/post.py b/cgi/post.py
index 89c2a19..07b05bc 100644
--- a/cgi/post.py
+++ b/cgi/post.py
@@ -7,6 +7,7 @@ import threading
import queue
import formatting
import logging
+import html
from database import *
from template import *
@@ -193,7 +194,7 @@ def shortenMsg(message, elid='0', elboard='0'):
if len(message_shortened) > limit:
message_shortened = message_shortened[:limit]
- #message_shortened = formatting.close_html(message_shortened)
+ message_shortened = formatting.close_html(message_shortened)
return True, message_shortened
else:
@@ -722,12 +723,14 @@ def deletePost(postid, password, deltype=0, imageonly=False, quick=False):
if not post["parentid"]:
deleteReplies(post)
- logging.info("Deleting post " + str(postid))
+ logging.info("Deleting post %d - parentid: %d" % (post["id"], post["parentid"]))
if deltype != 0 and post["parentid"]:
# Soft delete (recycle bin)
+ logging.info("Soft delete")
UpdateDb("UPDATE `posts` SET `IS_DELETED` = %s WHERE `boardid` = %s AND `id` = %s LIMIT 1", (deltype, board["id"], post["id"]))
else:
# Hard delete
+ logging.info("Hard delete")
if post["file"]:
deleteFile(post)
@@ -745,10 +748,16 @@ def deletePost(postid, password, deltype=0, imageonly=False, quick=False):
(newlast["timestamp"], threadNumReplies(post["parentid"]), post["parentid"], board["id"]))
if not post['parentid']:
+ logging.info("Unlinking html")
if board['board_type'] == 1:
- os.unlink(Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["timestamp"]) + ".html")
+ fname = Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["timestamp"]) + ".html"
else:
- os.unlink(Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["id"]) + ".html")
+ fname = Settings.ROOT_DIR + str(board["dir"]) + "/res/" + str(post["id"]) + ".html"
+
+ try:
+ os.unlink(fname)
+ except FileNotFoundError:
+ logging.warn("Thread HTML (%s) didn't exist! Continuing..." % fname)
regenerateHome()
@@ -907,7 +916,7 @@ def autoclose_thread(parentid, t, replies):
notice_post["bumped"] = get_parent_post(parentid, board["id"])["bumped"]
notice_post["timestamp_formatted"] = str(replylimit) + " mensajes"
notice_post.insert()
- UpdateDb("UPDATE `posts` SET `locked` = 1 WHERE `boardid` = '%s' AND `id` = '%s' LIMIT 1" % (board["id"], _mysql.escape_string(parentid)))
+ UpdateDb("UPDATE `posts` SET `locked` = 1 WHERE `boardid` = %s AND `id` = %s LIMIT 1", (board["id"], parentid))
def pageNavigator(page_num, page_count, is_omitted=False):
"""
@@ -972,10 +981,12 @@ def flood_check(t,post,boardid):
if not post["parentid"]:
maxtime = round(t - int(board['threadsecs']))
- #lastpost = FetchOne("SELECT COUNT(*) FROM `posts` WHERE `ip` = INET6_ATON('%s') and `parentid` = 0 and `boardid` = '%s' and IS_DELETED = 0 AND timestamp > %d" % (str(post["ip"]), boardid, int(maxtime)), 0)
+ lastpost = FetchOne("SELECT `timestamp` FROM `posts` WHERE `ip` = INET6_ATON(%s) and `parentid` = 0 and `boardid` = %s and IS_DELETED = 0 AND timestamp > %s",
+ (post["ip"], boardid, maxtime))
# NO MATTER THE IP
- lastpost = FetchOne("SELECT `timestamp` FROM `posts` WHERE `parentid` = 0 and `boardid` = %s and IS_DELETED = 0 AND timestamp > %s",
+ if not lastpost:
+ lastpost = FetchOne("SELECT `timestamp` FROM `posts` WHERE `parentid` = 0 and `boardid` = %s and IS_DELETED = 0 AND timestamp > %s",
(boardid, maxtime))
else:
maxtime = round(t - int(board['postsecs']))
@@ -990,11 +1001,10 @@ def flood_check(t,post,boardid):
wait = int(int(board['threadsecs']) - (t - int(lastpost["timestamp"])))
raise UserError("Espera " + str(wait) + " segundos antes de crear otro hilo.")
-def cut_home_msg(message, boardlength=0):
+def cut_msg(message, limit):
short_message = message.replace("<br />", " ")
short_message = short_message.split("<hr />")[0]
short_message = re.compile(r"<[^>]*?>", re.DOTALL | re.IGNORECASE).sub("", short_message) # Removes HTML tags
- limit = Settings.HOME_LASTPOSTS_LENGTH - boardlength
if len(short_message) > limit:
if isinstance(short_message, str):
@@ -1002,6 +1012,9 @@ def cut_home_msg(message, boardlength=0):
short_message = re.compile(r"&(.(?!;))*$", re.DOTALL | re.IGNORECASE).sub("", short_message) # Removes incomplete HTML
return short_message
+def cut_home_msg(message, boardlength=0):
+ return cut_msg(message, Settings.HOME_LASTPOSTS_LENGTH - boardlength)
+
def getLastAge(board_type, limit):
threads = []
sql = "SELECT posts.id, boards.name AS board_fulln, boards.subname AS board_name, board_type, boards.dir, timestamp, bumped, last, length, thumb, CASE WHEN posts.subject = boards.subject THEN posts.message ELSE posts.subject END AS content FROM posts INNER JOIN boards ON boardid = boards.id WHERE parentid = 0 AND IS_DELETED = 0 AND boards.secret = 0 AND posts.locked < 3 AND boards.board_type = %s ORDER BY bumped DESC LIMIT %s"
@@ -1209,12 +1222,13 @@ def latestAdd(post, postnum, postid, parent_post):
else:
url = '/%s/res/%s.html#%s' % (board['dir'], parentid, postid)
- sql = "INSERT INTO last (id, boardid, board_name, timestamp, timestamp_formatted, content, url) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s')" % (str(postid), board['id'], _mysql.escape_string(board['name']), post['timestamp'], _mysql.escape_string(timestamp_formatted), _mysql.escape_string(content), _mysql.escape_string(url))
- UpdateDb(sql)
+ sql = "INSERT INTO last (id, boardid, board_name, timestamp, timestamp_formatted, content, url) VALUES (%s, %s, %s, %s, %s, %s, %s)"
+ params = (postid, board['id'], board['name'], post['timestamp'], timestamp_formatted, content, url)
+ UpdateDb(sql, params)
def latestRemove(postid):
board = Settings._.BOARD
- UpdateDb("DELETE FROM last WHERE id = %s AND boardid = %s" % (str(postid), board['id']))
+ UpdateDb("DELETE FROM last WHERE id = %s AND boardid = %s", (postid, board['id']))
def archiveThread(postid):
import json
@@ -1271,7 +1285,7 @@ def magic_ball():
return string
-def discord_hook(post, url):
+def discord_hook(post, parent_post, url):
if not Settings.DISCORD_HOOK_URL:
return
@@ -1280,23 +1294,31 @@ def discord_hook(post, url):
board = Settings._.BOARD
- #data = {"embeds": [{
- # "title": post['subject'],
- # "description": cut_home_msg(post['message'], 30),
- # "url": "https://bienvenidoainternet.org" + url, # TODO: Parametrizar.
- # "color": 11910504,
- # "timestamp": datetime.datetime.utcfromtimestamp(post['timestamp']).isoformat(),
- # "footer": { "text": board['name'] },
- # "thumbnail": { "url": "%s%s/thumb/%s" % (Settings.HOME_URL, board['dir'], post['thumb']) },
- # "author": {
- # "name": "Nuevo hilo",
- # "icon_url": "%s0/junk/w/shobon.gif" % Settings.HOME_URL
- # }}]
- #}
- data = {"content": "test"}
- jsondata = json.dumps(data, separators=(',',':'))
-
- opener = urllib.request.build_opener()
- #opener.addheaders = [('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0')]
- response = opener.open(Settings.DISCORD_HOOK_URL, jsondata, 6)
- the_page = response.read()
+ if parent_post:
+ ptitle = "Nueva respuesta en {} ({})".format(html.unescape(parent_post["subject"]), parent_post["length"]+1)
+ else:
+ ptitle = "Nuevo hilo: {}".format(html.unescape(post['subject']))
+
+ data = {"embeds": [{
+ "type": "rich",
+ "title": ptitle,
+ "description": html.unescape(cut_msg(post['message'], 200)),
+ "color": 11910504,
+ "url": "https://bienvenidoainternet.org" + url, # TODO: Parametrizar.
+ "timestamp": datetime.datetime.utcfromtimestamp(post['timestamp']).isoformat(),
+ "footer": { "text": board['name'] },
+ }]
+ }
+ if post['thumb']:
+ data["embeds"][0]["thumbnail"] = {"url": "%s%s/thumb/%s" % (Settings.HOME_URL, board['dir'], post['thumb'])}
+ jsondata = json.dumps(data, separators=(',',':')).encode('utf-8')
+
+ try:
+ req = urllib.request.Request(Settings.DISCORD_HOOK_URL)
+ req.add_header('Content-Type', 'application/json')
+ req.add_header('Content-Length', len(jsondata))
+ req.add_header('User-Agent', "weabot/0.1")
+ response = urllib.request.urlopen(req, jsondata)
+ except urllib.error.HTTPError as e:
+ raise Exception(e.read())
+
diff --git a/cgi/templates/board.html b/cgi/templates/board.html
index 70718b8..3732ba9 100644
--- a/cgi/templates/board.html
+++ b/cgi/templates/board.html
@@ -241,11 +241,11 @@
<div style="color:red;font-weight:bold;">Este hilo es viejo y desaparecerá pronto.</div>
<?py #endif ?>
<?py #endif ?>
- <?py if post['parentid'] == "0": ?>
+ <?py if not post['parentid']: ?>
<?py if not replythread: ?>
- <?py if int(thread['omitted']) == 1: ?>
+ <?py if thread['omitted'] == 1: ?>
<div class="omitted">Un post omitido. Haz clic en Responder para ver.</div>
- <?py elif int(thread['omitted']) > 1: ?>
+ <?py elif thread['omitted'] > 1: ?>
<div class="omitted">#{thread['omitted']} posts omitidos. Haz clic en Responder para ver.</div>
<?py #endif ?>
<?py #endif ?>
diff --git a/cgi/templates/board.jp.html b/cgi/templates/board.jp.html
index f463dee..06a9391 100644
--- a/cgi/templates/board.jp.html
+++ b/cgi/templates/board.jp.html
@@ -238,9 +238,9 @@
<div style="color:red;font-weight:bold">このスレは古いので、もうすぐ消えます。</div>
<?py #endif ?>
<?py #endif ?>
- <?py if int(post['parentid']) == 0: ?>
+ <?py if not post['parentid']: ?>
<?py if not replythread: ?>
- <?py if int(thread['omitted']) > 0: ?>
+ <?py if thread['omitted']: ?>
<span class="omitted">レス${thread['omitted']}件省略。全て読むには返信ボタンを押してください。</span>
<?py #endif ?>
<?py #endif ?>
@@ -266,4 +266,4 @@
<?py if pagenav: ?>
<div class="pg">#{pagenav}</div>
<?py #endif ?>
-<?py include('templates/base_bottom.html') ?> \ No newline at end of file
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/home.html b/cgi/templates/home.html
index a9ca238..47ee5c7 100644
--- a/cgi/templates/home.html
+++ b/cgi/templates/home.html
@@ -29,10 +29,12 @@
<a href="/juegos/">Juegos</a>
<a href="/musica/">Música</a>
<a href="/letras/">Humanidades</a>
+ <a href="/drogas/">Psicotrópicos</a>
</div>
<div class="cat">
<h3>Conversación</h3>
<a href="/zonavip/">Club VIP</a>
+ <a href="/consejos/">Consejos</a>
<a href="/world/">World Lobby</a>
</div>
<div class="cat">
diff --git a/cgi/templates/mobile/board.html b/cgi/templates/mobile/board.html
index 8466c8f..f32a12c 100644
--- a/cgi/templates/mobile/board.html
+++ b/cgi/templates/mobile/board.html
@@ -4,12 +4,12 @@
<?py for thread in threads: ?>
<div id="thread">
<?py for post in thread['posts']: ?>
- <?py if post['IS_DELETED'] == "1": ?>
+ <?py if post['IS_DELETED'] == 1: ?>
<div class="pst"><h3 class="del"><a name="#{post['id']}"></a>No.#{post['id']} eliminado por usuario.</h3></div>
- <?py elif post['IS_DELETED'] == "2": ?>
+ <?py elif post['IS_DELETED'] == 2: ?>
<div class="pst"><h3 class="del"><a name="#{post['id']}"></a>No.#{post['id']} eliminado por staff.</h3></div>
<?py else: ?>
- <?py if post['parentid'] == "0": ?>
+ <?py if not post['parentid']: ?>
<div class="first"><h1>#{post["subject"]} <span>(#{thread['length']})</span></h1>
<?py else: ?>
<div class="pst">
@@ -21,11 +21,11 @@
<div class="msg">#{post['message']}</div></div>
<?py #endif ?>
<?py #endfor ?>
-<?py if threads[0]['posts'][0]['locked'] != "1": ?>
+<?py if threads[0]['posts'][0]['locked'] != 1: ?>
<a href="./#{thread['id']}" id="n">Recargar</a><span id="n2"></span>
<?py #endif ?>
<div class="nav"><div><a href="//m.bienvenidoainternet.org">Home</a><a href="#{cgi_url}mobile/#{board}/">Volver</a><a href="#top">&#9650;</a></div></div>
-<?py if threads[0]['posts'][0]['locked'] == "1": ?>
+<?py if threads[0]['posts'][0]['locked'] == 1: ?>
<div class="warn red" style="text-align:center;">El hilo ha sido cerrado. Ya no se puede postear en &eacute;l.</div>
<?py else: ?>
<form name="postform" id="postform" action="/cgi/post" method="post" enctype="multipart/form-data">
@@ -52,4 +52,4 @@
<?py #endfor ?>
<a name="form"></a>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/cgi/templates/mobile/txt_thread.html b/cgi/templates/mobile/txt_thread.html
index 3df16fc..8397fc7 100644
--- a/cgi/templates/mobile/txt_thread.html
+++ b/cgi/templates/mobile/txt_thread.html
@@ -71,4 +71,4 @@
<a name="form"></a>
<?py #endfor ?>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/cgi/templates/paint.html b/cgi/templates/paint.html
index 945a8d2..4787674 100644
--- a/cgi/templates/paint.html
+++ b/cgi/templates/paint.html
@@ -13,8 +13,8 @@
<script type="text/javascript">palette_selfy();</script>
<?py #endif ?>
<?py elif applet == 'neo': ?>
-<link rel="stylesheet" href="#{static_url}js/paintbbs/PaintBBS-1.3.4.css" type="text/css" />
-<script src="#{static_url}js/paintbbs/PaintBBS-1.3.4.js" charset="UTF-8"></script>
+<link rel="stylesheet" href="#{static_url}js/paintbbs/PaintBBS-1.5.15.css" type="text/css" />
+<script src="#{static_url}js/paintbbs/PaintBBS-1.5.15.js" charset="UTF-8"></script>
<applet-dummy id="oekaki" name="paintbbs" width="#{width+250}" height="#{height+280}">
<param name="image_width" value="#{width}">
<param name="image_height" value="#{height}">
@@ -27,8 +27,8 @@
<param name="color_bk2" value="#D5D8EF">
<param name="color_icon" value="#A1B8D8">
<param name="color_iconselect" value="#000000">
-<param name="url_save" value="#{cgi_url}oekaki/save/#{board}/paintbbs?rawpost">
-<param name="url_exit" value="#{cgi_url}oekaki/finish/#{board}/#{replythread}">
+<param name="url_save" value="save/#{board}/paintbbs?rawpost">
+<param name="url_exit" value="finish/#{board}/#{replythread}">
<param name="poo" value="false">
<param name="send_advance" value="true">
<param name="thumbnail_width" value="100%">
diff --git a/cgi/weabot.py b/cgi/weabot.py
index e0e941a..ff3c9d3 100755
--- a/cgi/weabot.py
+++ b/cgi/weabot.py
@@ -126,6 +126,8 @@ class weabot(object):
self._newcookies = None
def run(self):
+ clearCache()
+
path_split = self.environ["PATH_INFO"].split("/")
caught = False
@@ -454,7 +456,7 @@ class weabot(object):
# Disallow posting if the site OR board is in maintenance
if Settings.MAINTENANCE and board["dir"] != 'polka':
raise UserError(_("%s is currently under maintenance. We'll be back.") % Settings.SITE_TITLE)
- if board["locked"] == '1':
+ if board["locked"] == 1:
raise UserError(_("This board is closed. You can't post in it."))
# create post object
@@ -471,17 +473,17 @@ class weabot(object):
parent_timestamp = parent_post['timestamp']
post["parentid"] = parent_post['id']
post["bumped"] = parent_post['bumped']
- if parent_post['locked'] == '1':
+ if parent_post['locked'] == 1:
raise UserError(_("The thread is closed. You can't post in it."))
# check if the user is flooding
flood_check(t, post, board["id"])
# use fields only if enabled
- if board["disable_name"] != '1':
+ if not board["disable_name"]:
post["name"] = cleanString(name)
post["email"] = cleanString(email, quote=True)
- if board["disable_subject"] != '1':
+ if not board["disable_subject"]:
post["subject"] = cleanString(subject)
# process tripcodes
@@ -495,7 +497,7 @@ class weabot(object):
if not post["parentid"] and board["dir"] not in ['bai', 'world']:
# creating thread
- __extend = re.compile(r"^!extend(:\w+)(:\w+)?\n")
+ __extend = re.compile(r"!extend(:\w+)(:\w+)?\n", re.IGNORECASE)
res = __extend.match(message)
if res:
extend = res.groups()
@@ -510,7 +512,8 @@ class weabot(object):
# add function messages
if extend_str:
- extend_str = extend_str.replace('!extend', 'EXTEND')
+ extend_str = extend_str[1:]
+ extend_str = extend_str.replace('extend', 'EXTEND')
post["message"] += '<hr />' + extend_str + ' configurado.'
if not post["parentid"] and post["email"].lower() == 'sage':
@@ -527,12 +530,6 @@ class weabot(object):
capcode = Settings.CAPCODES[post["name"]]
if post["tripcode"] == (Settings.TRIP_CHAR + capcode[0]):
post["name"], post["tripcode"] = capcode[1], capcode[2]
- # if board['board_type'] == '1':
- # post["name"], post["tripcode"] = capcode[1], ''
- # else:
- # post["name"] = post["tripcode"] = ''
- # post["message"] = ('[<span style="color:red">%s</span>]<br />' % capcode[2]) + post["message"]
-
cap_id, hide_end, use_icon = capcode[3], capcode[4], capcode[5]
# hide ip if necessary
@@ -566,28 +563,28 @@ class weabot(object):
try:
# 1: ID
if extend[0] == ':no':
- board["useid"] = '0'
+ board["useid"] = 0
elif extend[0] == ':yes':
- board["useid"] = '1'
+ board["useid"] = 1
elif extend[0] == ':force':
- board["useid"] = '2'
+ board["useid"] = 2
elif extend[0] == ':extra':
- board["useid"] = '3'
+ board["useid"] = 3
# 2: Slip
if extend[1] == ':no':
- board["slip"] = '0'
+ board["slip"] = 0
elif extend[1] == ':yes':
- board["slip"] = '1'
+ board["slip"] = 1
elif extend[1] == ':domain':
- board["slip"] = '2'
+ board["slip"] = 2
elif extend[1] == ':verbose':
- board["slip"] = '3'
+ board["slip"] = 3
elif extend[1] == ':country':
- board["countrycode"] = '1'
+ board["countrycode"] = 1
elif extend[1] == ':all':
- board["slip"] = '3'
- board["countrycode"] = '1'
+ board["slip"] = 3
+ board["countrycode"] = 1
except IndexError:
pass
@@ -743,7 +740,7 @@ class weabot(object):
host = '*.' + host
elif ':' in ip:
iprs = ip.split(':')
- host = '%s:%s:%s:%s:*.*.*.*' % (iprs[0], iprs[1], iprs[2], iprs[3])
+ host = '%s:%s:*:*:*.*.*.*' % (iprs[0], iprs[1])
else:
iprs = ip.split('.')
host = '%s.%s.*.*' % (iprs[0], iprs[1])
@@ -824,7 +821,7 @@ class weabot(object):
thread_length = threadNumReplies(post["parentid"])
# bump if not saged
- if 'sage' not in post["email"].lower() and parent_post['locked'] != '2':
+ if 'sage' not in post["email"].lower() and parent_post['locked'] != 2:
UpdateDb("UPDATE `posts` SET bumped = %s WHERE (`id` = %s OR `parentid` = %s) AND `boardid` = %s",
(post["timestamp"], post["parentid"], post["parentid"], board["id"]))
@@ -855,10 +852,10 @@ class weabot(object):
if Settings.ENABLE_RSS:
latestAdd(post, thread_length, postid, parent_post)
# call discord hook
- if Settings.ENABLE_DISCORD_HOOK and not post["parentid"]:
+ if Settings.ENABLE_DISCORD_HOOK:
hook_url = make_url(
postid, post, parent_post or post, True, False)
- discord_hook(post, hook_url)
+ discord_hook(post, parent_post, hook_url)
return (post_url, ttaken, postid)
diff --git a/static/js/paintbbs/PaintBBS-1.5.15.css b/static/js/paintbbs/PaintBBS-1.5.15.css
new file mode 100644
index 0000000..f79917f
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.5.15.css
@@ -0,0 +1,655 @@
+.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: 200px;
+ height: 400px;
+ 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;
+}
+
+/*
+-----------------------
+ Viewer
+-----------------------
+*/
+
+.NEO #viewerButtonsWrapper {
+ position: absolute;
+ bottom: 0px;
+ left: 0px;
+ width: 100%;
+ height: 24px;
+ border: 1px solid red;
+ margin:0;
+ padding:0;
+}
+
+.NEO #viewerButtons {
+ width: calc(100% - 2px);
+ height: 22px;
+ border: 1px solid white;
+ font-size: 0;
+ text-align: left;
+
+ margin: 0;
+ padding: 0;
+ /* padding-top: 2px; */
+ /* padding-left: 2px; */
+
+ overflow: hidden;
+}
+
+.NEO #viewerButtons > div {
+ margin: 0;
+ padding: 0;
+ width: 18px;
+ height: 18px;
+ overflow: hidden;
+ margin-top: 1px;
+ margin-left: 2px;
+
+ font-size: 14px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+}
+
+.NEO #viewerButtons >div.buttonOff {
+ display: inline-block;
+ border: 1px solid black;
+ width: 18px;
+ height: 18px;
+ background-color: red;
+
+ border-left: 1px solid rgba(0, 0, 0, 1);
+ border-top: 1px solid rgba(0, 0, 0, 1);
+ border-right: 1px solid rgba(0, 0, 0, 1);
+ border-bottom: 1px solid rgba(0, 0, 0, 1);
+}
+
+.NEO #viewerButtons >div.buttonOff:hover {}
+
+.NEO #viewerButtons >div.buttonOff:active,
+.NEO #viewerButtons >div.buttonOn {
+ display: inline-block;
+ border: 1px solid black;
+ width: 18px;
+ height: 18px;
+ background-color: grey;
+
+ border-right: 1px solid rgba(0, 0, 0, 1);
+ border-bottom: 1px solid rgba(0, 0, 0, 1);
+}
+
+.NEO #viewerButtons canvas {
+ max-width: 24px;
+ margin-left: 1px;
+ margin-top: 1px;
+}
+
+.NEO #viewerBarLeft {
+ pointer-events: none;
+ width: calc(100% - 2px);
+ height: 16px;
+ position: absolute;
+ top: 1px;
+ left: 1px;
+}
+
+.NEO #viewerBarMark {
+ pointer-events: none;
+ width: 1px;
+ height: 16px;
+ position: absolute;
+ top: 1px;
+ left: 1px;
+}
+
+.NEO #viewerBarText {
+ pointer-events: none;
+ position: absolute;
+ top: 0px;
+ left: 1px;
+ background-color: rgba(0, 0, 0, 0) !important;
+}
+
diff --git a/static/js/paintbbs/PaintBBS-1.5.15.js b/static/js/paintbbs/PaintBBS-1.5.15.js
new file mode 100644
index 0000000..50fe432
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.5.15.js
@@ -0,0 +1,9111 @@
+"use strict";
+
+document.addEventListener("DOMContentLoaded", function () {
+ if (Neo.init()) {
+ if (!navigator.userAgent.match("Electron")) {
+ Neo.start();
+ }
+ }
+});
+
+var Neo = function () {};
+
+Neo.version = "1.5.15";
+Neo.painter;
+Neo.fullScreen = false;
+Neo.uploaded = false;
+Neo.viewer = false;
+Neo.toolSide = 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" || name == "pch") {
+ Neo.applet = applet;
+
+ if (name == "paintbbs") {
+ Neo.initConfig(applet);
+ Neo.createContainer(applet);
+ Neo.init2();
+ } else {
+ Neo.viewer = true;
+ Neo.initConfig(applet);
+
+ var filename = Neo.getFilename();
+ var pch = Neo.getPCH(filename, function (pch) {
+ if (pch) {
+ Neo.createViewer(applet);
+ Neo.config.width = pch.width;
+ Neo.config.height = pch.height;
+ Neo.initViewer(pch);
+ Neo.startViewer();
+ }
+ });
+ }
+ return true;
+ }
+ }
+ return false;
+};
+
+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;
+ };
+
+ // 動画記録
+ Neo.animation = Neo.config.thumbnail_type == "animation";
+
+ // 続きから描く
+ Neo.storage = Neo.isMobile() ? localStorage : sessionStorage;
+
+ var filename = Neo.getFilename();
+ var message =
+ !filename || filename.slice(-4).toLowerCase() != ".pch"
+ ? "描きかけの画像があります。復元しますか?"
+ : "描きかけの画像があります。動画の読み込みを中止して復元しますか?";
+
+ if (Neo.storage.getItem("timestamp") && confirm(Neo.translate(message))) {
+ var oe = Neo.painter;
+ setTimeout(function () {
+ oe.loadSession(function () {
+ oe._pushUndo();
+ oe._actionMgr.restore();
+ });
+ }, 1);
+ } else if (filename) {
+ if (filename.slice(-4).toLowerCase() == ".pch") {
+ Neo.painter.loadAnimation(filename);
+ } else {
+ Neo.painter.loadImage(filename);
+ }
+ }
+
+ window.addEventListener(
+ "pagehide",
+ function (e) {
+ if (!Neo.uploaded && Neo.painter.isDirty()) {
+ 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);
+
+ if (Neo.viewer && !Neo.config.color_bar) {
+ Neo.config.color_bar = "#eeeeff";
+ }
+
+ 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");
+
+ // viewer用
+ if (Neo.viewer) {
+ Neo.applyStyle("color_back", "#ccccff");
+ Neo.applyStyle("color_bar_select", "#407675");
+ }
+
+ 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;
+
+ if (
+ Neo.config.neo_tool_side == "left" ||
+ Neo.config.neo_tool_side == "true"
+ ) {
+ Neo.toolSide = true;
+ }
+ }
+
+ 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.getStyleSheet = function () {
+ var style = document.createElement("style");
+ document.head.appendChild(style);
+ return style.sheet;
+};
+
+Neo.initSkin = function () {
+ Neo.styleSheet = Neo.getStyleSheet();
+ 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.painter ? 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.setToolSide(Neo.toolSide);
+};
+
+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 () {
+ var copyright = document.getElementById("copyright");
+ if (copyright) 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("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.submitButton = new Neo.Button().init("submit");
+ Neo.submitButton.onmouseup = function () {
+ Neo.submitButton.disable(5000);
+ new Neo.SubmitCommand(Neo.painter).execute();
+ };
+
+ Neo.fillButton = new Neo.FillButton().init("fill");
+ Neo.rightButton = new Neo.RightButton().init("right");
+
+ if (Neo.isMobile() || Neo.config.neo_show_right_button == "true") {
+ 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.viewer) 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 () {
+ if (navigator.userAgent.match(/Android|iPhone|iPad|iPod/i)) return true;
+ if (navigator.maxTouchPoints && navigator.maxTouchPoints > 1) return true;
+ return false;
+};
+
+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");
+ if (warning) {
+ 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;
+
+ if (Neo.viewer) {
+ width = canvasWidth;
+ height = canvasHeight;
+ }
+
+ 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";
+
+ if (Neo.toolsWrapper) {
+ 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.getAbsoluteURL = function (board, url) {
+ if (url && (url.indexOf('://') > 0 || url.indexOf('//') === 0)) {
+ return url;
+ } else {
+ return board + url;
+ }
+}
+
+Neo.submit = function (board, blob, thumbnail, thumbnail2) {
+ var url = Neo.getAbsoluteURL(board, Neo.config.url_save);
+ var headerString = Neo.str_header || "";
+
+ 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;
+ }
+
+ var count = Neo.painter.securityCount;
+ var timer = new Date() - Neo.painter.securityTimer;
+ if (Neo.config.send_header_count == "true") {
+ headerString = "count=" + count + "&" + headerString;
+ }
+ if (Neo.config.send_header_timer == "true") {
+ headerString = "timer=" + timer + "&" + headerString;
+ }
+ console.log("header: " + headerString);
+
+ if (Neo.config.neo_emulate_security_error == "true") {
+ var securityError = false;
+ if (Neo.config.security_click) {
+ if (count - parseInt(Neo.config.security_click || 0) < 0) {
+ securityError = true;
+ }
+ }
+ if (Neo.config.security_timer) {
+ if (timer - parseInt(Neo.config.security_timer || 0) * 1000 < 0) {
+ securityError = true;
+ }
+ }
+ if (securityError && Neo.config.security_url) {
+ if (Neo.config.security_post == "true") {
+ url = Neo.config.security_url;
+ } else {
+ location.href = Neo.config.security_url;
+ return;
+ }
+ }
+ }
+ // console.log("submit url=" + url + " 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 futaba = location.hostname.match(/2chan.net/i);
+ var subtype = futaba ? "octet-binary" : "octet-stream"; // 念のため
+ var body = new Blob(array, { type: "application/" + subtype });
+
+ var request = new XMLHttpRequest();
+ request.open("POST", url, true);
+
+ request.onload = function (e) {
+ console.log(request.response, "status=", request.status);
+
+ var errorMessage = null;
+ if (request.status / 100 != 2) {
+ errorMessage = request.responseURL + "\n"
+ + Neo.translate("投稿に失敗。時間を置いて再度投稿してみてください。");
+ } else if (request.response.match(/^error\n/m)) {
+ errorMessage = request.response.replace(/^error\n/m, '');
+ } else {
+ Neo.uploaded = true;
+ }
+
+ var exitURL = Neo.getAbsoluteURL(board, Neo.config.url_exit);
+ var responseURL = request.response.replace(/&amp;/g, "&");
+
+ // ふたばではresponseの文字列をそのままURLとして解釈する
+ if (responseURL.match(/painttmp=/)) {
+ exitURL = responseURL;
+ }
+ // responseが "URL:〜" の形だった場合はそのURLへ
+ if (responseURL.match(/^URL:/)) {
+ exitURL = responseURL.replace(/^URL:/, "");
+ }
+
+ if (Neo.uploaded) {
+ location.href = exitURL;
+ } else {
+ alert(errorMessage);
+ Neo.submitButton.enable();
+ }
+ };
+ request.onerror = function (e) {
+ console.log("error");
+ Neo.submitButton.enable();
+ };
+ request.onabort = function (e) {
+ console.log("abort");
+ Neo.submitButton.enable();
+ };
+ request.ontimeout = function (e) {
+ console.log("timeout");
+ Neo.submitButton.enable();
+ };
+
+ 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 =
+ '<div id="pageView" style="margin:auto; width:450px; height:470px;">' +
+ '<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">' +
+ '<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>" +
+ "</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>";
+
+ 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);
+};
+
+Neo.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.setToolSide = function (side) {
+ if (side === "left") side = true;
+ if (side === "right") side = false;
+ Neo.toolSide = !!side;
+
+ if (!Neo.toolSide) {
+ Neo.addRule(".NEO #toolsWrapper", "right", "-3px");
+ Neo.addRule(".NEO #toolsWrapper", "left", "auto");
+ Neo.addRule(".NEO #painterWrapper", "padding", "0 55px 0 0 !important");
+ Neo.addRule(".NEO #upper", "padding-right", "75px !important");
+ } else {
+ Neo.addRule(".NEO #toolsWrapper", "right", "auto");
+ Neo.addRule(".NEO #toolsWrapper", "left", "-1px");
+ Neo.addRule(".NEO #painterWrapper", "padding", "0 0 0 55px !important");
+ Neo.addRule(".NEO #upper", "padding-right", "20px !important");
+ }
+};
+
+"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>",
+
+ "画像を投稿しますか?<br>投稿に成功後、編集を終了します。":
+ "Is the picture contributed?<br>if contribution completed, you jump to the comment page.",
+ "描きかけの画像があります。動画の読み込みを中止して復元しますか?":
+ "Discard animation data and restore session?",
+ 最: "Mx",
+ 早: "H",
+ 既: "M",
+ 鈍: "L",
+ "投稿に失敗。時間を置いて再度投稿してみてください。":
+ "Please push send button again.",
+ },
+ enx: {
+ やり直し: "Redo",
+ 元に戻す: "Undo",
+ 塗り潰し: "Fill",
+ 窓: "Float",
+ 投稿: "Send",
+ "(C)しぃちゃん PaintBBS NEO": "&copy;shi-chan 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>",
+
+ "画像を投稿しますか?<br>投稿に成功後、編集を終了します。":
+ "Send this picture and end session?",
+ "描きかけの画像があります。動画の読み込みを中止して復元しますか?":
+ "Discard animation data and restore session?",
+ 最: "Mx",
+ 早: "H",
+ 既: "M",
+ 鈍: "L",
+ "投稿に失敗。時間を置いて再度投稿してみてください。":
+ "Failed to upload image. please try again.",
+ },
+ es: {
+ やり直し: "Rehacer",
+ 元に戻す: "Deshacer",
+ 塗り潰し: "Llenar",
+ 窓: "Ventana",
+ 投稿: "Enviar",
+ "(C)しぃちゃん PaintBBS NEO": "&copy;shi-chan 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>",
+
+ "画像を投稿しますか?<br>投稿に成功後、編集を終了します。":
+ "¿Enviar esta imagen y finalizar sesión?",
+ "描きかけの画像があります。動画の読み込みを中止して復元しますか?":
+ "¿Desechar datos de animación y restaurar sesión?",
+ 最: "Mx",
+ 早: "H",
+ 既: "M",
+ 鈍: "L",
+ "投稿に失敗。時間を置いて再度投稿してみてください。":
+ "No se pudo cargar la imagen. por favor, inténtalo de nuevo.",
+ },
+};
+
+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);
+ this._actionMgr = new Neo.ActionManager();
+};
+
+Neo.Painter.prototype.container;
+Neo.Painter.prototype._undoMgr;
+Neo.Painter.prototype._actionMgr;
+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.prototype.dirty = false;
+Neo.Painter.prototype.busy = false;
+Neo.Painter.prototype.busySkipped = false;
+
+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.LINETYPE_BLUR = 7;
+
+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;
+
+ this.securityTimer = new Date() - 0;
+ this.securityCount = 0;
+
+ 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;
+
+ if (!Neo.viewer) {
+ 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);
+ };
+ }
+
+ if (Neo.config.neo_confirm_unload == "true") {
+ window.onbeforeunload = function () {
+ if (!Neo.uploaded && Neo.painter.isDirty()) {
+ return false;
+ }
+ };
+ }
+ 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();
+ // console.log(document.activeElement.tagName)
+ if (
+ document.activeElement != this.inputText &&
+ !(document.activeElement.tagName == "INPUT")
+ ) {
+ 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 (this.busy) {
+ // loadAnimation実行中は何もしない
+ if (e.target == Neo.painter.destCanvas) {
+ this.busySkipped = true;
+ }
+ return;
+ }
+
+ 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;
+ this.securityCount++;
+
+ 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._actionMgr.back();
+
+ 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._actionMgr.forward();
+
+ 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);
+
+ if (!holdRedo) {
+ this._actionMgr.step();
+ }
+ this.dirty = true;
+};
+
+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) {
+ if (Neo.animation) {
+ // neo_save_layers
+ var items = this._actionMgr._items;
+ if (items.length > 0 && items[items.length - 1][0] != "restore") {
+ this._pushUndo();
+ this._actionMgr.restore();
+ }
+ }
+
+ var thumbnail = null;
+ var thumbnail2 = null;
+
+ if (Neo.config.thumbnail_type == "animation" || this.useThumbnail()) {
+ thumbnail = this.getThumbnail(Neo.config.thumbnail_type || "png");
+ }
+
+ if (Neo.config.thumbnail_type2 && this.useThumbnail()) {
+ thumbnail2 = this.getThumbnail(Neo.config.thumbnail_type2);
+ }
+
+ /*
+ 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 {
+ var data = JSON.stringify(this._actionMgr._items);
+ data = LZString.compressToUint8Array(data);
+
+ var magic = "NEO ";
+ var w = this.canvasWidth;
+ var h = this.canvasHeight;
+
+ return new Blob([
+ magic,
+ new Uint8Array([w % 0x100, Math.floor(w / 0x100)]),
+ new Uint8Array([h % 0x100, Math.floor(h / 0x100)]),
+ new Uint8Array(4),
+ data,
+ ]);
+ }
+};
+
+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._actionMgr.clearCanvas();
+ /*
+ 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 * 0.5, this.destCanvas.height * 0.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._currentColor[3] / 255.0; //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];
+ this._currentWidth = this.lineWidth;
+ this._currentMaskType = this.maskType;
+};
+
+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._currentMaskType; //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._currentWidth;
+ 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._currentWidth;
+ 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._currentWidth;
+ var r0 = Math.floor(d / 2);
+
+ x -= r0;
+ y -= r0;
+ x0 -= r0;
+ y0 -= r0;
+
+ 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._currentWidth;
+ 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._currentColor[3]); //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._currentWidth;
+ 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;
+ var a1 = this._currentColor[3] / 255.0 / 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._currentWidth;
+ 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._currentWidth;
+ 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];
+};
+
+Neo.Painter.prototype.drawBezier = function (
+ ctx,
+ x0,
+ y0,
+ x1,
+ y1,
+ x2,
+ y2,
+ x3,
+ y3,
+ type,
+ isReplay,
+ isPreview
+) {
+ var points = [
+ [x0, y0],
+ [x1, y1],
+ [x2, y2],
+ [x3, y3],
+ ];
+ var that = this;
+
+ this.draw(ctx, points, function (left, top, width, height, buf8, imageData) {
+ var n = Math.ceil((width + height) * 2.5);
+ var oType = that._currentMaskType;
+ var oAlpha = that._currentColor[3];
+
+ if (isPreview) {
+ that._currentMaskType = Neo.Painter.MASKTYPE_NONE;
+ that._currentColor[3] = 255;
+ }
+
+ for (var i = 0; i < n; i++) {
+ var t = (i * 1.0) / n;
+ var p = that.getBezierPoint(t, x0, y0, x1, y1, x2, y2, x3, y3);
+
+ p[0] = Math.round(p[0]);
+ p[1] = Math.round(p[1]);
+
+ that.plot(p, function (x, y) {
+ that.setPoint(buf8, imageData.width, x, y, left, top, type);
+ });
+ }
+ that._currentMaskType = oType;
+ that._currentColor[3] = oAlpha;
+ that.prevLine = null;
+ });
+};
+
+Neo.Painter.prototype.prevLine = null; // 始点または終点が2度プロットされることがあるので
+Neo.Painter.prototype.drawLine = function (ctx, x0, y0, x1, y1, type) {
+ var points = [
+ [x0, y0],
+ [x1, y1],
+ ];
+ var that = this;
+ this.aerr = 0;
+
+ this.draw(ctx, points, function (left, top, width, height, buf8, imageData) {
+ that.bresenham(points, function (x, y) {
+ that.setPoint(buf8, imageData.width, x, y, left, top, type);
+ });
+ });
+ this.prevLine = points;
+};
+
+Neo.Painter.prototype.draw = function (ctx, points, callback) {
+ var xs = [],
+ ys = [];
+ for (var i = 0; i < points.length; i++) {
+ var point = points[i];
+ xs.push(Math.round(point[0]));
+ ys.push(Math.round(point[1]));
+ }
+ var xmin = Math.min.apply(null, xs);
+ var xmax = Math.max.apply(null, xs);
+ var ymin = Math.min.apply(null, ys);
+ var ymax = Math.max.apply(null, ys);
+
+ var r = Math.ceil(this._currentWidth / 2);
+ var left = xmin - r;
+ var top = ymin - r;
+ var width = xmax - xmin;
+ var height = ymax - ymin;
+
+ 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);
+
+ callback(left, top, width, height, buf8, imageData);
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+};
+
+Neo.Painter.prototype.bresenham = function (points, callback) {
+ var x0 = points[0][0];
+ var y0 = points[0][1];
+ var x1 = points[1][0];
+ var y1 = points[1][1];
+
+ var dx = Math.abs(x1 - x0),
+ sx = x0 < x1 ? 1 : -1;
+ var dy = Math.abs(y1 - y0),
+ sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+
+ while (true) {
+ if (
+ this.prevLine == null ||
+ !(
+ (this.prevLine[0][0] == x0 && this.prevLine[0][1] == y0) ||
+ (this.prevLine[1][0] == x0 && this.prevLine[1][1] == y0)
+ )
+ ) {
+ callback(x0, y0);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) {
+ err -= dy;
+ x0 += sx;
+ }
+ if (e2 < dy) {
+ err += dx;
+ y0 += sy;
+ }
+ }
+ this.prevLine = points;
+};
+
+Neo.Painter.prototype.plot = function (point, callback) {
+ var x0 = point[0];
+ var y0 = point[1];
+
+ if (
+ this.prevLine == null ||
+ !(this.prevLine[0][0] == x0 && this.prevLine[0][1] == y0)
+ ) {
+ callback(x0, y0);
+ }
+ this.prevLine = [point, point];
+};
+
+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 (layer, x, y, width, height) {
+ var ctx = this.canvasCtx[layer];
+ 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._currentColor[3] / 255.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 (layer, x, y, width, height) {
+ var ctx = this.canvasCtx[layer];
+ 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 (layer, x, y, width, height) {
+ var ctx = this.canvasCtx[layer];
+ 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 (layer, x, y, width, height) {
+ var ctx = this.canvasCtx[layer];
+ 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 = layer;
+ 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 (layer, x, y, width, height) {
+ var ctx = this.canvasCtx[layer];
+ 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._currentColor[3] / 255.0 / 12; //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, color) {
+ var index = y * this.canvasWidth + x0;
+ for (var x = x0; x <= x1; x++) {
+ buf32[index++] = color;
+ }
+};
+
+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 });
+ }
+};
+
+Neo.Painter.prototype.doFloodFill = function (layer, x, y, fillColor) {
+ x = Math.round(x);
+ y = Math.round(y);
+ var ctx = this.canvasCtx[layer];
+
+ 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];
+
+ 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, fillColor);
+
+ 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 (layer, x, y, width, height) {
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+
+ var imageData = this.canvasCtx[layer].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 (layer, x, y, width, height, dx, dy) {
+ var ctx = this.canvasCtx[layer];
+ // console.log(this.tempX, this.tempY);
+
+ var imageData = ctx.getImageData(x + dx, y + dy, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ if (this.temp) {
+ for (var i = 0; i < buf32.length; i++) {
+ buf32[i] = this.temp[i];
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x + dx, y + dy);
+ }
+
+ this.temp = null;
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.turn = function (layer, x, y, width, height) {
+ var ctx = this.canvasCtx[layer];
+
+ // 傾けツールのバグを再現するため一番上のラインで対象領域を埋める
+ 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.getMaskFunc = function (type) {
+ switch (type) {
+ case Neo.Painter.TOOLTYPE_RECT:
+ return this.rectMask;
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ return this.rectFillMask;
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ return this.ellipseMask;
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return this.ellipseFillMask;
+ }
+ return null;
+};
+
+Neo.Painter.prototype.doFill = function (layer, x, y, width, height, type) {
+ var ctx = this.canvasCtx[layer];
+ var maskFunc = this.getMaskFunc(type);
+
+ 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._currentMaskType >= 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._currentWidth;
+ // 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._currentWidth;
+ // 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.loadAnimation = function (filename) {
+ console.log("loadAnimation " + filename);
+
+ Neo.painter.busy = true;
+ Neo.painter.busySkipped = false;
+
+ Neo.getPCH(filename, function (pch) {
+ //console.log(pch);
+ Neo.painter._actionMgr._items = pch.data;
+ Neo.painter._actionMgr._mark = pch.data.length;
+ Neo.painter._actionMgr.play();
+ });
+};
+
+Neo.Painter.prototype.loadSession = function (callback) {
+ 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);
+
+ if (callback) callback();
+ };
+ };
+ }
+};
+
+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 (
+ layer,
+ x,
+ y,
+ color,
+ alpha,
+ string,
+ fontSize,
+ fontFamily
+) {
+ //テキスト描画
+ if (string.length <= 0) return;
+
+ //描画位置がずれるので適当に調整
+ var offset = parseInt(fontSize, 10);
+ var ctx = this.tempCanvasCtx;
+ ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ ctx.save();
+ ctx.translate(x, y);
+ ctx.font = fontSize + " " + fontFamily;
+
+ ctx.fillStyle = 0;
+ ctx.fillText(string, 0, 0);
+ ctx.restore();
+
+ // 適当に二値化
+ var r = color & 0xff;
+ var g = (color & 0xff00) >> 8;
+ var b = (color & 0xff0000) >> 16;
+ var a = Math.round(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[layer];
+ 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);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Recorder Test
+ -------------------------------------------------------------------------
+ */
+
+Neo.Painter.prototype.play = function () {
+ if (this._actionMgr) {
+ this._actionMgr.clearCanvas();
+ this.prevLine = null;
+
+ //console.log('[play]');
+
+ this._actionMgr._head = 0;
+ this._actionMgr._index = 0;
+ this._actionMgr._mark = this._actionMgr._items.length;
+ this._actionMgr._pause = false;
+ this._actionMgr.play();
+ }
+};
+
+Neo.Painter.prototype.onrewind = function () {
+ if (this._actionMgr) {
+ this._actionMgr.clearCanvas();
+ this._actionMgr._head = 0;
+ this._actionMgr._index = 0;
+ this.prevLine = null;
+ }
+ if (Neo.viewerBar) Neo.viewerBar.update();
+ if (!this._actionMgr._pause) {
+ this._actionMgr.play();
+ }
+};
+
+Neo.Painter.prototype.onmark = function () {
+ if (Neo.viewerBar) Neo.viewerBar.update();
+ if (!this._actionMgr._pause) {
+ if (this._actionMgr._head > this._actionMgr._mark) {
+ this.onrewind();
+ } else {
+ this.onplay();
+ }
+ }
+};
+
+Neo.Painter.prototype.onplay = function () {
+ Neo.viewerPlay.setSelected(true);
+ Neo.viewerStop.setSelected(false);
+
+ this._actionMgr._pause = false;
+ this._actionMgr.play();
+};
+
+Neo.Painter.prototype.onstop = function () {
+ Neo.viewerPlay.setSelected(false);
+ Neo.viewerStop.setSelected(true);
+ this._actionMgr._pause = true;
+};
+
+Neo.Painter.prototype.onspeed = function () {
+ var mgr = Neo.painter._actionMgr;
+ var mode = mgr.speedMode();
+ Neo.speed = mgr._speedTable[(mode + 1) % 4];
+};
+
+Neo.Painter.prototype.setCurrent = function (item) {
+ var color = this._currentColor;
+ var mask = this._currentMask;
+ var width = this._currentWidth;
+ var type = this._currentMaskType;
+
+ item.push(color[0], color[1], color[2], color[3]);
+ item.push(mask[0], mask[1], mask[2]);
+ item.push(width);
+ item.push(type);
+};
+
+Neo.Painter.prototype.getCurrent = function (item) {
+ this._currentColor = [item[2], item[3], item[4], item[5]];
+ this._currentMask = [item[6], item[7], item[8]];
+ this._currentWidth = item[9];
+ this._currentMaskType = item[10];
+};
+
+Neo.Painter.prototype.isDirty = function () {
+ return this.dirty;
+};
+
+"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._actionMgr.freeHand(x0, y0, this.lineType);
+ // 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);
+ oe._actionMgr.freeHandMove(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 x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe._actionMgr.line(x0, y0, this.startX, this.startY, this.lineType);
+
+ /*
+ 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 + 0.499 - oe.zoomX + (oe.destCanvas.width * 0.5) / oe.zoom) * oe.zoom;
+ var y0 =
+ (my + 0.499 - oe.zoomY + (oe.destCanvas.height * 0.5) / oe.zoom) * oe.zoom;
+ var x1 =
+ (nx + 0.499 - oe.zoomX + (oe.destCanvas.width * 0.5) / oe.zoom) * oe.zoom;
+ var y1 =
+ (ny + 0.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;
+ } else return; // 枠外からベジェを開始したときdownを通らずにupが呼ばれてエラーになる
+
+ 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._actionMgr.bezier(
+ 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.drawBezier(oe.canvasCtx[oe.current],
+ this.x0, this.y0, this.x1, this.y1,
+ this.x2, this.y2, this.x3, this.y3, this.lineType);
+ 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,
+ Neo.Painter.LINETYPE_PEN, //this.lineType,
+ false,
+ true
+ );
+ ctx.save();
+ ctx.translate(oe.destCanvas.width * 0.5, oe.destCanvas.height * 0.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,
+ Neo.Painter.LINETYPE_PEN, //this.lineType,
+ false,
+ true
+ );
+ ctx.save();
+ ctx.translate(oe.destCanvas.width * 0.5, oe.destCanvas.height * 0.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);
+ var layer = oe.current;
+ var color = oe.getColor();
+
+ oe._pushUndo();
+ oe._actionMgr.floodFill(layer, x, y, color);
+ //oe.doFloodFill(layer, x, y, color);
+};
+
+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._actionMgr.eraseAll();
+
+ /*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);
+ oe._actionMgr.eraseRect2(x, y, width, height);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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);
+ oe._actionMgr.flipH(x, y, width, height);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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);
+ oe._actionMgr.flipV(x, y, width, height);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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);
+ oe._actionMgr.blurRect(x, y, width, height);
+};
+
+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);
+ oe._actionMgr.turn(x, y, width, height);
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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);
+ oe._actionMgr.merge(x, y, width, height);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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(oe.current, x, y, width, height);
+ oe._actionMgr.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();
+
+ var dx = oe.tempX;
+ var dy = oe.tempY;
+ // oe.paste(oe.current, this.x, this.y, this.width, this.height, dx, dy);
+ // oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe._actionMgr.paste(this.x, this.y, this.width, this.height, dx, dy);
+
+ 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.kill = function () {
+ var oe = Neo.painter;
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+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, this.type); //oe.rectMask);
+ // oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe._actionMgr.fill(x, y, width, height, this.type);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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, this.type); //oe.rectFillMask);
+ // oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe._actionMgr.fill(x, y, width, height, this.type);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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, this.type); //oe.ellipseMask);
+ // oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe._actionMgr.fill(x, y, width, height, this.type);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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, this.type); //oe.ellipseFillMask);
+ // oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe._actionMgr.fill(x, y, width, height, this.type);
+};
+
+/*
+ -------------------------------------------------------------------------
+ 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);
+
+ var string = text.textContent || text.innerText;
+ var size = text.style.fontSize;
+ var family = text.style.fontFamily || "Arial";
+ var layer = oe.current;
+ var color = oe.getColor();
+ var alpha = oe.alpha;
+ var x = this.startX;
+ var y = this.startY;
+ //oe.doText(layer, this.startX, this.startY, color, string, size, family);
+ oe._actionMgr.text(
+ this.startX,
+ this.startY,
+ color,
+ alpha,
+ string,
+ size,
+ family
+ );
+
+ 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;
+
+ var string = text.textContent || text.innerText;
+ var size = text.style.fontSize;
+ var family = text.style.fontFamily || "Arial";
+ var layer = oe.current;
+ var color = oe.getColor();
+ var alpha = oe.alpha;
+ var x = this.startX;
+ var y = this.startY;
+ //oe.doText(layer, this.startX, this.startY, color, string, size, family);
+ oe._actionMgr.doText(layer, this.startX, this.startY,
+ color, alpha, string, size, family);
+};
+*/
+
+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(/[^/]*$/, "");
+ 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";
+
+/*
+ -----------------------------------------------------------------------
+ Action Manager
+ -----------------------------------------------------------------------
+*/
+
+Neo.ActionManager = function () {
+ this._items = [];
+ this._head = 0;
+ this._index = 0;
+
+ this._pause = false;
+ this._mark = 0;
+
+ this._speedTable = [-1, 0, 1, 11]; // [最, 早, 既, 鈍]
+
+ Neo.speed = parseInt(Neo.config.speed || 0);
+ this._prevSpeed = Neo.speed;
+};
+
+Neo.ActionManager.prototype.speedMode = function () {
+ if (Neo.speed < 0) {
+ return 0;
+ } else if (Neo.speed == 0) {
+ return 1;
+ } else if (Neo.speed <= 10) {
+ return 2;
+ } else {
+ return 3;
+ }
+};
+
+Neo.ActionManager.prototype.step = function () {
+ if (!Neo.animation) return;
+
+ if (this._items.length > this._head) {
+ this._items.length = this._head;
+ }
+ this._items.push([]);
+ this._head++;
+ this._index = 0;
+};
+
+Neo.ActionManager.prototype.back = function () {
+ if (!Neo.animation) return;
+
+ if (this._head > 0) {
+ this._head--;
+ }
+};
+
+Neo.ActionManager.prototype.forward = function () {
+ if (!Neo.animation) return;
+
+ if (this._head < this._items.length) {
+ this._head++;
+ }
+};
+
+Neo.ActionManager.prototype.push = function () {
+ if (!Neo.animation) return;
+
+ var head = this._items[this._head - 1];
+ for (var i = 0; i < arguments.length; i++) {
+ head.push(arguments[i]);
+ }
+};
+
+Neo.ActionManager.prototype.pushCurrent = function () {
+ if (!Neo.animation) return;
+
+ var oe = Neo.painter;
+ var head = this._items[this._head - 1];
+
+ var color = oe._currentColor;
+ var mask = oe._currentMask;
+ var width = oe._currentWidth;
+ var type = oe._currentMaskType;
+
+ head.push(color[0], color[1], color[2], color[3]);
+ head.push(mask[0], mask[1], mask[2]);
+ head.push(width);
+ head.push(type);
+};
+
+Neo.ActionManager.prototype.getCurrent = function (item) {
+ var oe = Neo.painter;
+
+ oe._currentColor = [item[2], item[3], item[4], item[5]];
+ oe._currentMask = [item[6], item[7], item[8]];
+ oe._currentWidth = item[9];
+ oe._currentMaskType = item[10];
+};
+
+Neo.ActionManager.prototype.skip = function () {
+ for (var i = 0; i < this._items.length; i++) {
+ if (this._items[i][0] == "restore") {
+ this._head = i;
+ }
+ }
+};
+
+Neo.ActionManager.prototype.play = function () {
+ if (Neo.viewerBar) Neo.viewerBar.update();
+
+ if (this._pause) {
+ console.log("suspend viewer");
+ return;
+ }
+
+ if (this._head < this._items.length && this._head < this._mark) {
+ var item = this._items[this._head];
+
+ if (!Neo.viewer) {
+ Neo.painter._pushUndo(
+ 0,
+ 0,
+ Neo.painter.canvasWidth,
+ Neo.painter.canvasHeight,
+ true
+ );
+ }
+
+ if (Neo.viewer && Neo.viewerSpeed && this._index == 0) {
+ Neo.viewerSpeed.update();
+ //console.log("play", item[0], this._head + 1, this._items.length);
+ }
+
+ var func = item[0] && this[item[0]] ? item[0] : "dummy";
+ var that = this;
+ var wait = this._prevSpeed < 0 ? 0 : this._prevSpeed;
+
+ this[func](item, function (result) {
+ if (result) {
+ if (
+ Neo.painter.busySkipped &&
+ that._head < that._mark - 2 &&
+ that._mark - 2 >= 0 &&
+ that._items[that._mark - 1][0] == "restore"
+ ) {
+ that._head = that._mark - 2;
+ } else {
+ that._head++;
+ }
+ that._index = 0;
+ that._prevSpeed = Neo.speed;
+ }
+
+ setTimeout(function () {
+ Neo.painter._actionMgr.play();
+ }, wait);
+ });
+
+ } else {
+ Neo.painter.dirty = false;
+ Neo.painter.busy = false;
+
+ if (Neo.painter.busySkipped) {
+ Neo.painter.busySkipped = false;
+ console.log("animation skipped");
+ } else {
+ console.log("animation finished");
+ }
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Action
+-------------------------------------------------------------------------
+*/
+
+Neo.ActionManager.prototype.clearCanvas = function () {
+ if (typeof arguments[0] != "object") {
+ this.push("clearCanvas");
+ }
+
+ 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.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.floodFill = function (layer, x, y, color) {
+ if (typeof layer != "object") {
+ this.push("floodFill", layer, x, y, color);
+ } else {
+ var item = layer;
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ color = item[4];
+ }
+
+ var oe = Neo.painter;
+ oe.doFloodFill(layer, x, y, color);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.eraseAll = function () {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("eraseAll", layer);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ }
+
+ var oe = Neo.painter;
+ oe.canvasCtx[layer].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.freeHand = function (x0, y0, lineType) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("freeHand", layer);
+ this.pushCurrent();
+ this.push(lineType, x0, y0, x0, y0);
+
+ oe.drawLine(oe.canvasCtx[layer], x0, y0, x0, y0, lineType);
+ } else if (!Neo.viewer || this._prevSpeed <= 0) {
+ this.freeHandFast(arguments[0], arguments[1]);
+ } else {
+ var item = arguments[0];
+
+ layer = item[1];
+ lineType = item[11];
+ this.getCurrent(item);
+
+ var i = this._index;
+ if (i == 0) {
+ i = 12;
+ } else {
+ i += 2;
+ }
+
+ var x1 = item[i + 0];
+ var y1 = item[i + 1];
+ x0 = item[i + 2];
+ y0 = item[i + 3];
+
+ oe.drawLine(oe.canvasCtx[layer], x0, y0, x1, y1, lineType);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ this._index = i;
+ var result = i + 2 + 3 >= item.length;
+
+ if (!result) {
+ oe.prevLine = null;
+ }
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") {
+ callback(result);
+ }
+ }
+};
+
+Neo.ActionManager.prototype.freeHandFast = function (x0, y0, lineType) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("freeHand", layer);
+ this.pushCurrent();
+ this.push(lineType, x0, y0, x0, y0);
+
+ oe.drawLine(oe.canvasCtx[layer], x0, y0, x0, y0, lineType);
+ } else {
+ var item = arguments[0];
+ var length = item.length;
+
+ layer = item[1];
+ this.getCurrent(item);
+
+ lineType = item[11];
+ x0 = item[12];
+ y0 = item[13];
+ var x1, y1;
+
+ for (var i = 14; i + 1 < length; i += 2) {
+ x1 = x0;
+ y1 = y0;
+ x0 = item[i + 0];
+ y0 = item[i + 1];
+ oe.drawLine(oe.canvasCtx[layer], x0, y0, x1, y1, lineType);
+ }
+ oe.prevLine = null;
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ }
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.freeHandMove = function (x0, y0, x1, y1, lineType) {
+ if (arguments.length > 1) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+ var head = this._items[this._head - 1];
+ if (head && head.length == 0) {
+ this.push("freeHand", layer);
+ this.pushCurrent();
+ this.push(lineType, x1, y1, x0, y0);
+ } else if (Neo.animation) {
+ head.push(x0, y0);
+
+ // 記録漏れがないか確認
+ var x = head[head.length - 4];
+ var y = head[head.length - 3];
+ if (
+ x1 != head[head.length - 4] ||
+ y1 != head[head.length - 3] ||
+ lineType != head[11]
+ ) {
+ console.log("eror in freeHandMove?", x, y, lineType, head);
+ }
+ }
+ oe.drawLine(oe.canvasCtx[layer], x0, y0, x1, y1, lineType);
+ } else {
+ console.log("error in freeHandMove: called from recorder", head);
+ }
+};
+
+Neo.ActionManager.prototype.line = function (x0, y0, x1, y1, lineType) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("line", layer);
+ this.pushCurrent();
+ this.push(lineType, x0, y0, x1, y1);
+ } else {
+ var item = arguments[0];
+
+ layer = item[1];
+ this.getCurrent(item);
+
+ lineType = item[11];
+ x0 = item[12];
+ y0 = item[13];
+ x1 = item[14];
+ y1 = item[15];
+ }
+ if (x1 === null) x1 = x0;
+ if (y1 === null) y1 = y0;
+
+ oe.drawLine(oe.canvasCtx[layer], x0, y0, x1, y1, lineType);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.bezier = function (
+ x0,
+ y0,
+ x1,
+ y1,
+ x2,
+ y2,
+ x3,
+ y3,
+ lineType
+) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+ var isReplay = true;
+
+ if (typeof arguments[0] != "object") {
+ this.push("bezier", layer);
+ this.pushCurrent();
+ this.push(lineType, x0, y0, x1, y1, x2, y2, x3, y3);
+ isReplay = false;
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ this.getCurrent(item);
+
+ lineType = item[11];
+ x0 = item[12];
+ y0 = item[13];
+ x1 = item[14];
+ y1 = item[15];
+ x2 = item[16];
+ y2 = item[17];
+ x3 = item[18];
+ y3 = item[19];
+ }
+ oe.drawBezier(
+ oe.canvasCtx[layer],
+ x0,
+ y0,
+ x1,
+ y1,
+ x2,
+ y2,
+ x3,
+ y3,
+ lineType,
+ isReplay
+ );
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.fill = function (x, y, width, height, type) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("fill", layer);
+ this.pushCurrent();
+ this.push(x, y, width, height, type);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ this.getCurrent(item);
+
+ x = item[11];
+ y = item[12];
+ width = item[13];
+ height = item[14];
+ type = item[15];
+ }
+
+ oe.doFill(layer, x, y, width, height, type);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.flipH = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("flipH", layer, x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ }
+ oe.flipH(layer, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.flipV = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("flipV", layer, x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ }
+ oe.flipV(layer, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.merge = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("merge", layer, x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ }
+ oe.merge(layer, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.blurRect = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("blurRect", layer, x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ }
+ oe.blurRect(layer, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.eraseRect2 = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("eraseRect2", layer);
+ this.pushCurrent();
+ this.push(x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ this.getCurrent(item);
+
+ x = item[11];
+ y = item[12];
+ width = item[13];
+ height = item[14];
+ }
+ oe.eraseRect(layer, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.eraseRect = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("eraseRect", layer, x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ }
+ oe.eraseRect(layer, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.copy = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("copy", layer, x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ }
+
+ oe.copy(layer, x, y, width, height);
+ oe.tool.x = x;
+ oe.tool.y = y;
+ oe.tool.width = width;
+ oe.tool.height = height;
+ // oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.paste = function (x, y, width, height, dx, dy) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("paste", layer, x, y, width, height, dx, dy);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ dx = item[6];
+ dy = item[7];
+ }
+
+ oe.paste(layer, x, y, width, height, dx, dy);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.turn = function (x, y, width, height) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("turn", layer, x, y, width, height);
+ } else {
+ var item = arguments[0];
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ width = item[4];
+ height = item[5];
+ }
+ oe.turn(layer, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.text = function (
+ x,
+ y,
+ color,
+ alpha,
+ string,
+ size,
+ family
+) {
+ var oe = Neo.painter;
+ var layer = oe.current;
+
+ if (typeof arguments[0] != "object") {
+ this.push("text", layer, x, y, color, alpha, string, size, family);
+ } else {
+ var item = arguments[0];
+
+ layer = item[1];
+ x = item[2];
+ y = item[3];
+ color = item[4];
+ alpha = item[5];
+ string = item[6];
+ size = item[7];
+ family = item[8];
+ }
+ oe.doText(layer, x, y, color, alpha, string, size, family);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+Neo.ActionManager.prototype.restore = function () {
+ var oe = Neo.painter;
+ var width = oe.canvasWidth;
+ var height = oe.canvasHeight;
+
+ if (typeof arguments[0] != "object") {
+ this.push("restore");
+
+ var img0 = oe.canvas[0].toDataURL("image/png");
+ var img1 = oe.canvas[1].toDataURL("image/png");
+ this.push(img0, img1);
+ } else {
+ var item = arguments[0];
+ var callback = arguments[1];
+
+ var img0 = new Image();
+ img0.src = item[1];
+ img0.onload = function () {
+ var img1 = new Image();
+ img1.src = item[2];
+ img1.onload = function () {
+ oe.canvasCtx[0].clearRect(0, 0, width, height);
+ oe.canvasCtx[1].clearRect(0, 0, width, height);
+ oe.canvasCtx[0].drawImage(img0, 0, 0);
+ oe.canvasCtx[1].drawImage(img1, 0, 0);
+ oe.updateDestCanvas(0, 0, width, height);
+
+ if (callback && typeof callback == "function") callback(true);
+ };
+ };
+ }
+};
+
+Neo.ActionManager.prototype.dummy = function () {
+ var callback = arguments[1];
+ if (callback && typeof callback == "function") callback(true);
+};
+
+/*
+ -----------------------------------------------------------------------
+ 動画表示モード
+ -----------------------------------------------------------------------
+*/
+
+Neo.createViewer = function (applet) {
+ var neo = document.createElement("div");
+ neo.className = "NEO";
+ neo.id = "NEO";
+
+ var html =
+ '<div id="pageView" style="margin:auto;">' +
+ '<div id="container" style="visibility:visible;" class="o">' +
+ '<div id="painter" style="background-color:white;">' +
+ '<div id="canvas" style="background-color:white;">' +
+ "</div>" +
+ "</div>" +
+ '<div id="viewerButtonsWrapper" style="display:block;">' +
+ '<div id="viewerButtons" style="display:block;">' +
+ '<div id="viewerPlay"></div>' +
+ '<div id="viewerStop"></div>' +
+ '<div id="viewerRewind"></div>' +
+ '<div id="viewerSpeed" style="padding-left:2px; margin-top: 1px;"></div>' +
+ '<div id="viewerPlus"></div>' +
+ '<div id="viewerMinus"></div>' +
+ '<div id="viewerBar" style="display:inline-block;">' +
+ "</div>" +
+ "</div>" +
+ "</div>" +
+ "</div>";
+
+ 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);
+};
+
+Neo.initViewer = function (pch) {
+ var pageview = document.getElementById("pageView");
+ var pageWidth = Neo.config.applet_width;
+ var pageHeight = Neo.config.applet_height;
+ pageview.style.width = pageWidth + "px";
+ pageview.style.height = pageHeight + "px";
+
+ Neo.canvas = document.getElementById("canvas");
+ Neo.container = document.getElementById("container");
+ Neo.container.style.backgroundColor = Neo.config.color_back;
+ Neo.container.style.border = "0";
+
+ var dx = (pageWidth - Neo.config.width) / 2;
+ var dy = (pageHeight - Neo.config.height - 26) / 2;
+
+ var painter = document.getElementById("painter");
+
+ painter.style.marginTop = "0";
+ painter.style.position = "absolute";
+ painter.style.padding = "0";
+ painter.style.bottom = dy + 26 + "px";
+ painter.style.left = dx + "px";
+
+ var viewerButtonsWrapper = document.getElementById("viewerButtonsWrapper");
+ viewerButtonsWrapper.style.width = pageWidth - 2 + "px";
+
+ var viewerBar = document.getElementById("viewerBar");
+ viewerBar.style.position = "absolute";
+ viewerBar.style.right = "2px";
+ viewerBar.style.top = "1px";
+ viewerBar.style.width = pageWidth - 24 * 6 - 2 + "px";
+
+ Neo.canvas.style.width = Neo.config.width + "px";
+ Neo.canvas.style.height = Neo.config.height + "px";
+
+ Neo.painter = new Neo.Painter();
+ Neo.painter.build(Neo.canvas, Neo.config.width, Neo.config.height);
+
+ Neo.container.oncontextmenu = function () {
+ return false;
+ };
+
+ painter.addEventListener(
+ "mousedown",
+ function () {
+ Neo.painter._actionMgr.isMouseDown = true;
+ },
+ false
+ );
+
+ document.addEventListener(
+ "mousemove",
+ function (e) {
+ if (Neo.painter._actionMgr.isMouseDown) {
+ var zoom = Neo.painter.zoom;
+ var x = Neo.painter.zoomX - e.movementX / zoom;
+ var y = Neo.painter.zoomY - e.movementY / zoom;
+ Neo.painter.setZoomPosition(x, y);
+ }
+ },
+ false
+ );
+ document.addEventListener(
+ "mouseup",
+ function () {
+ Neo.painter._actionMgr.isMouseDown = false;
+ Neo.viewerBar.isMouseDown = false;
+ },
+ false
+ );
+
+ if (pch) {
+ //Neo.config.pch_file) {
+ Neo.painter._actionMgr._items = pch.data;
+ Neo.painter.play();
+ }
+};
+
+Neo.startViewer = function () {
+ if (Neo.applet) {
+ var name = Neo.applet.attributes.name.value || "pch";
+ if (!document[name]) document[name] = Neo;
+ if (Neo.applet.parentNode) {
+ Neo.applet.parentNode.removeChild(Neo.applet);
+ }
+ }
+
+ Neo.styleSheet = Neo.getStyleSheet();
+ var lightBack = Neo.multColor(Neo.config.color_back, 1.3);
+ var darkBack = Neo.multColor(Neo.config.color_back, 0.7);
+
+ Neo.addRule(".NEO #viewerButtons", "color", Neo.config.color_text);
+ Neo.addRule(".NEO #viewerButtons", "background-color", Neo.config.color_back);
+
+ Neo.addRule(
+ ".NEO #viewerButtonsWrapper",
+ "border",
+ "1px solid " + Neo.config.color_frame + " !important"
+ );
+
+ Neo.addRule(
+ ".NEO #viewerButtons",
+ "border",
+ "1px solid " + Neo.config.color_back + " !important"
+ );
+ Neo.addRule(
+ ".NEO #viewerButtons",
+ "border-left",
+ "1px solid " + lightBack + " !important"
+ );
+ Neo.addRule(
+ ".NEO #viewerButtons",
+ "border-top",
+ "1px solid " + lightBack + " !important"
+ );
+
+ Neo.addRule(
+ ".NEO #viewerButtons >div.buttonOff",
+ "background-color",
+ Neo.config.color_icon + " !important"
+ );
+
+ Neo.addRule(
+ ".NEO #viewerButtons >div.buttonOff:active",
+ "background-color",
+ darkBack + " !important"
+ );
+ Neo.addRule(
+ ".NEO #viewerButtons >div.buttonOn",
+ "background-color",
+ darkBack + " !important"
+ );
+
+ Neo.addRule(
+ ".NEO #viewerButtons >div",
+ "border",
+ "1px solid " + Neo.config.color_frame + " !important"
+ );
+
+ Neo.addRule(
+ ".NEO #viewerButtons >div.buttonOff:hover",
+ "border",
+ "1px solid" + Neo.config.color_bar_select + " !important"
+ );
+
+ Neo.addRule(
+ ".NEO #viewerButtons >div.buttonOff:active",
+ "border",
+ "1px solid" + Neo.config.color_bar_select + " !important"
+ );
+ Neo.addRule(
+ ".NEO #viewerButtons >div.buttonOn",
+ "border",
+ "1px solid" + Neo.config.color_bar_select + " !important"
+ );
+
+ Neo.addRule(".NEO #viewerBar >div", "background-color", Neo.config.color_bar);
+ // Neo.addRule(".NEO #viewerBar:active", "background-color", darkBack);
+ Neo.addRule(
+ ".NEO #viewerBarMark",
+ "background-color",
+ Neo.config.color_text + " !important"
+ );
+
+ setTimeout(function () {
+ Neo.viewerPlay = new Neo.ViewerButton().init("viewerPlay");
+ Neo.viewerPlay.setSelected(true);
+ Neo.viewerPlay.onmouseup = function () {
+ Neo.painter.onplay();
+ };
+ Neo.viewerStop = new Neo.ViewerButton().init("viewerStop");
+ Neo.viewerStop.onmouseup = function () {
+ Neo.painter.onstop();
+ };
+ Neo.viewerSpeed = new Neo.ViewerButton().init("viewerSpeed");
+ Neo.viewerSpeed.onmouseup = function () {
+ Neo.painter.onspeed();
+ this.update();
+ };
+
+ new Neo.ViewerButton().init("viewerRewind").onmouseup = function () {
+ Neo.painter.onrewind();
+ };
+ new Neo.ViewerButton().init("viewerPlus").onmouseup = function () {
+ new Neo.ZoomPlusCommand(Neo.painter).execute();
+ };
+ new Neo.ViewerButton().init("viewerMinus").onmouseup = function () {
+ new Neo.ZoomMinusCommand(Neo.painter).execute();
+ };
+
+ var length = Neo.painter._actionMgr._items.length;
+ Neo.viewerBar = new Neo.ViewerBar().init("viewerBar", { length: length });
+ }, 0);
+};
+
+Neo.getFilename = function () {
+ return Neo.config.pch_file || Neo.config.image_canvas;
+};
+
+Neo.getPCH = function (filename, callback) {
+ if (!filename || filename.slice(-4).toLowerCase() != ".pch") return null;
+
+ var request = new XMLHttpRequest();
+ request.open("GET", filename, true);
+ request.responseType = "arraybuffer";
+ request.onload = function () {
+ var pch = Neo.decodePCH(request.response);
+ if (pch) {
+ if (callback) callback(pch);
+ } else {
+ console.log("not a NEO animation");
+ }
+ };
+ request.send();
+};
+
+Neo.decodePCH = function (rawdata) {
+ var byteArray = new Uint8Array(rawdata);
+ var data = LZString.decompressFromUint8Array(byteArray.subarray(12));
+ var header = byteArray.subarray(0, 12);
+
+ if (
+ header[0] == "N".charCodeAt(0) &&
+ header[1] == "E".charCodeAt(0) &&
+ header[2] == "O".charCodeAt(0)
+ ) {
+ var width = header[4] + header[5] * 0x100;
+ var height = header[6] + header[7] * 0x100;
+ var items = Neo.fixPCH(JSON.parse(data));
+ return {
+ width: width,
+ height: height,
+ data: items,
+ };
+ } else {
+ return null;
+ }
+};
+
+Neo.fixPCH = function (items) {
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+
+ var index = item.indexOf("eraseAll");
+ if (index > 0) {
+ var tmp = item.slice(index);
+ var tmp2 = item.slice(0, index);
+ console.log("fix eraseAll", tmp2, tmp);
+
+ items[i] = tmp2;
+ items.splice(i, 0, tmp);
+ }
+ }
+ return items;
+};
+
+/*
+ -----------------------------------------------------------------------
+ LiveConnect
+ -----------------------------------------------------------------------
+*/
+
+Neo.playPCH = function () {
+ Neo.painter.onplay();
+};
+
+Neo.suspendDraw = function () {
+ Neo.painter.onstop();
+};
+
+Neo.setSpeed = function (value) {
+ Neo.speed = value;
+};
+
+Neo.setVisit = function (layer, value) {
+ Neo.painter.visible[layer] = (value == 0) ? false : true;
+ Neo.painter.updateDestCanvas(
+ 0,
+ 0,
+ Neo.painter.canvasWidth,
+ Neo.painter.canvasHeight);
+};
+
+Neo.setMark = function (value) {
+ Neo.painter._actionMgr._mark = value;
+ Neo.painter.onmark();
+};
+
+Neo.getSeek = function () {
+ return Neo.painter._actionMgr._head;
+};
+
+Neo.getLineCount = function () {
+ return Neo.painter._actionMgr._items.length;
+};
+
+"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";
+
+ this.disable = function(wait) {
+ this.element.style.pointerEvents = "none";
+ this.element.style.opacity = "0.5";
+ if (wait) {
+ setTimeout(function () {
+ ref.enable();
+ }, wait);
+ }
+ }
+
+ this.enable = function() {
+ this.element.style.pointerEvents = "inherit";
+ this.element.style.opacity = "1.0";
+ }
+
+ 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 {
+ Neo.tintImage(ctx, c);
+ }
+ }
+};
+
+Neo.ToolTip.prototype.drawTintImage = function (ctx, img, c, x, y) {
+ ctx.drawImage(img, x, y);
+ Neo.tintImage(ctx, c);
+};
+
+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";
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ ViewerButton
+ -------------------------------------------------------------------------
+*/
+
+Neo.ViewerButton = function () {};
+Neo.ViewerButton.prototype = new Neo.Button();
+
+Neo.ViewerButton.speedStrings = ["最", "早", "既", "鈍"];
+
+Neo.ViewerButton.prototype.init = function (name, params) {
+ Neo.Button.prototype.init.call(this, name, params);
+
+ if (name != "viewerSpeed") {
+ this.element.innerHTML = "<canvas width=24 height=24></canvas>";
+ this.canvas = this.element.getElementsByTagName("canvas")[0];
+ var ctx = this.canvas.getContext("2d");
+
+ var img = new Image();
+ img.src = Neo.ViewerButton[name.toLowerCase().replace(/viewer/, "")];
+ img.onload = function () {
+ var ref = this;
+ ctx.clearRect(0, 0, 24, 24);
+ ctx.drawImage(img, 0, 0);
+ Neo.tintImage(ctx, Neo.config.color_text);
+ }.bind(this);
+ } else {
+ this.element.innerHTML = "<div></div><canvas width=24 height=24></canvas>";
+ this.update();
+ }
+ return this;
+};
+
+Neo.ViewerButton.prototype.update = function () {
+ if (this.name == "viewerSpeed") {
+ var mode = Neo.painter._actionMgr.speedMode();
+ var speedString = Neo.translate(Neo.ViewerButton.speedStrings[mode]);
+ this.element.children[0].innerHTML = "<div>" + speedString + "</div>";
+ }
+};
+
+Neo.ViewerButton.minus =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEX/////HgA/G9hMAAAAAXRSTlMAQObYZgAAABFJREFUCNdjYMAG5H+AEDYAADOnAi81ABEKAAAAAElFTkSuQmCC";
+
+Neo.ViewerButton.plus =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEX/////HgD/HgAvnCBAAAAAAnRSTlMAAHaTzTgAAAAfSURBVAjXY2BAA0wTMAimVasaIARj2FQHCIGkBAUAAGm3CXHeKF1tAAAAAElFTkSuQmCC";
+
+Neo.ViewerButton.play =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEX/////HgD/HgAvnCBAAAAAAnRSTlMAAHaTzTgAAAAuSURBVAjXY2BAABUQoQkitBxAxAQQsQRErAQRq+CspSBiKogIAekIABKqDhAzAAuwB6SsnxQ6AAAAAElFTkSuQmCC";
+
+Neo.ViewerButton.stop =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEX/////HgA/G9hMAAAAAXRSTlMAQObYZgAAABFJREFUCNdjYIAB+x8EEBgAACjyDV75Mi9xAAAAAElFTkSuQmCC";
+
+Neo.ViewerButton.rewind =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEX/////HgA/G9hMAAAAAXRSTlMAQObYZgAAACxJREFUCNdjYAADJiYGNjYGPj4GOTkGOzuGujqGf/9AJJANFAGKA2WBahgYAIE2Bb0RIYJRAAAAAElFTkSuQmCC";
+
+/*
+ -------------------------------------------------------------------------
+ ViewerBar
+ -------------------------------------------------------------------------
+*/
+
+// length/mark/count
+// update
+
+Neo.ViewerBar = function () {};
+Neo.ViewerBar.prototype.init = function (name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+
+ this.element.style.display = "inline-block";
+ this.element.innerHTML =
+ "<div id='viewerBarLeft'></div>" +
+ "<div id='viewerBarMark'></div>" +
+ "<div id='viewerBarText'>hoge</div>";
+ this.seekElement = this.element.children[0];
+ this.markElement = this.element.children[1];
+ this.textElement = this.element.children[2];
+
+ this.width = this.seekElement.offsetWidth;
+
+ this.length = this.params.length || 100;
+ this.mark = this.length;
+ this.seek = 0;
+
+ var ref = this;
+ this.element.onmousedown = function (e) {
+ ref.isMouseDown = true;
+ ref._touchHandler(e);
+ };
+ this.element.onmousemove = function (e) {
+ if (ref.isMouseDown) {
+ ref._touchHandler(e);
+ }
+ };
+ // this.element.onmouseup = function(e) { this.isMouseDown = false; }
+ // this.element.onmouseout = function(e) { this.isMouseDown = false; }
+ this.element.addEventListener(
+ "touchstart",
+ function (e) {
+ ref._touchHandler(e);
+ e.preventDefault();
+ },
+ true
+ );
+
+ this.update();
+ return this;
+};
+
+Neo.ViewerBar.prototype.update = function () {
+ this.mark = Neo.painter._actionMgr._mark;
+ this.seek = Neo.painter._actionMgr._head;
+
+ var markX = (this.mark / this.length) * this.width;
+ this.markElement.style.left = markX + "px";
+
+ var seekX = (this.seek / this.length) * this.width;
+ this.seekElement.style.width = seekX + "px";
+ this.textElement.innerHTML = this.seek + "/" + this.length;
+};
+
+Neo.ViewerBar.prototype._touchHandler = function (e) {
+ var x = e.offsetX / this.width;
+ x = Math.max(Math.min(x, 1), 0);
+
+ Neo.painter._actionMgr._mark = Math.round(x * this.length);
+ //this.update();
+ // console.log('mark=', this.mark, 'head=', Neo.painter._actionMgr._head);
+
+ Neo.painter.onmark();
+};
+
+// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
+// This work is free. You can redistribute it and/or modify it
+// under the terms of the WTFPL, Version 2
+// For more information see LICENSE.txt or http://www.wtfpl.net/
+//
+// For more information, the home page:
+// http://pieroxy.net/blog/pages/lz-string/testing.html
+//
+// LZ-based compression algorithm, version 1.4.4
+var LZString = (function() {
+
+// private property
+var f = String.fromCharCode;
+var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
+var baseReverseDic = {};
+
+function getBaseValue(alphabet, character) {
+ if (!baseReverseDic[alphabet]) {
+ baseReverseDic[alphabet] = {};
+ for (var i=0 ; i<alphabet.length ; i++) {
+ baseReverseDic[alphabet][alphabet.charAt(i)] = i;
+ }
+ }
+ return baseReverseDic[alphabet][character];
+}
+
+var LZString = {
+ compressToBase64 : function (input) {
+ if (input == null) return "";
+ var res = LZString._compress(input, 6, function(a){return keyStrBase64.charAt(a);});
+ switch (res.length % 4) { // To produce valid Base64
+ default: // When could this happen ?
+ case 0 : return res;
+ case 1 : return res+"===";
+ case 2 : return res+"==";
+ case 3 : return res+"=";
+ }
+ },
+
+ decompressFromBase64 : function (input) {
+ if (input == null) return "";
+ if (input == "") return null;
+ return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrBase64, input.charAt(index)); });
+ },
+
+ compressToUTF16 : function (input) {
+ if (input == null) return "";
+ return LZString._compress(input, 15, function(a){return f(a+32);}) + " ";
+ },
+
+ decompressFromUTF16: function (compressed) {
+ if (compressed == null) return "";
+ if (compressed == "") return null;
+ return LZString._decompress(compressed.length, 16384, function(index) { return compressed.charCodeAt(index) - 32; });
+ },
+
+ //compress into uint8array (UCS-2 big endian format)
+ compressToUint8Array: function (uncompressed) {
+ var compressed = LZString.compress(uncompressed);
+ var buf=new Uint8Array(compressed.length*2); // 2 bytes per character
+
+ for (var i=0, TotalLen=compressed.length; i<TotalLen; i++) {
+ var current_value = compressed.charCodeAt(i);
+ buf[i*2] = current_value >>> 8;
+ buf[i*2+1] = current_value % 256;
+ }
+ return buf;
+ },
+
+ //decompress from uint8array (UCS-2 big endian format)
+ decompressFromUint8Array:function (compressed) {
+ if (compressed===null || compressed===undefined){
+ return LZString.decompress(compressed);
+ } else {
+ var buf=new Array(compressed.length/2); // 2 bytes per character
+ for (var i=0, TotalLen=buf.length; i<TotalLen; i++) {
+ buf[i]=compressed[i*2]*256+compressed[i*2+1];
+ }
+
+ var result = [];
+ buf.forEach(function (c) {
+ result.push(f(c));
+ });
+ return LZString.decompress(result.join(''));
+
+ }
+
+ },
+
+
+ //compress into a string that is already URI encoded
+ compressToEncodedURIComponent: function (input) {
+ if (input == null) return "";
+ return LZString._compress(input, 6, function(a){return keyStrUriSafe.charAt(a);});
+ },
+
+ //decompress from an output of compressToEncodedURIComponent
+ decompressFromEncodedURIComponent:function (input) {
+ if (input == null) return "";
+ if (input == "") return null;
+ input = input.replace(/ /g, "+");
+ return LZString._decompress(input.length, 32, function(index) { return getBaseValue(keyStrUriSafe, input.charAt(index)); });
+ },
+
+ compress: function (uncompressed) {
+ return LZString._compress(uncompressed, 16, function(a){return f(a);});
+ },
+ _compress: function (uncompressed, bitsPerChar, getCharFromInt) {
+ if (uncompressed == null) return "";
+ var i, value,
+ context_dictionary= {},
+ context_dictionaryToCreate= {},
+ context_c="",
+ context_wc="",
+ context_w="",
+ context_enlargeIn= 2, // Compensate for the first entry which should not count
+ context_dictSize= 3,
+ context_numBits= 2,
+ context_data=[],
+ context_data_val=0,
+ context_data_position=0,
+ ii;
+
+ for (ii = 0; ii < uncompressed.length; ii += 1) {
+ context_c = uncompressed.charAt(ii);
+ if (!Object.prototype.hasOwnProperty.call(context_dictionary,context_c)) {
+ context_dictionary[context_c] = context_dictSize++;
+ context_dictionaryToCreate[context_c] = true;
+ }
+
+ context_wc = context_w + context_c;
+ if (Object.prototype.hasOwnProperty.call(context_dictionary,context_wc)) {
+ context_w = context_wc;
+ } else {
+ if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
+ if (context_w.charCodeAt(0)<256) {
+ for (i=0 ; i<context_numBits ; i++) {
+ context_data_val = (context_data_val << 1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ }
+ value = context_w.charCodeAt(0);
+ for (i=0 ; i<8 ; i++) {
+ context_data_val = (context_data_val << 1) | (value&1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = value >> 1;
+ }
+ } else {
+ value = 1;
+ for (i=0 ; i<context_numBits ; i++) {
+ context_data_val = (context_data_val << 1) | value;
+ if (context_data_position ==bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = 0;
+ }
+ value = context_w.charCodeAt(0);
+ for (i=0 ; i<16 ; i++) {
+ context_data_val = (context_data_val << 1) | (value&1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = value >> 1;
+ }
+ }
+ context_enlargeIn--;
+ if (context_enlargeIn == 0) {
+ context_enlargeIn = Math.pow(2, context_numBits);
+ context_numBits++;
+ }
+ delete context_dictionaryToCreate[context_w];
+ } else {
+ value = context_dictionary[context_w];
+ for (i=0 ; i<context_numBits ; i++) {
+ context_data_val = (context_data_val << 1) | (value&1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = value >> 1;
+ }
+
+
+ }
+ context_enlargeIn--;
+ if (context_enlargeIn == 0) {
+ context_enlargeIn = Math.pow(2, context_numBits);
+ context_numBits++;
+ }
+ // Add wc to the dictionary.
+ context_dictionary[context_wc] = context_dictSize++;
+ context_w = String(context_c);
+ }
+ }
+
+ // Output the code for w.
+ if (context_w !== "") {
+ if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate,context_w)) {
+ if (context_w.charCodeAt(0)<256) {
+ for (i=0 ; i<context_numBits ; i++) {
+ context_data_val = (context_data_val << 1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ }
+ value = context_w.charCodeAt(0);
+ for (i=0 ; i<8 ; i++) {
+ context_data_val = (context_data_val << 1) | (value&1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = value >> 1;
+ }
+ } else {
+ value = 1;
+ for (i=0 ; i<context_numBits ; i++) {
+ context_data_val = (context_data_val << 1) | value;
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = 0;
+ }
+ value = context_w.charCodeAt(0);
+ for (i=0 ; i<16 ; i++) {
+ context_data_val = (context_data_val << 1) | (value&1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = value >> 1;
+ }
+ }
+ context_enlargeIn--;
+ if (context_enlargeIn == 0) {
+ context_enlargeIn = Math.pow(2, context_numBits);
+ context_numBits++;
+ }
+ delete context_dictionaryToCreate[context_w];
+ } else {
+ value = context_dictionary[context_w];
+ for (i=0 ; i<context_numBits ; i++) {
+ context_data_val = (context_data_val << 1) | (value&1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = value >> 1;
+ }
+
+
+ }
+ context_enlargeIn--;
+ if (context_enlargeIn == 0) {
+ context_enlargeIn = Math.pow(2, context_numBits);
+ context_numBits++;
+ }
+ }
+
+ // Mark the end of the stream
+ value = 2;
+ for (i=0 ; i<context_numBits ; i++) {
+ context_data_val = (context_data_val << 1) | (value&1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data_position = 0;
+ context_data.push(getCharFromInt(context_data_val));
+ context_data_val = 0;
+ } else {
+ context_data_position++;
+ }
+ value = value >> 1;
+ }
+
+ // Flush the last char
+ while (true) {
+ context_data_val = (context_data_val << 1);
+ if (context_data_position == bitsPerChar-1) {
+ context_data.push(getCharFromInt(context_data_val));
+ break;
+ }
+ else context_data_position++;
+ }
+ return context_data.join('');
+ },
+
+ decompress: function (compressed) {
+ if (compressed == null) return "";
+ if (compressed == "") return null;
+ return LZString._decompress(compressed.length, 32768, function(index) { return compressed.charCodeAt(index); });
+ },
+
+ _decompress: function (length, resetValue, getNextValue) {
+ var dictionary = [],
+ next,
+ enlargeIn = 4,
+ dictSize = 4,
+ numBits = 3,
+ entry = "",
+ result = [],
+ i,
+ w,
+ bits, resb, maxpower, power,
+ c,
+ data = {val:getNextValue(0), position:resetValue, index:1};
+
+ for (i = 0; i < 3; i += 1) {
+ dictionary[i] = i;
+ }
+
+ bits = 0;
+ maxpower = Math.pow(2,2);
+ power=1;
+ while (power!=maxpower) {
+ resb = data.val & data.position;
+ data.position >>= 1;
+ if (data.position == 0) {
+ data.position = resetValue;
+ data.val = getNextValue(data.index++);
+ }
+ bits |= (resb>0 ? 1 : 0) * power;
+ power <<= 1;
+ }
+
+ switch (next = bits) {
+ case 0:
+ bits = 0;
+ maxpower = Math.pow(2,8);
+ power=1;
+ while (power!=maxpower) {
+ resb = data.val & data.position;
+ data.position >>= 1;
+ if (data.position == 0) {
+ data.position = resetValue;
+ data.val = getNextValue(data.index++);
+ }
+ bits |= (resb>0 ? 1 : 0) * power;
+ power <<= 1;
+ }
+ c = f(bits);
+ break;
+ case 1:
+ bits = 0;
+ maxpower = Math.pow(2,16);
+ power=1;
+ while (power!=maxpower) {
+ resb = data.val & data.position;
+ data.position >>= 1;
+ if (data.position == 0) {
+ data.position = resetValue;
+ data.val = getNextValue(data.index++);
+ }
+ bits |= (resb>0 ? 1 : 0) * power;
+ power <<= 1;
+ }
+ c = f(bits);
+ break;
+ case 2:
+ return "";
+ }
+ dictionary[3] = c;
+ w = c;
+ result.push(c);
+ while (true) {
+ if (data.index > length) {
+ return "";
+ }
+
+ bits = 0;
+ maxpower = Math.pow(2,numBits);
+ power=1;
+ while (power!=maxpower) {
+ resb = data.val & data.position;
+ data.position >>= 1;
+ if (data.position == 0) {
+ data.position = resetValue;
+ data.val = getNextValue(data.index++);
+ }
+ bits |= (resb>0 ? 1 : 0) * power;
+ power <<= 1;
+ }
+
+ switch (c = bits) {
+ case 0:
+ bits = 0;
+ maxpower = Math.pow(2,8);
+ power=1;
+ while (power!=maxpower) {
+ resb = data.val & data.position;
+ data.position >>= 1;
+ if (data.position == 0) {
+ data.position = resetValue;
+ data.val = getNextValue(data.index++);
+ }
+ bits |= (resb>0 ? 1 : 0) * power;
+ power <<= 1;
+ }
+
+ dictionary[dictSize++] = f(bits);
+ c = dictSize-1;
+ enlargeIn--;
+ break;
+ case 1:
+ bits = 0;
+ maxpower = Math.pow(2,16);
+ power=1;
+ while (power!=maxpower) {
+ resb = data.val & data.position;
+ data.position >>= 1;
+ if (data.position == 0) {
+ data.position = resetValue;
+ data.val = getNextValue(data.index++);
+ }
+ bits |= (resb>0 ? 1 : 0) * power;
+ power <<= 1;
+ }
+ dictionary[dictSize++] = f(bits);
+ c = dictSize-1;
+ enlargeIn--;
+ break;
+ case 2:
+ return result.join('');
+ }
+
+ if (enlargeIn == 0) {
+ enlargeIn = Math.pow(2, numBits);
+ numBits++;
+ }
+
+ if (dictionary[c]) {
+ entry = dictionary[c];
+ } else {
+ if (c === dictSize) {
+ entry = w + w.charAt(0);
+ } else {
+ return null;
+ }
+ }
+ result.push(entry);
+
+ // Add w+entry[0] to the dictionary.
+ dictionary[dictSize++] = w + entry.charAt(0);
+ enlargeIn--;
+
+ w = entry;
+
+ if (enlargeIn == 0) {
+ enlargeIn = Math.pow(2, numBits);
+ numBits++;
+ }
+
+ }
+ }
+};
+ return LZString;
+})();
+
+if (typeof define === 'function' && define.amd) {
+ define(function () { return LZString; });
+} else if( typeof module !== 'undefined' && module != null ) {
+ module.exports = LZString
+} else if( typeof angular !== 'undefined' && angular != null ) {
+ angular.module('LZString', [])
+ .factory('LZString', function () {
+ return LZString;
+ });
+}
diff --git a/static/js/shobon.js b/static/js/shobon.js
index d4b345c..c710bac 100644
--- a/static/js/shobon.js
+++ b/static/js/shobon.js
@@ -75,6 +75,7 @@ function shobon() {
for (var e = 0; e < replyList.length; e++) {
var reply = replyList[e];
var message = reply.getElementsByClassName("msg")[0];
+ var id = 0;
if (shobon_time != "false") {
var date = reply.getElementsByClassName("date")[0];
@@ -82,7 +83,7 @@ function shobon() {
this.title = "Hace " + timeAgo(this.dataset.unix);
});
if (date.textContent.includes("ID:"))
- var id = date.textContent.split(" ")[1];
+ id = date.textContent.split(" ")[1];
date.textContent = localTime(date.dataset.unix, id);
}