Merge branch 'dev' into 'master'

Dev

See merge request link/projekte/ws19/vkvm-new/text-renderer!8
This commit is contained in:
Julian Hinxlage 2020-01-08 12:11:18 +00:00
commit 762f8af5fe
15 changed files with 289 additions and 85 deletions

32
.ci/clang-tidy.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/sh
echo "Doing clang-tidy..."
bool=false
# explicitly set IFS to contain only a line feed
IFS='
'
filelist="$(find . -not \( -path './*build*' -prune \) -not \( -path './include' -prune \) -type f ! -name "$(printf "*\n*")")"
for file in $filelist; do
if echo "$file" | grep -q -E ".*(\.cpp|\.hpp)$" ; then
#Extra check missing dependencies due to clang-tidy doesn't toggle exit code.
clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' "$file" -- -I. -std=c++14 2>&1)"
for tidy_line in $clang_tidy_lib_check; do
echo "$tidy_line" | grep -q -v -E "^Error while processing*"
if [ $? -eq 1 ]; then
bool=true
fi
echo "$tidy_line" | grep -q -v -E ".* error: .*"
if [ $? -eq 1 ]; then
bool=true
fi
echo "$tidy_line"
done
fi
done
if $bool; then
exit 1
else
echo "No clang-tidy errors found."
fi
exit 0

2
.clang-tidy Normal file
View File

@ -0,0 +1,2 @@
Checks: '*,-llvm-header-guard,-fuchsia*,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-hicpp-signed-bitwise,-bugprone-exception-escape,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-cstyle-cast,-hicpp-member-init,-google-readability-namespace-comments,-llvm-namespace-comment,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-modernize-use-trailing-return-type,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers'
WarningsAsErrors: 'true'

76
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,76 @@
---
image: samueldebruyn/debian-git:latest
stages:
- style
- test
- build
clang_tidy:
image: joethei/clang_tidy
stage: style
tags:
- docker-ci
script:
- mkdir current
- ls -d .[!.]* | grep -v current | xargs mv -t current
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git
- mkdir library/build
- cd library/build
- cmake ..
- make
- cd ../../current/.ci
- sh clang-tidy.sh
make_test:
stage: test
tags:
- docker-ci
script:
- apt-get update
- apt-get install -y g++ make cmake clang-tidy
- mkdir current
- ls | grep -v current | xargs mv -t current
- git clone https://github.com/catchorg/Catch2.git
- cd Catch2
- cmake -Bbuild -H. -DBUILD_TESTING=OFF
- cmake --build build/ --target install
- cd ..
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git
- mkdir library/build
- cd library/build
- cmake ..
- make
- cd ../../current
- mkdir build
- cd build
- cmake ..
- make
- make test
cmake_build:
stage: build
tags:
- docker-ci
script:
- apt-get update
- apt-get install -y g++ make cmake clang-tidy
- mkdir current
- ls | grep -v current | xargs mv -t current
- git clone https://github.com/catchorg/Catch2.git
- cd Catch2
- cmake -Bbuild -H. -DBUILD_TESTING=OFF
- cmake --build build/ --target install
- cd ..
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.repo.digitech.hs-emden-leer.de/link/projekte/ws19/vkvm-new/library.git
- mkdir library/build
- cd library/build
- cmake ..
- make
- cd ../../current
- mkdir build
- cd build
- cmake ..
- make

View File

@ -12,11 +12,11 @@ project(TextRenderer)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
# enable clang_tidy # enable clang_tidy
set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-checks=*") set(CMAKE_CXX_CLANG_TIDY "clang-tidy")
set(CMAKE_CXX_CLANG_TIDY clang-tidy;-header-filter=.;-checks=*;) set(CMAKE_CXX_CLANG_TIDY clang-tidy;-header-filter=.;)
file(GLOB_RECURSE SOURCES src/*.cpp) file(GLOB_RECURSE SOURCES src/*.cpp)
file(GLOB_RECURSE HEADERS src/*.h) file(GLOB_RECURSE HEADERS src/*.hpp)
file(GLOB_RECURSE TESTS test/*.cpp) file(GLOB_RECURSE TESTS test/*.cpp)
include_directories(src) include_directories(src)
include_directories(test) include_directories(test)
@ -30,12 +30,14 @@ include_directories(${LIB_PATH}/include)
add_executable(TextRenderer ${SOURCES} ${HEADERS} main/main.cpp) add_executable(TextRenderer ${SOURCES} ${HEADERS} main/main.cpp)
target_link_libraries(TextRenderer ${LIB_PATH}/lib/liblibrary.a) target_link_libraries(TextRenderer ${LIB_PATH}/lib/liblibrary.a)
target_link_libraries(TextRenderer pthread)
enable_testing() enable_testing()
find_package(Catch2 REQUIRED) find_package(Catch2 REQUIRED)
add_executable(UnitTests ${SOURCES} ${HEADERS} ${TESTS}) add_executable(UnitTests ${SOURCES} ${HEADERS} ${TESTS})
target_link_libraries(UnitTests ${LIB_PATH}/lib/liblibrary.a)
target_link_libraries(UnitTests Catch2::Catch2) target_link_libraries(UnitTests Catch2::Catch2)
target_link_libraries(UnitTests pthread)
include(CTest) include(CTest)
include(Catch) include(Catch)

View File

@ -1,4 +1,10 @@
# vKVM TextRenderer # vKVM Text Renderer
The Text Renderer gets the string from the text area in the Shared Memory and writes it
into pixelarea.
To convert a string the Text Renderer uses a font, which is loaded from a bitmap-file.
## Installation ## Installation
@ -6,36 +12,3 @@ Use the installation script provided in the Scripts repository
to install the full package. to install the full package.
Installing a single component is currently not supported. Installing a single component is currently not supported.
## Target
TextRender build exports an interface target TextRender::TextRender.
This means that if TextRender has been installed on the Project Path, it
should be enough to do.
translate a string from terminal to the readable form of shared memory .
## Usage
mkdir build
cd build
cmake ..
make
## Description
TextRender has two class, Bitmap class and Font class.
res/font.bmp (bitmap data, used by Bitmap::load() function)
res/font.toml (configuration file, it configure how to read the font.bmp)
src/Bitmap class, it used to read the font.bmp file.
src/Font class, it read the font.bmp data by Bitmap class,
translate a string to a bitmap.
test folder used to test.
main folder is only used to test now.

View File

@ -1,36 +1,117 @@
#include "add.h" #include "Font.hpp"
#include "Bitmap.h" #include "internal.hpp"
#include "Font.h" #include "vkvm.hpp"
#include <thread>
#include <iostream> #include <iostream>
int cursorPosX = 0;
int cursorPosY = 0;
bool showCursor = false;
/** /**
* @author: Julian Hinxlage * @author: Julian Hinxlage
* @since: v0.0.0 * @since: v0.0.0
* @brief: An image is loaded and used as a font. * @brief: An image is loaded and used as a font.
* A string is converted and displayed in the console.
* Currently only to test.
*/ */
int main() {
Font font("../res/font2.bmp","../res/font2.toml");
std::string str; void threadHandler(Font &font){
std::cout << "string to draw: "; static bool cursorState{false};
std::getline(std::cin, str);
for (int i = 0; i < font.height(); i++) { int start = 0;
for (char c : str) { int end = font.height();
for (int j = 0; j < font.width(); j++) { auto bc = vkvm::getBackgroundColor();
if (font.getPixel(c,j,i)) { auto fc = vkvm::getForegroundColor();
std::cout << "";
while(true){
if(showCursor) {
int x = cursorPosX - 1;
if (x < 0) {
x = 0;
}
for (int i = start; i < end; i++) {
if (cursorState) {
vkvm::setPixel(x, cursorPosY + i, bc);
} else { } else {
std::cout << " "; vkvm::setPixel(x, cursorPosY + i, fc);
} }
} }
std::cout << " "; vkvm::callEvent(vkvm::EventType::Redraw);
cursorState = !cursorState;
} }
std::cout << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(800));
} }
}
int main() {
vkvm::initialize(0);
vkvm::setLogLevel(vkvm::DEBUG);
Font font(
std::string() + "../res/font" +
std::to_string(static_cast<int>(vkvm::getFont())) + ".bmp",
std::string() + "../res/font" +
std::to_string(static_cast<int>(vkvm::getFont())) + ".toml");
std::thread thread(std::bind(threadHandler, font));
vkvm::registerEvent(vkvm::EventType::RenderText, [&font]() {
std::string currentText = vkvm::getText();
int perRow = vkvm::getWidth() / font.width();
auto bc = vkvm::getBackgroundColor();
auto fc = vkvm::getForegroundColor();
//clear area
for(int y = 0; y < vkvm::getHeight();y++){
for(int x = 0; x < vkvm::getWidth();x++) {
vkvm::setPixel(x,y,bc);
}
}
showCursor = false;
int x = 0;
int y = 0;
for(char c : currentText){
if(c == '\n'){
y++;
x = 0;
}else if(c == -127){
cursorPosX = x * font.width();
cursorPosY = y * font.height();
showCursor = true;
}
else{
if(x == perRow){
y++;
x = 0;
}
for(int i = 0; i < font.height();i++){
for(int j = 0; j < font.width();j++){
if(font.getPixel(c, j, i)){
vkvm::setPixel(x * font.width() + j, y * font.height() + i, fc);
}else{
vkvm::setPixel(x * font.width() + j, y * font.height() + i, bc);
}
}
}
x++;
}
}
vkvm::callEvent(vkvm::EventType::Redraw);
});
vkvm::registerEvent(vkvm::EventType::UpdateControlRegisters, [&font]() {
font.load(
std::string() + "../res/font" +
std::to_string(static_cast<int>(vkvm::getFont())) + ".bmp",
std::string() + "../res/font" +
std::to_string(static_cast<int>(vkvm::getFont())) + ".toml");
});
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return 0; return 0;
} }

BIN
res/font3.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 KiB

12
res/font3.toml Normal file
View File

@ -0,0 +1,12 @@
xOffset = 6
yOffset = 6
xSize = 18
ySize = 27
xCount = 32
yCount = 9
xStart = 7
yStart = 9
fillValue = 4294967295
firstChar = 25
pixelSize = 1
invertedColors = 1

BIN
res/font4.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

12
res/font4.toml Normal file
View File

@ -0,0 +1,12 @@
xOffset = 6
yOffset = 2
xSize = 10
ySize = 14
xCount = 255
yCount = 255
xStart = 33
yStart = 65
fillValue = 0
firstChar = 0
pixelSize = 1
invertedColors = 0

View File

@ -1,4 +1,4 @@
#include "Bitmap.h" #include "Bitmap.hpp"
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -26,11 +26,10 @@ void Bitmap::load(const std::string &file) {
for(int i = 0; i < str.size();i++){ for(int i = 0; i < str.size();i++){
data[i] = str[i]; data[i] = str[i];
} }
offset = *reinterpret_cast<int*>(&data[10]);
offset = (int)*(unsigned int*)(&data[10]); width = *reinterpret_cast<int*>(&data[18]);
width = (int)*(unsigned int*)(&data[18]); height = *reinterpret_cast<int*>(&data[22]);
height = (int)*(unsigned int*)(&data[22]); bpp = *reinterpret_cast<uint16_t *>(&data[28]);
bpp = (int)*(unsigned short*)(&data[28]);
} }
} }
@ -52,12 +51,18 @@ int Bitmap::getBitsPerPixel() {
unsigned int Bitmap::getPixel(int x, int y) { unsigned int Bitmap::getPixel(int x, int y) {
unsigned int pixel = 0; unsigned int pixel = 0;
if(bpp == 1){
int index = (getHeight() - 1 - y) * getWidth() + x;
char *ptr = getData() + (index / 8);
bool value = (ptr[0] >> (7 - (index % 8))) & 1u;
return (int)value;
}
char *ptr = getData() + ((getHeight() - 1 - y) * getWidth() + x) * (getBitsPerPixel() / 8); char *ptr = getData() + ((getHeight() - 1 - y) * getWidth() + x) * (getBitsPerPixel() / 8);
for(int i = 0; i < getBitsPerPixel() / 8;i++){ for(int i = 0; i < getBitsPerPixel() / 8;i++){
*((char*)&pixel+i) = ptr[i]; auto value = reinterpret_cast<char*>(&pixel)+i;
} *value = ptr[i];
if(pixel != 0){
return pixel;
} }
return pixel; return pixel;
} }

View File

@ -1,5 +1,5 @@
#ifndef TEXTRENDERER_BITMAP_H #ifndef TEXTRENDERER_BITMAP_HPP
#define TEXTRENDERER_BITMAP_H #define TEXTRENDERER_BITMAP_HPP
#include <string> #include <string>
#include <vector> #include <vector>
@ -19,7 +19,7 @@ public:
* @since: v0.0.0 * @since: v0.0.0
* @brief: Used to load a Bitmap from a file. * @brief: Used to load a Bitmap from a file.
*/ */
void load(const std::string &file); void load(const std::string &file);
/** /**
* @author: Julian Hinxlage * @author: Julian Hinxlage
@ -65,4 +65,4 @@ private:
}; };
#endif //TEXTRENDERER_BITMAP_H #endif //TEXTRENDERER_BITMAP_HPP

View File

@ -2,8 +2,8 @@
// Copyright (c) 2019 Julian Hinxlage. All rights reserved. // Copyright (c) 2019 Julian Hinxlage. All rights reserved.
// //
#include "Font.h" #include "Font.hpp"
#include <cpptoml.h> #include "../lib/toml/cpptoml.h"
Font::Font() { Font::Font() {
xOffset = 0; xOffset = 0;
@ -16,6 +16,9 @@ Font::Font() {
yStart = 0; yStart = 0;
fillValue = 0; fillValue = 0;
firstChar = ' '; firstChar = ' ';
pixelSize = 1;
gap = -1;
invertedColors = false;
} }
Font::Font(const std::string &file, const std::string &configFile) : Font() { Font::Font(const std::string &file, const std::string &configFile) : Font() {
@ -34,9 +37,10 @@ void Font::load(const std::string &file, const std::string &configFile) {
xStart = config->get_as<int>("xStart").value_or(0); xStart = config->get_as<int>("xStart").value_or(0);
yStart = config->get_as<int>("yStart").value_or(0); yStart = config->get_as<int>("yStart").value_or(0);
fillValue = config->get_as<unsigned int>("fillValue").value_or(0); fillValue = config->get_as<unsigned int>("fillValue").value_or(0);
firstChar = (char)config->get_as<int>("firstChar").value_or(0); firstChar = config->get_as<char>("firstChar").value_or(0);
pixelSize = config->get_as<int>("pixelSize").value_or(0); pixelSize = config->get_as<int>("pixelSize").value_or(0);
gap = config->get_as<int>("gap").value_or(-1); gap = config->get_as<int>("gap").value_or(-1);
invertedColors = static_cast<bool>(config->get_as<int>("invertedColors").value_or(0));
} }
int Font::width() { int Font::width() {
@ -69,6 +73,7 @@ bool Font::getPixel(char character, int x, int y) {
int xPos = xIndex * (xSize + xOffset) + xStart; int xPos = xIndex * (xSize + xOffset) + xStart;
int yPos = yIndex * (ySize + yOffset) + yStart; int yPos = yIndex * (ySize + yOffset) + yStart;
return bitmap.getPixel((xPos + x) * pixelSize, (yPos + y) * pixelSize) == fillValue; bool value = bitmap.getPixel((xPos + x) * pixelSize, (yPos + y) * pixelSize) == fillValue;
return invertedColors != value;
} }

View File

@ -2,10 +2,10 @@
// Copyright (c) 2019 Julian Hinxlage. All rights reserved. // Copyright (c) 2019 Julian Hinxlage. All rights reserved.
// //
#ifndef TEXTRENDERER_FONT_H #ifndef TEXTRENDERER_FONT_HPP
#define TEXTRENDERER_FONT_H #define TEXTRENDERER_FONT_HPP
#include "Bitmap.h" #include "Bitmap.hpp"
/** /**
* @author: Julian Hinxlage * @author: Julian Hinxlage
@ -13,7 +13,7 @@
* @brief: this class provides pixel access based on characters * @brief: this class provides pixel access based on characters
*/ */
class Font { class Font {
public: private:
Bitmap bitmap; Bitmap bitmap;
//space between characters //space between characters
@ -38,6 +38,10 @@ public:
int pixelSize; int pixelSize;
int gap; int gap;
bool invertedColors;
public:
Font(); Font();
explicit Font(const std::string &file, const std::string &configFile); explicit Font(const std::string &file, const std::string &configFile);
void load(const std::string &file, const std::string &configFile); void load(const std::string &file, const std::string &configFile);
@ -48,4 +52,4 @@ public:
}; };
#endif //TEXTRENDERER_FONT_H #endif //TEXTRENDERER_FONT_HPP

View File

@ -1,6 +1,6 @@
#include "Bitmap.hpp"
#include "Font.hpp"
#include <catch2/catch.hpp> #include <catch2/catch.hpp>
#include "Bitmap.h"
#include "Font.h"
TEST_CASE("default values") { TEST_CASE("default values") {
Bitmap bitmap = Bitmap(); Bitmap bitmap = Bitmap();
@ -20,7 +20,7 @@ TEST_CASE("Font") {
Font font("../res/font1.bmp", "../res/font1.toml"); Font font("../res/font1.bmp", "../res/font1.toml");
REQUIRE(font.width() == 5); REQUIRE(font.width() == 5);
REQUIRE(font.height() == 7); REQUIRE(font.height() == 7);
REQUIRE(!font.getPixel('a', 1,1)); REQUIRE_FALSE(font.getPixel('a', 1,1));
REQUIRE(font.getPixel('a', 1,2)); REQUIRE(font.getPixel('a', 1,2));
} }