// // Created by my on 2019/11/16. // #include #include "TextRenderer.h" TextRenderer::TextRenderer() { updateParameters(); } void TextRenderer::update(std::string newText) { currentX = 0; currentY = 0; int i; int fontNumbersInOneLine = windowWidth / (font.width() + left_margin); int space = 0; int currentLine; std::vector> characterBitmap; clear(); newText = adjustText(newText); vkvm::log(vkvm::LogLevel::DEBUG, newText, "\n"); for(i = 0; i < newText.size(); i++) { if(newText[i] == returnCharacter) { space += (fontNumbersInOneLine - ((i + space) % fontNumbersInOneLine) - 1); } else { if(newText[i] == specialCharacter) { space -= 1; int tempBlinkX = blinkX; int tempBlinkY = blinkY; int tempSpecialCharacterCurrentX = specialCharacterCurrentX; int tempSpecialCharacterCurrentY = specialCharacterCurrentY; char tempSpecialChar = _specialCharacter; specialCharacterCurrentX = ((i + space) % fontNumbersInOneLine) * (font.width() + left_margin); specialCharacterCurrentY = ((i + space) / fontNumbersInOneLine) * (font.height() + bottom_margin); blinkX = specialCharacterCurrentX + font.width(); blinkY = specialCharacterCurrentY; _specialCharacter = newText[i - 1]; if(_specialCharacter != '\n') { characterBitmap = getCharacter(_specialCharacter); translateToSharedMemory(characterBitmap, specialCharacterCurrentX, specialCharacterCurrentY, true); } else { blinkX = 0; blinkY += (font.height() + bottom_margin); } if(specialCharacterCurrentX != tempSpecialCharacterCurrentX && specialCharacterCurrentY != tempSpecialCharacterCurrentY) { clear(tempBlinkX, tempBlinkY, tempBlinkX + 1, tempBlinkY + font.height() + 1); if(tempSpecialChar != '\n' && (tempSpecialCharacterCurrentY * 10 + tempSpecialCharacterCurrentX <= specialCharacterCurrentY * 10 + tempSpecialCharacterCurrentX)) { translateToSharedMemory(getCharacter(tempSpecialChar), tempSpecialCharacterCurrentX, tempSpecialCharacterCurrentY, true); } } } else { currentLine = ((i + space) / fontNumbersInOneLine); currentX = ((i + space) % fontNumbersInOneLine) * (font.width() + left_margin); currentY = (currentLine) * (font.height() + bottom_margin); characterBitmap = getCharacter(newText[i]); translateToSharedMemory(characterBitmap, currentX, currentY, false); } } } if(newText.size() < oldTextsize) { clear(currentX, currentY, font.width(), currentY + font.height()); } } std::string TextRenderer::adjustText(std::string newText) { int fontNumbersInOneLine = windowWidth / (font.width() + left_margin); int totalLine = windowHeight / (font.height() + bottom_margin); int stringLine = 1; int characterNumberOfLastLine = 0; for(char c : newText) { if(c == returnCharacter) { stringLine++; characterNumberOfLastLine = 0; } else if(c != specialCharacter) { characterNumberOfLastLine++; if(characterNumberOfLastLine == fontNumbersInOneLine) { stringLine++; characterNumberOfLastLine = 0; } } } if(stringLine > totalLine) { int startLine = stringLine - totalLine; int currentLine = 0; int cursorLine; for(int i = 0; i < newText.size(); i++) { if(newText[i] == returnCharacter) { currentLine++; characterNumberOfLastLine = 0; } else if(newText[i] != specialCharacter) { characterNumberOfLastLine++; if(characterNumberOfLastLine == fontNumbersInOneLine) { currentLine++; characterNumberOfLastLine = 0; } } else { cursorLine = currentLine; if(currentLine < startLine) { return adjustText(newText, cursorLine, cursorLine + totalLine); } } if(currentLine == startLine) { return newText.substr(i + 1, newText.size()); } } } return newText; } std::string TextRenderer::adjustText(std::string newText, int startLine, int endLine) { int currentLine = 0; int startIndex, endIndex; int characterNumberOfCurrentLine = 0; int fontNumbersInOneLine = windowWidth / (font.width() + left_margin); for(int i = 0; i < newText.size(); i++) { if(newText[i] == returnCharacter) { characterNumberOfCurrentLine = 0; currentLine++; if(currentLine == startLine) { startIndex = i; } if(currentLine == endLine) { endIndex = i; return newText.substr(startIndex + 1, endIndex); } } else if (newText[i] != specialCharacter) { characterNumberOfCurrentLine++; if(characterNumberOfCurrentLine == fontNumbersInOneLine) { characterNumberOfCurrentLine = 0; currentLine++; if(currentLine == startLine) { startIndex = i; } if(currentLine == endLine) { endIndex = i; return newText.substr(startIndex + 1, endIndex); } } } } vkvm::log(vkvm::ERROR, "could not adjust string"); return std::string(); } void TextRenderer::clear() { clear(0, 0, windowWidth, windowHeight); } void TextRenderer::clear(int startX, int startY, int endX, int endY) { int x, y; for(y = startY; y < endY; y++) { for(x = startX; x < endX; x++) { vkvm::setPixel(x, y, backgroundColor); } } } std::vector> TextRenderer::getCharacter(unsigned char character) { std::vector> bitmap_character; bitmap_character.resize(font.height()); vkvm::log(vkvm::DEBUG, bitmap_character.size()); for (int y = 0; y < font.height(); y += fontSize) { vkvm::log(vkvm::DEBUG, y); for(int i = 0; i < fontSize; i++) { bitmap_character[y + i].resize(font.width()); } for (int x = 0; x < font.width(); x += fontSize) { bitmap_character[y][x] = font.getPixel(character, x / fontSize, y / fontSize); if(bitmap_character[y][x] && fontSize != 1) { if(y != 0) { for (int i = y - fontSize + 1; i < y; i++) { bitmap_character[i][x] = bitmap_character[y - fontSize][x]; } } if(x != 0) { for (int i = x - fontSize + 1; i < x; i++) { bitmap_character[y][i] = bitmap_character[y][x - fontSize]; } } if(x != 0 && y != 0) { for (int i = 1; i < fontSize; i++) { bitmap_character[y - i][x - i] = bitmap_character[y - fontSize][x - fontSize]; } } } } } vkvm::log(vkvm::DEBUG, bitmap_character.size()); return bitmap_character; } void TextRenderer::translateToSharedMemory(std::vector> characterBitmap, int startX, int startY, bool flipColors) { int x, y; int _currentX = startX; int _currentY = startY; for(y = 0; y < font.height(); y++) { for(x = 0; x < font.width(); x++) { if(characterBitmap[y][x]) { vkvm::log(vkvm::DEBUG, x, y); if(flipColors) { vkvm::setPixel(currentX, currentY, backgroundColor); }else { vkvm::setPixel(currentX, currentY, foregroundColor); } } else { if(flipColors) vkvm::setPixel(currentX, currentY, foregroundColor); else vkvm::setPixel(currentX, currentY, backgroundColor); } _currentX++; } _currentX = startX; _currentY++; } for(x = 0; x < left_margin; x++) { for(y = 0; y < font.height(); y++) { vkvm::setPixel(startX + font.width() + x, startY + y, backgroundColor); } } for(y = 0; y < bottom_margin; y++) { for(x = 0; x < font.width() + left_margin; x++) { vkvm::setPixel(startX + x, startY + font.height() + y, backgroundColor); } } } void TextRenderer::setLeftMargin(int margin) { left_margin = margin; } void TextRenderer::setBottomMargin(int margin) { bottom_margin = margin; } void TextRenderer::updateParameters() { windowHeight = vkvm::getHeight(); windowWidth = vkvm::getWidth(); int fontId = vkvm::getFont(); std::string fontResourcePath = "../res/font" + std::to_string(fontId) + ".bmp"; std::string fontConfigureFilePath = "../res/font" + std::to_string(fontId) + ".toml"; font = Font(fontResourcePath, fontConfigureFilePath); backgroundColor = vkvm::getBackgroundColor(); foregroundColor = vkvm::getForegroundColor(); }