Rendering support for fucking W I D E characters

This commit is contained in:
IgorTimofeev 2023-10-08 19:09:42 +03:00
parent a575a74b8d
commit cdbb421e7e
3 changed files with 271 additions and 98 deletions

View File

@ -131,7 +131,7 @@ for i = 1, #modules do
object.draw = moduleDraw object.draw = moduleDraw
object.eventHandler = moduleEventHandler object.eventHandler = moduleEventHandler
leftPanel.width = math.max(leftPanel.width, unicode.len(result.name) + 14) leftPanel.width = math.max(leftPanel.width, unicode.wlen(result.name) + 14)
else else
error("Failed to execute module " .. modules[i] .. ": " .. tostring(result)) error("Failed to execute module " .. modules[i] .. ": " .. tostring(result))
end end

View File

@ -550,7 +550,7 @@ local function pressableDraw(pressable)
screen.drawRectangle(pressable.x, pressable.y, pressable.width, pressable.height, background, text, " ") screen.drawRectangle(pressable.x, pressable.y, pressable.width, pressable.height, background, text, " ")
end end
screen.drawText(math.floor(pressable.x + pressable.width / 2 - unicode.len(pressable.text) / 2), math.floor(pressable.y + pressable.height / 2), text, pressable.text) screen.drawText(math.floor(pressable.x + pressable.width / 2 - unicode.wlen(pressable.text) / 2), math.floor(pressable.y + pressable.height / 2), text, pressable.text)
end end
local function pressableHandlePress(workspace, pressable, ...) local function pressableHandlePress(workspace, pressable, ...)
@ -672,7 +672,7 @@ local function buttonGetColors(button)
end end
local function buttonDrawText(button, textColor) local function buttonDrawText(button, textColor)
screen.drawText(math.floor(button.x + button.width / 2 - unicode.len(button.text) / 2), math.floor(button.y + button.height / 2), textColor, button.text) screen.drawText(math.floor(button.x + button.width / 2 - unicode.wlen(button.text) / 2), math.floor(button.y + button.height / 2), textColor, button.text)
end end
local function buttonDraw(button) local function buttonDraw(button)
@ -741,7 +741,7 @@ local function buttonCreate(x, y, width, height, backgroundColor, textColor, bac
end end
local function adaptiveButtonCreate(x, y, xOffset, yOffset, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text) local function adaptiveButtonCreate(x, y, xOffset, yOffset, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text)
return buttonCreate(x, y, unicode.len(text) + xOffset * 2, yOffset * 2 + 1, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text) return buttonCreate(x, y, unicode.wlen(text) + xOffset * 2, yOffset * 2 + 1, backgroundColor, textColor, backgroundPressedColor, textPressedColor, text)
end end
function GUI.button(...) function GUI.button(...)
@ -848,7 +848,7 @@ local function drawLabel(object)
object.height, object.height,
object.horizontalAlignment, object.horizontalAlignment,
object.verticalAlignment, object.verticalAlignment,
unicode.len(object.text), unicode.wlen(object.text),
1 1
) )
screen.drawText(math.floor(xText), math.floor(yText), object.colors.text, object.text) screen.drawText(math.floor(xText), math.floor(yText), object.colors.text, object.text)
@ -910,7 +910,7 @@ local function drawProgressBar(object)
if object.showValue then if object.showValue then
local stringValue = (object.valuePrefix or "") .. object.value .. (object.valuePostfix or "") local stringValue = (object.valuePrefix or "") .. object.value .. (object.valuePostfix or "")
screen.drawText(math.floor(object.x + object.width / 2 - unicode.len(stringValue) / 2), object.y + 1, object.colors.value, stringValue) screen.drawText(math.floor(object.x + object.width / 2 - unicode.wlen(stringValue) / 2), object.y + 1, object.colors.value, stringValue)
end end
return object return object
@ -1013,7 +1013,7 @@ local function codeViewDraw(codeView)
local y, toLine, colorScheme, patterns = codeView.y, codeView.fromLine + codeView.height - 1, codeView.syntaxColorScheme, codeView.syntaxPatterns local y, toLine, colorScheme, patterns = codeView.y, codeView.fromLine + codeView.height - 1, codeView.syntaxColorScheme, codeView.syntaxPatterns
-- Line numbers bar and code area -- Line numbers bar and code area
codeView.lineNumbersWidth = unicode.len(tostring(toLine)) + 2 codeView.lineNumbersWidth = unicode.wlen(tostring(toLine)) + 2
codeView.codeAreaPosition = codeView.x + codeView.lineNumbersWidth codeView.codeAreaPosition = codeView.x + codeView.lineNumbersWidth
codeView.codeAreaWidth = codeView.width - codeView.lineNumbersWidth codeView.codeAreaWidth = codeView.width - codeView.lineNumbersWidth
@ -1033,7 +1033,7 @@ local function codeViewDraw(codeView)
screen.drawRectangle(codeView.codeAreaPosition, y, codeView.codeAreaWidth, 1, codeView.highlights[line], colorScheme.text, " ") screen.drawRectangle(codeView.codeAreaPosition, y, codeView.codeAreaWidth, 1, codeView.highlights[line], colorScheme.text, " ")
end end
screen.drawText(codeView.codeAreaPosition - unicode.len(text) - 1, y, colorScheme.lineNumbersText, text) screen.drawText(codeView.codeAreaPosition - unicode.wlen(text) - 1, y, colorScheme.lineNumbersText, text)
y = y + 1 y = y + 1
else else
@ -1295,21 +1295,21 @@ local function drawChart(object)
for y = object.y + object.height - 3, object.y + 1, -chartHeight * object.yAxisValueInterval do for y = object.y + object.height - 3, object.y + 1, -chartHeight * object.yAxisValueInterval do
local stringValue = getAxisValue(value, object.yAxisPostfix, object.roundValues) local stringValue = getAxisValue(value, object.yAxisPostfix, object.roundValues)
yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.len(stringValue)) yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.wlen(stringValue))
table.insert(yAxisValues, {y = math.ceil(y), value = stringValue}) table.insert(yAxisValues, {y = math.ceil(y), value = stringValue})
value = value + dy * object.yAxisValueInterval value = value + dy * object.yAxisValueInterval
end end
local stringValue = getAxisValue(yMax, object.yAxisPostfix, object.roundValues) local stringValue = getAxisValue(yMax, object.yAxisPostfix, object.roundValues)
table.insert(yAxisValues, {y = object.y, value = stringValue}) table.insert(yAxisValues, {y = object.y, value = stringValue})
yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.len(stringValue)) yAxisValueMaxWidth = math.max(yAxisValueMaxWidth, unicode.wlen(stringValue))
local chartWidth = object.width - (object.showYAxisValues and yAxisValueMaxWidth + 2 or 0) local chartWidth = object.width - (object.showYAxisValues and yAxisValueMaxWidth + 2 or 0)
local chartX = object.x + object.width - chartWidth local chartX = object.x + object.width - chartWidth
for i = 1, #yAxisValues do for i = 1, #yAxisValues do
if object.showYAxisValues then if object.showYAxisValues then
screen.drawText(chartX - unicode.len(yAxisValues[i].value) - 2, yAxisValues[i].y, object.colors.axisValue, yAxisValues[i].value) screen.drawText(chartX - unicode.wlen(yAxisValues[i].value) - 2, yAxisValues[i].y, object.colors.axisValue, yAxisValues[i].value)
end end
screen.drawText(chartX, yAxisValues[i].y, object.colors.helpers, string.rep("", chartWidth)) screen.drawText(chartX, yAxisValues[i].y, object.colors.helpers, string.rep("", chartWidth))
end end
@ -1319,11 +1319,11 @@ local function drawChart(object)
value = xMin value = xMin
for x = chartX, chartX + chartWidth - 2, chartWidth * object.xAxisValueInterval do for x = chartX, chartX + chartWidth - 2, chartWidth * object.xAxisValueInterval do
local stringValue = getAxisValue(value, object.xAxisPostfix, object.roundValues) local stringValue = getAxisValue(value, object.xAxisPostfix, object.roundValues)
screen.drawText(math.floor(x - unicode.len(stringValue) / 2), object.y + object.height - 1, object.colors.axisValue, stringValue) screen.drawText(math.floor(x - unicode.wlen(stringValue) / 2), object.y + object.height - 1, object.colors.axisValue, stringValue)
value = value + dx * object.xAxisValueInterval value = value + dx * object.xAxisValueInterval
end end
local value = getAxisValue(xMax, object.xAxisPostfix, object.roundValues) local value = getAxisValue(xMax, object.xAxisPostfix, object.roundValues)
screen.drawText(object.x + object.width - unicode.len(value), object.y + object.height - 1, object.colors.axisValue, value) screen.drawText(object.x + object.width - unicode.wlen(value), object.y + object.height - 1, object.colors.axisValue, value)
end end
-- Axis lines -- Axis lines
@ -1418,13 +1418,13 @@ local function sliderDraw(object)
if object.showMaximumAndMinimumValues then if object.showMaximumAndMinimumValues then
local stringMaximumValue, stringMinimumValue = tostring(object.roundValues and math.floor(object.maximumValue) or number.roundToDecimalPlaces(object.maximumValue, 2)), tostring(object.roundValues and math.floor(object.minimumValue) or number.roundToDecimalPlaces(object.minimumValue, 2)) local stringMaximumValue, stringMinimumValue = tostring(object.roundValues and math.floor(object.maximumValue) or number.roundToDecimalPlaces(object.maximumValue, 2)), tostring(object.roundValues and math.floor(object.minimumValue) or number.roundToDecimalPlaces(object.minimumValue, 2))
screen.drawText(object.x - unicode.len(stringMinimumValue) - 1, object.y, object.colors.value, stringMinimumValue) screen.drawText(object.x - unicode.wlen(stringMinimumValue) - 1, object.y, object.colors.value, stringMinimumValue)
screen.drawText(object.x + object.width + 1, object.y, object.colors.value, stringMaximumValue) screen.drawText(object.x + object.width + 1, object.y, object.colors.value, stringMaximumValue)
end end
if object.currentValuePrefix or object.currentValuePostfix then if object.currentValuePrefix or object.currentValuePostfix then
local stringCurrentValue = (object.currentValuePrefix or "") .. (object.roundValues and math.floor(object.value) or number.roundToDecimalPlaces(object.value, 2)) .. (object.currentValuePostfix or "") local stringCurrentValue = (object.currentValuePrefix or "") .. (object.roundValues and math.floor(object.value) or number.roundToDecimalPlaces(object.value, 2)) .. (object.currentValuePostfix or "")
screen.drawText(math.floor(object.x + object.width / 2 - unicode.len(stringCurrentValue) / 2), object.y + 1, object.colors.value, stringCurrentValue) screen.drawText(math.floor(object.x + object.width / 2 - unicode.wlen(stringCurrentValue) / 2), object.y + 1, object.colors.value, stringCurrentValue)
end end
local activeWidth = number.round((object.value - object.minimumValue) / (object.maximumValue - object.minimumValue) * object.width) local activeWidth = number.round((object.value - object.minimumValue) / (object.maximumValue - object.minimumValue) * object.width)
@ -2029,7 +2029,7 @@ end
local function filesystemDialogAddExtensionFilter(filesystemDialog, extension) local function filesystemDialogAddExtensionFilter(filesystemDialog, extension)
filesystemDialog.extensionComboBox:addItem(extension) filesystemDialog.extensionComboBox:addItem(extension)
filesystemDialog.extensionComboBox.width = math.max(filesystemDialog.extensionComboBox.width, unicode.len(extension) + 3) filesystemDialog.extensionComboBox.width = math.max(filesystemDialog.extensionComboBox.width, unicode.wlen(extension) + 3)
filesystemDialog.extensionComboBox.localX = filesystemDialog.cancelButton.localX - filesystemDialog.extensionComboBox.width - 2 filesystemDialog.extensionComboBox.localX = filesystemDialog.cancelButton.localX - filesystemDialog.extensionComboBox.width - 2
filesystemDialog.filesystemTree:addExtensionFilter(extension) filesystemDialog.filesystemTree:addExtensionFilter(extension)
@ -2704,7 +2704,7 @@ local function textBoxDraw(object)
1, 1,
object.horizontalAlignment, object.horizontalAlignment,
object.verticalAlignment, object.verticalAlignment,
unicode.len(line), unicode.wlen(line),
1 1
) )
@ -3611,7 +3611,7 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function textUpdate(object) local function textUpdate(object)
object.width = unicode.len(object.text) object.width = unicode.wlen(object.text)
return object return object
end end
@ -3684,7 +3684,7 @@ local function listUpdate(list)
-- Размеры хуйни -- Размеры хуйни
if list.cells[1][1].direction == GUI.DIRECTION_HORIZONTAL then if list.cells[1][1].direction == GUI.DIRECTION_HORIZONTAL then
if list.offsetMode then if list.offsetMode then
child.width, child.height = list.itemSize * 2 + unicode.len(child.text), list.height child.width, child.height = list.itemSize * 2 + unicode.wlen(child.text), list.height
else else
child.width, child.height = list.itemSize, list.height child.width, child.height = list.itemSize, list.height
end end
@ -3819,7 +3819,7 @@ end
--------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------
local function keyAndValueUpdate(object) local function keyAndValueUpdate(object)
object.keyLength, object.valueLength = unicode.len(object.key), unicode.len(object.value) object.keyLength, object.valueLength = unicode.wlen(object.key), unicode.wlen(object.value)
object.width = object.keyLength + object.valueLength object.width = object.keyLength + object.valueLength
end end
@ -3931,8 +3931,9 @@ local function dropDownMenuItemDraw(item)
end end
screen.drawText(item.x + 1, yText, textColor, item.text) screen.drawText(item.x + 1, yText, textColor, item.text)
if item.shortcut then if item.shortcut then
screen.drawText(item.x + item.width - unicode.len(item.shortcut) - 1, yText, textColor, item.shortcut) screen.drawText(item.x + item.width - unicode.wlen(item.shortcut) - 1, yText, textColor, item.shortcut)
end end
else else
screen.drawText(item.x, yText, item.parent.parent.colors.separator, string.rep("", item.width)) screen.drawText(item.x, yText, item.parent.parent.colors.separator, string.rep("", item.width))
@ -4182,9 +4183,10 @@ local function contextMenuUpdate(menu)
local widestItem, widestShortcut = 0, 0 local widestItem, widestShortcut = 0, 0
for i = 1, #menu.itemsContainer.children do for i = 1, #menu.itemsContainer.children do
if menu.itemsContainer.children[i].type == 1 then if menu.itemsContainer.children[i].type == 1 then
widestItem = math.max(widestItem, unicode.len(menu.itemsContainer.children[i].text)) widestItem = math.max(widestItem, unicode.wlen(menu.itemsContainer.children[i].text))
if menu.itemsContainer.children[i].shortcut then if menu.itemsContainer.children[i].shortcut then
widestShortcut = math.max(widestShortcut, unicode.len(menu.itemsContainer.children[i].shortcut)) widestShortcut = math.max(widestShortcut, unicode.wlen(menu.itemsContainer.children[i].shortcut))
end end
end end
end end
@ -4596,7 +4598,7 @@ local function menuDraw(menu)
end end
local function menuAddItem(menu, text, textColor) local function menuAddItem(menu, text, textColor)
local item = menu:addChild(pressable(1, 1, unicode.len(text) + 2, 1, nil, textColor or menu.colors.default.text, menu.colors.selected.background, menu.colors.selected.text, 0x0, 0x0, text)) local item = menu:addChild(pressable(1, 1, unicode.wlen(text) + 2, 1, nil, textColor or menu.colors.default.text, menu.colors.selected.background, menu.colors.selected.text, 0x0, 0x0, text))
item.eventHandler = pressableEventHandler item.eventHandler = pressableEventHandler
return item return item

View File

@ -22,16 +22,18 @@ local
unicodeLen, unicodeLen,
unicodeSub, unicodeSub,
unicodeWlen,
unicodeWlenCache,
bufferWidth, bufferWidth,
bufferHeight, bufferHeight,
currentFrameBackgrounds, currentFrameBackgrounds,
currentFrameForegrounds, currentFrameForegrounds,
currentFrameSymbols, currentFrameChars,
newFrameBackgrounds, newFrameBackgrounds,
newFrameForegrounds, newFrameForegrounds,
newFrameSymbols, newFrameChars,
drawLimitX1, drawLimitX1,
drawLimitX2, drawLimitX2,
@ -56,7 +58,9 @@ local
color.integerToRGB, color.integerToRGB,
unicode.len, unicode.len,
unicode.sub; unicode.sub,
unicode.wlen,
{};
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -65,11 +69,11 @@ local function getIndex(x, y)
end end
local function getCurrentFrameTables() local function getCurrentFrameTables()
return currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols return currentFrameBackgrounds, currentFrameForegrounds, currentFrameChars
end end
local function getNewFrameTables() local function getNewFrameTables()
return newFrameBackgrounds, newFrameForegrounds, newFrameSymbols return newFrameBackgrounds, newFrameForegrounds, newFrameChars
end end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -93,7 +97,7 @@ local function flush(width, height)
width, height = componentInvoke(GPUAddress, "getResolution") width, height = componentInvoke(GPUAddress, "getResolution")
end end
currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols, newFrameBackgrounds, newFrameForegrounds, newFrameSymbols = {}, {}, {}, {}, {}, {} currentFrameBackgrounds, currentFrameForegrounds, currentFrameChars, newFrameBackgrounds, newFrameForegrounds, newFrameChars = {}, {}, {}, {}, {}, {}
bufferWidth = width bufferWidth = width
bufferHeight = height bufferHeight = height
@ -106,8 +110,8 @@ local function flush(width, height)
currentFrameForegrounds[i] = 0xFEFEFE currentFrameForegrounds[i] = 0xFEFEFE
newFrameForegrounds[i] = 0xFEFEFE newFrameForegrounds[i] = 0xFEFEFE
currentFrameSymbols[i] = " " currentFrameChars[i] = " "
newFrameSymbols[i] = " " newFrameChars[i] = " "
end end
end end
@ -199,31 +203,62 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function rawSet(index, background, foreground, symbol) local function rawSet(index, background, foreground, char)
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, foreground, char
end end
local function rawGet(index) local function rawGet(index)
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index]
end end
local function get(x, y) local function get(x, y)
if x >= 1 and y >= 1 and x <= bufferWidth and y <= bufferHeight then if x >= 1 and y >= 1 and x <= bufferWidth and y <= bufferHeight then
local index = bufferWidth * (y - 1) + x local index = bufferWidth * (y - 1) + x
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index]
else else
return 0x000000, 0x000000, " " return 0x000000, 0x000000, " "
end end
end end
local function set(x, y, background, foreground, symbol) local function set(x, y, background, foreground, char)
if x >= drawLimitX1 and y >= drawLimitY1 and x <= drawLimitX2 and y <= drawLimitY2 then if x < drawLimitX1 or y < drawLimitY1 or x > drawLimitX2 or y > drawLimitY2 then
local index = bufferWidth * (y - 1) + x return
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol end
local
index,
charWlen =
bufferWidth * (y - 1) + x,
unicodeWlenCache[char]
if not charWlen then
charWlen = unicodeWlen(char)
unicodeWlenCache[char] = charWlen
end
newFrameBackgrounds[index],
newFrameForegrounds[index],
newFrameChars[index] =
background,
foreground,
char
index = index + 1
for i = 2, charWlen do
newFrameBackgrounds[index],
newFrameForegrounds[index],
newFrameChars[index] =
background,
foreground,
" "
index = index + 1
end end
end end
local function drawRectangle(x, y, width, height, background, foreground, symbol, transparency) local function drawRectangle(x, y, width, height, background, foreground, char, transparency)
local temp local temp
-- Clipping left -- Clipping left
@ -272,7 +307,7 @@ local function drawRectangle(x, y, width, height, background, foreground, symbol
for i = 1, width do for i = 1, width do
newFrameBackgrounds[temp], newFrameBackgrounds[temp],
newFrameForegrounds[temp], newFrameForegrounds[temp],
newFrameSymbols[temp] = background, foreground, symbol newFrameChars[temp] = background, foreground, char
temp = temp + 1 temp = temp + 1
end end
@ -361,7 +396,7 @@ local function blur(x, y, width, height, radius, color, transparency)
newFrameBackgrounds[screenIndex] = colorRGBToInteger(r, g, b) newFrameBackgrounds[screenIndex] = colorRGBToInteger(r, g, b)
newFrameForegrounds[screenIndex] = 0x0 newFrameForegrounds[screenIndex] = 0x0
newFrameSymbols[screenIndex] = " " newFrameChars[screenIndex] = " "
screenIndex = screenIndex + 1 screenIndex = screenIndex + 1
end end
@ -383,7 +418,7 @@ local function copy(x, y, width, height)
index = bufferWidth * (j - 1) + i index = bufferWidth * (j - 1) + i
tableInsert(copyArray, newFrameBackgrounds[index]) tableInsert(copyArray, newFrameBackgrounds[index])
tableInsert(copyArray, newFrameForegrounds[index]) tableInsert(copyArray, newFrameForegrounds[index])
tableInsert(copyArray, newFrameSymbols[index]) tableInsert(copyArray, newFrameChars[index])
else else
tableInsert(copyArray, 0x0) tableInsert(copyArray, 0x0)
tableInsert(copyArray, 0x0) tableInsert(copyArray, 0x0)
@ -405,7 +440,7 @@ local function paste(startX, startY, picture)
if x >= drawLimitX1 and x <= drawLimitX2 then if x >= drawLimitX1 and x <= drawLimitX2 then
newFrameBackgrounds[screenIndex] = picture[pictureIndex] newFrameBackgrounds[screenIndex] = picture[pictureIndex]
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1] newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
newFrameSymbols[screenIndex] = picture[pictureIndex + 2] newFrameChars[screenIndex] = picture[pictureIndex + 2]
end end
screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 3 screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 3
@ -517,37 +552,56 @@ local function rasterizePolygon(centerX, centerY, startX, startY, countOfEdges,
end end
end end
local function drawLine(x1, y1, x2, y2, background, foreground, symbol) local function drawLine(x1, y1, x2, y2, background, foreground, char)
rasterizeLine(x1, y1, x2, y2, function(x, y) rasterizeLine(x1, y1, x2, y2, function(x, y)
set(x, y, background, foreground, symbol) set(x, y, background, foreground, char)
end) end)
end end
local function drawEllipse(centerX, centerY, radiusX, radiusY, background, foreground, symbol) local function drawEllipse(centerX, centerY, radiusX, radiusY, background, foreground, char)
rasterizeEllipse(centerX, centerY, radiusX, radiusY, function(x, y) rasterizeEllipse(centerX, centerY, radiusX, radiusY, function(x, y)
set(x, y, background, foreground, symbol) set(x, y, background, foreground, char)
end) end)
end end
local function drawPolygon(centerX, centerY, radiusX, radiusY, background, foreground, countOfEdges, symbol) local function drawPolygon(centerX, centerY, radiusX, radiusY, background, foreground, countOfEdges, char)
rasterizePolygon(centerX, centerY, radiusX, radiusY, countOfEdges, function(x, y) rasterizePolygon(centerX, centerY, radiusX, radiusY, countOfEdges, function(x, y)
set(x, y, background, foreground, symbol) set(x, y, background, foreground, char)
end) end)
end end
local function drawText(x, y, textColor, data, transparency) local function drawText(x, y, textColor, text, transparency)
if y >= drawLimitY1 and y <= drawLimitY2 then if y < drawLimitY1 or y > drawLimitY2 then
local charIndex, screenIndex = 1, bufferWidth * (y - 1) + x return
end
for charIndex = 1, unicodeLen(data) do
if x >= drawLimitX1 and x <= drawLimitX2 then local
charIndex,
screenIndex,
char,
charWlen =
1,
bufferWidth * (y - 1) + x
for charIndex = 1, unicodeLen(text) do
char = unicodeSub(text, charIndex, charIndex)
charWlen = unicodeWlenCache[char]
if not charWlen then
charWlen = unicodeWlen(char)
unicodeWlenCache[char] = charWlen
end
for i = 1, charWlen do
if x >= drawLimitX1 and x + charWlen - 1 <= drawLimitX2 then
if transparency then if transparency then
newFrameForegrounds[screenIndex] = colorBlend(newFrameBackgrounds[screenIndex], textColor, transparency) newFrameForegrounds[screenIndex] = colorBlend(newFrameBackgrounds[screenIndex], textColor, transparency)
else else
newFrameForegrounds[screenIndex] = textColor newFrameForegrounds[screenIndex] = textColor
end end
newFrameSymbols[screenIndex] = unicodeSub(data, charIndex, charIndex) newFrameChars[screenIndex] = i == 1 and char or " "
end end
x, screenIndex = x + 1, screenIndex + 1 x, screenIndex = x + 1, screenIndex + 1
@ -592,11 +646,11 @@ local function drawImage(x, y, picture, blendForeground)
background, background,
foreground, foreground,
alpha, alpha,
symbol = bufferWidth * (y - 1) + x, bufferWidth - clippedImageWidth, (imageWidth - clippedImageWidth) * 4 char = bufferWidth * (y - 1) + x, bufferWidth - clippedImageWidth, (imageWidth - clippedImageWidth) * 4
for j = 1, clippedImageHeight do for j = 1, clippedImageHeight do
for i = 1, clippedImageWidth do for i = 1, clippedImageWidth do
alpha, symbol = picture[pictureIndex + 2], picture[pictureIndex + 3] alpha, char = picture[pictureIndex + 2], picture[pictureIndex + 3]
-- If it's fully transparent pixel -- If it's fully transparent pixel
if alpha == 0 then if alpha == 0 then
@ -611,11 +665,11 @@ local function drawImage(x, y, picture, blendForeground)
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1] newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
end end
-- If it's not transparent with whitespace -- If it's not transparent with whitespace
elseif symbol ~= " " then elseif char ~= " " then
newFrameForegrounds[screenIndex] = picture[pictureIndex + 1] newFrameForegrounds[screenIndex] = picture[pictureIndex + 1]
end end
newFrameSymbols[screenIndex] = symbol newFrameChars[screenIndex] = char
screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 4 screenIndex, pictureIndex = screenIndex + 1, pictureIndex + 4
end end
@ -640,35 +694,35 @@ end
local function semiPixelRawSet(index, color, yPercentTwoEqualsZero) local function semiPixelRawSet(index, color, yPercentTwoEqualsZero)
local upperPixel, lowerPixel, bothPixel = "", "", " " local upperPixel, lowerPixel, bothPixel = "", "", " "
local background, foreground, symbol = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] local background, foreground, char = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index]
if yPercentTwoEqualsZero then if yPercentTwoEqualsZero then
if symbol == upperPixel then if char == upperPixel then
if color == foreground then if color == foreground then
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, bothPixel newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, bothPixel
else else
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, symbol newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, char
end end
elseif symbol == bothPixel then elseif char == bothPixel then
if color ~= background then if color ~= background then
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, lowerPixel newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, lowerPixel
end end
else else
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, lowerPixel newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, lowerPixel
end end
else else
if symbol == lowerPixel then if char == lowerPixel then
if color == foreground then if color == foreground then
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, bothPixel newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, bothPixel
else else
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = color, foreground, symbol newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = color, foreground, char
end end
elseif symbol == bothPixel then elseif char == bothPixel then
if color ~= background then if color ~= background then
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, upperPixel newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, upperPixel
end end
else else
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, color, upperPixel newFrameBackgrounds[index], newFrameForegrounds[index], newFrameChars[index] = background, color, upperPixel
end end
end end
end end
@ -765,51 +819,168 @@ end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function update(force) local function update(force)
local index, indexStepOnEveryLine, changes = bufferWidth * (drawLimitY1 - 1) + drawLimitX1, (bufferWidth - drawLimitX2 + drawLimitX1 - 1), {} local
local x, equalChars, equalCharsIndex, charX, charIndex, currentForeground index,
local currentFrameBackground, currentFrameForeground, currentFrameSymbol, changesCurrentFrameBackground, changesCurrentFrameBackgroundCurrentFrameForeground indexStepOnEveryLine,
local changesCurrentFrameBackgroundCurrentFrameForegroundIndex changes,
x,
charX,
charIndex,
charWlen,
equalChars,
equalCharsIndex,
currentFrameBackground,
currentFrameForeground,
currentFrameChar,
newFrameChar,
newFrameForeground,
newFrameBackground,
changesCurrentFrameBackground,
changesCurrentFrameBackgroundCurrentFrameForeground,
changesCurrentFrameBackgroundCurrentFrameForegroundIndex,
currentForeground =
bufferWidth * (drawLimitY1 - 1) + drawLimitX1,
(bufferWidth - drawLimitX2 + drawLimitX1 - 1),
{}
for y = drawLimitY1, drawLimitY2 do for y = drawLimitY1, drawLimitY2 do
x = drawLimitX1 x = drawLimitX1
while x <= drawLimitX2 do while x <= drawLimitX2 do
-- Determine if some pixel data was changed (or if <force> argument was passed) -- Determine if some pixel data was changed (or if <force> argument was passed)
currentFrameBackground,
currentFrameForeground,
currentFrameChar =
currentFrameBackgrounds[index],
currentFrameForegrounds[index],
currentFrameChars[index]
newFrameBackground,
newFrameForeground,
newFrameChar =
newFrameBackgrounds[index],
newFrameForegrounds[index],
newFrameChars[index]
if if
currentFrameBackgrounds[index] ~= newFrameBackgrounds[index] or currentFrameBackground ~= newFrameBackground or
currentFrameForegrounds[index] ~= newFrameForegrounds[index] or currentFrameForeground ~= newFrameForeground or
currentFrameSymbols[index] ~= newFrameSymbols[index] or currentFrameChar ~= newFrameChar or
force force
then then
-- Make pixel at both frames equal -- Make pixel at both frames equal
currentFrameBackground, currentFrameForeground, currentFrameSymbol = newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] currentFrameBackgrounds[index],
currentFrameBackgrounds[index] = currentFrameBackground currentFrameForegrounds[index],
currentFrameForegrounds[index] = currentFrameForeground currentFrameChars[index],
currentFrameSymbols[index] = currentFrameSymbol
currentFrameBackground,
currentFrameForeground,
currentFrameChar =
newFrameBackground,
newFrameForeground,
newFrameChar,
newFrameBackground,
newFrameForeground,
newFrameChar
-- Look for pixels with equal chars from right of current pixel -- Look for pixels with equal chars from right of current pixel
equalChars, equalCharsIndex, charX, charIndex = {currentFrameSymbol}, 2, x + 1, index + 1 charWlen = unicodeWlenCache[currentFrameChar]
if not charWlen then
charWlen = unicodeWlen(currentFrameChar)
unicodeWlenCache[currentFrameChar] = charWlen
end
charX,
charIndex,
equalChars,
equalCharsIndex =
x + 1,
index + 1,
{ currentFrameChar },
2
for i = 2, charWlen do
currentFrameBackgrounds[charIndex],
currentFrameForegrounds[charIndex],
currentFrameChars[charIndex],
charX,
charIndex =
newFrameBackground,
newFrameForeground,
" ",
charX + 1,
charIndex + 1
end
while charX <= drawLimitX2 do while charX <= drawLimitX2 do
newFrameBackground,
newFrameForeground,
newFrameChar =
newFrameBackgrounds[charIndex],
newFrameForegrounds[charIndex],
newFrameChars[charIndex]
-- Pixels becomes equal only if they have same background and (whitespace char or same foreground) -- Pixels becomes equal only if they have same background and (whitespace char or same foreground)
if if
currentFrameBackground == newFrameBackgrounds[charIndex] and newFrameBackground == currentFrameBackground
( and (
newFrameSymbols[charIndex] == " " or newFrameForeground == currentFrameForeground
currentFrameForeground == newFrameForegrounds[charIndex] or newFrameChar == " "
) )
then then
-- Make pixel at both frames equal charWlen = unicodeWlenCache[newFrameChar]
currentFrameBackgrounds[charIndex] = newFrameBackgrounds[charIndex]
currentFrameForegrounds[charIndex] = newFrameForegrounds[charIndex] if not charWlen then
currentFrameSymbols[charIndex] = newFrameSymbols[charIndex] charWlen = unicodeWlen(newFrameChar)
unicodeWlenCache[newFrameChar] = charWlen
end
equalChars[equalCharsIndex], equalCharsIndex = currentFrameSymbols[charIndex], equalCharsIndex + 1 currentFrameBackgrounds[charIndex],
currentFrameForegrounds[charIndex],
currentFrameChars[charIndex],
charX,
charIndex,
equalChars[equalCharsIndex],
equalCharsIndex =
newFrameBackground,
newFrameForeground,
newFrameChar,
charX + 1,
charIndex + 1,
newFrameChar,
equalCharsIndex + 1
for i = 2, charWlen do
currentFrameBackgrounds[charIndex],
currentFrameForegrounds[charIndex],
currentFrameChars[charIndex],
charX,
charIndex =
newFrameBackground,
newFrameForeground,
" ",
charX + 1,
charIndex + 1
end
else else
break break
end end
charX, charIndex = charX + 1, charIndex + 1
end end
-- Group pixels that need to be drawn by background and foreground -- Group pixels that need to be drawn by background and foreground