// ==UserScript==
// @name Colourful LOR
// @namespace com.bodqhrohro.lor.colourful
// @description Improve LOR with colourful pixel art!
// @include https://www.linux.org.ru/*
// @version 1
// @grant none
// ==/UserScript==
(function() {
var forthMap = {
3: 8,
4: 3,
5: 6,
6: 9,
7: 13,
8: 4,
9: 5,
10: 7,
11: 12,
12: 10,
13: 11
}
var backMap = {
3: 4,
4: 8,
5: 9,
6: 5,
7: 10,
8: 3,
9: 6,
10: 12,
11: 13,
12: 11,
13: 7
}
var braileRegex = /^[⠀-⣿]+$/m
var PIXEL_SCALE = 8
var reduceByte = function(byte) {
byte = (byte>>3) & 15
return byte < 3 || byte > 13 ? byte : forthMap[byte]
}
var enduceByte = function(byte) {
byte = byte < 3 || byte > 13 ? byte : backMap[byte]
return byte << 3
}
var bytesToBraile = function(byte1, byte2) {
byte1 = reduceByte(byte1)
byte2 = reduceByte(byte2)
return String.fromCharCode(0x2800 + ((byte2&8)<<4) + ((byte1&8)<<3) + ((byte2&7)<<3) + (byte1&7))
}
var braileToBytes = function(symbol) {
symbol = symbol.charCodeAt(0) - 0x2800
byte1 = (symbol&7) + ((symbol&64)>>3)
byte2 = ((symbol&56)>>3) + ((symbol&128)>>4)
return [
enduceByte(byte1),
enduceByte(byte2)
]
}
var insertText = function(textarea, text) {
var startPos = textarea.selectionStart
var endPos = textarea.selectionEnd
textarea.value = textarea.value.substring(0, startPos) +
'\n\n' + text + '\n\n' +
textarea.value.substring(endPos, textarea.value.length)
textarea.selectionStart = startPos + text.length
textarea.selectionEnd = startPos + text.length
}
var encodeImage = function(img) {
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
var imageData = ctx.getImageData(0, 0, img.width, img.height).data
var text = ''
var bytesWidth = img.width * 4
var r, g, b, a;
for (var i = 0; i < imageData.length; i += 4) {
r = imageData[i];
g = imageData[i+1];
b = imageData[i+2];
a = imageData[i+3];
// alpha subcarrier
a &= 128
a >>= 4
a |= (r & 128) >> 1
a |= (g & 128) >> 2
a |= (b & 128) >> 3
if (!(i % bytesWidth)) {
text += '[br]\n'
}
text += bytesToBraile(r, g)
text += bytesToBraile(b, a)
}
return text
}
var assignFileInputs = function(textarea) {
var fileInput = document.createElement('input')
fileInput.type = 'file'
textarea.parentNode.insertBefore(fileInput, textarea.nextSibling)
fileInput.addEventListener('change', function() {
if (!FileReader || !this.files.length) {
return ''
}
var fileReader = new FileReader()
fileReader.onload = function() {
var img = document.createElement('img')
document.body.appendChild(img)
img.style.display = 'none'
img.src = fileReader.result
img.onload = function() {
var text = encodeImage(img)
insertText(textarea, text)
img.parentNode.removeChild(img)
}
}
fileReader.readAsDataURL(this.files[0])
})
// description
var description = document.createElement('div')
description.innerHTML = 'Картинка для Colourful:'
textarea.parentNode.insertBefore(description, fileInput)
}
var decodeImage = function(p) {
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
lines = p.innerText.split('\n').filter(function(line) { return line !== ''; })
canvas.width = Math.max.apply(null, Array.prototype.map.call(lines, function(line) {
return line.length / 2;
})) * PIXEL_SCALE
canvas.height = lines.length * PIXEL_SCALE
lines.forEach(function(line, lineIndex) {
for (var i = 0; i < line.length; i += 2) {
var rg = line[i]
var ba = line[i+1]
rg = braileToBytes(rg)
ba = braileToBytes(ba)
var r = rg[0]
var g = rg[1]
var b = ba[0]
var a = ba[1]
ctx.beginPath()
ctx.rect(i * PIXEL_SCALE / 2, lineIndex * PIXEL_SCALE, PIXEL_SCALE, PIXEL_SCALE)
ctx.fillStyle = 'rgba(' + [r, g, b, a].join(',') + ')'
ctx.fill()
}
})
p.innerHTML = ''
p.appendChild(canvas)
}
var decodeImages = function(message) {
var ps = message.querySelectorAll('p')
if (ps && ps.length) {
Array.prototype.forEach.call(ps, function(p) {
if (braileRegex.test(p.innerText)) {
decodeImage(p)
}
})
}
}
window.addEventListener('load', function() {
// encode
var textareas = document.getElementsByTagName('textarea')
if (textareas && textareas.length) {
Array.prototype.forEach.call(textareas, assignFileInputs)
}
//decode
var messages = document.querySelectorAll('.msg_body')
if (messages && messages.length) {
Array.prototype.forEach.call(messages, decodeImages)
}
})
})()