From 1a53ca46cac8bb7cd10049fc61e95ebc213c7314 Mon Sep 17 00:00:00 2001 From: my Date: Wed, 30 Oct 2019 12:37:38 +0100 Subject: [PATCH 01/45] readme update, delete the useless part. --- README.md | 35 ++--------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index cdadfe7..751e9c6 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,10 @@ # vKVM TextRenderer +translate a string from terminal to the readable form of shared memory . + ## Installation Use the installation script provided in the Scripts repository to install the full package. 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. \ No newline at end of file From 5c896dcd4e003e4862019df79268bb2da40fdc54 Mon Sep 17 00:00:00 2001 From: Edgar Schkrob Date: Wed, 6 Nov 2019 12:34:46 +0000 Subject: [PATCH 02/45] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 751e9c6..cb276eb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # vKVM TextRenderer -translate a string from terminal to the readable form of shared memory . +The TextRenderer gets a string from the Shared Memory and converts the text into +a bitmap-array. Afterwards the array is send back to the Shared Memory. + +To convert a string the TextRendere uses a font, which is loaded from a bitmap-file. ## Installation From 2325c52e2aade6bc0c9ebc5db7d562bca7a07f77 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Thu, 7 Nov 2019 13:55:06 +0000 Subject: [PATCH 03/45] + ci pipeline --- .ci/clang-tidy.sh | 32 ++++++++++++++++++++++ .gitlab-ci.yml | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 .ci/clang-tidy.sh create mode 100644 .gitlab-ci.yml diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh new file mode 100644 index 0000000..eae5b12 --- /dev/null +++ b/.ci/clang-tidy.sh @@ -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 './client/cpptoml/*' -prune \) -type f ! -name "$(printf "*\n*")")" +for file in $filelist; do + if echo "$file" | grep -q -E ".*\.cpp$" ; 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' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-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' "$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 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..eb1309a --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,68 @@ +--- + +image: samueldebruyn/debian-git:latest + +stages: + - style + - test + - build + + +clang_tidy: + image: jhasse/clang-tidy + stage: style + tags: + - docker-ci + script: + - sh .ci/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 \ No newline at end of file From 958207eabc530935867afd46cb95f3ff03dfabdf Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 12 Nov 2019 11:17:17 +0000 Subject: [PATCH 04/45] ~ CI: clang_tidy step now contains catch2 & fltk --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eb1309a..522f05f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,7 +9,7 @@ stages: clang_tidy: - image: jhasse/clang-tidy + image: joethei/clang_tidy stage: style tags: - docker-ci From 51892ae707ba9f43a7b9ac516cee9db04ea7d3b5 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 12 Nov 2019 11:42:01 +0000 Subject: [PATCH 05/45] ~ default argument calls are now allowed --- .ci/clang-tidy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh index eae5b12..c20c8fb 100644 --- a/.ci/clang-tidy.sh +++ b/.ci/clang-tidy.sh @@ -9,7 +9,7 @@ filelist="$(find . -not \( -path './client/cpptoml/*' -prune \) -type f ! -name for file in $filelist; do if echo "$file" | grep -q -E ".*\.cpp$" ; 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' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-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' "$file" -- -I. -std=c++14 2>&1)" + clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-fuchsia-default-argument-calls,-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' "$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 From 0bc0862cb763a92f2434e2bdc97335f0bb7ae06e Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 12 Nov 2019 15:26:04 +0100 Subject: [PATCH 06/45] ~clang tidy checks all fies now --- .ci/clang-tidy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.ci/clang-tidy.sh b/.ci/clang-tidy.sh index c20c8fb..913c79a 100644 --- a/.ci/clang-tidy.sh +++ b/.ci/clang-tidy.sh @@ -5,11 +5,11 @@ bool=false # explicitly set IFS to contain only a line feed IFS=' ' -filelist="$(find . -not \( -path './client/cpptoml/*' -prune \) -type f ! -name "$(printf "*\n*")")" +filelist="$(find . -not \( -path './*build*' -prune \) -type f ! -name "$(printf "*\n*")")" for file in $filelist; do - if echo "$file" | grep -q -E ".*\.cpp$" ; then + if echo "$file" | grep -q -E ".*(\.cpp|\.h|\.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' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-fuchsia-default-argument-calls,-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' "$file" -- -I. -std=c++14 2>&1)" + clang_tidy_lib_check="$(clang-tidy -warnings-as-errors='*' -header-filter='.*,-cpptoml.hpp' -checks='*,-llvm-header-guard,-fuchsia-statically-constructed-objects,-fuchsia-default-arguments,-fuchsia-default-arguments-calls,-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' "$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 From 4a08c433ad835b00c6eab4a303cd2b2560ff54ba Mon Sep 17 00:00:00 2001 From: my Date: Thu, 14 Nov 2019 13:12:48 +0100 Subject: [PATCH 07/45] defination of Font and Block interface. --- CMakeLists.txt | 5 +- main/main.cpp | 12 +-- res/{font.bmp => font1.bmp} | Bin res/font1.toml | 11 +++ res/font2.bmp | Bin 0 -> 393354 bytes res/font2.toml | 13 +++ res/font3.ppm | 22 +++++ res/font3.toml | 7 ++ src/Bitmap.cpp | 5 +- src/Bitmap.h | 2 +- src/Block.cpp | 65 +++++++++++++++ src/Block.h | 35 ++++++++ src/Config.cpp | 66 +++++++++++++++ src/Config.h | 42 ++++++++++ src/DritteFont.cpp | 162 ++++++++++++++++++++++++++++++++++++ src/DritteFont.h | 42 ++++++++++ src/Font.cpp | 44 +--------- src/Font.h | 34 +------- src/MainFont.cpp | 91 ++++++++++++++++++++ src/MainFont.h | 53 ++++++++++++ 20 files changed, 631 insertions(+), 80 deletions(-) rename res/{font.bmp => font1.bmp} (100%) create mode 100644 res/font1.toml create mode 100644 res/font2.bmp create mode 100644 res/font2.toml create mode 100644 res/font3.ppm create mode 100644 res/font3.toml create mode 100644 src/Block.cpp create mode 100644 src/Block.h create mode 100644 src/Config.cpp create mode 100644 src/Config.h create mode 100644 src/DritteFont.cpp create mode 100644 src/DritteFont.h create mode 100644 src/MainFont.cpp create mode 100644 src/MainFont.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b41e461..60d47c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,10 +21,13 @@ file(GLOB_RECURSE TESTS test/*.cpp) include_directories(src) include_directories(test) +#toml +include_directories(lib/toml) + set(LIB_PATH "${CMAKE_SOURCE_DIR}/../library") include_directories(${LIB_PATH}/include) -add_executable(TextRenderer ${SOURCES} ${HEADERS} main/main.cpp) +add_executable(TextRenderer ${SOURCES} ${HEADERS} main/main.cpp src/Font.cpp src/Font.h src/DritteFont.cpp src/DritteFont.h src/Config.cpp src/Config.h src/Block.cpp src/Block.h) target_link_libraries(TextRenderer ${LIB_PATH}/lib/liblibrary.a) diff --git a/main/main.cpp b/main/main.cpp index a5541a8..033a82a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,8 +1,8 @@ -#include - -#include "add.h" +//#include "add.h" #include "Bitmap.h" -#include "Font.h" +#include "MainFont.h" + +#include /** * @author: Julian Hinxlage @@ -12,7 +12,7 @@ * Currently only to test. */ int main() { - Font font("../res/font.bmp"); + MainFont font("../res/font2.bmp", "../res/font2.toml"); std::string str; std::cout << "string to draw: "; @@ -33,4 +33,4 @@ int main() { } return 0; -} \ No newline at end of file +} diff --git a/res/font.bmp b/res/font1.bmp similarity index 100% rename from res/font.bmp rename to res/font1.bmp diff --git a/res/font1.toml b/res/font1.toml new file mode 100644 index 0000000..fb5c1e4 --- /dev/null +++ b/res/font1.toml @@ -0,0 +1,11 @@ +xOffset = 2 +yOffset = 2 +xSize = 5 +ySize = 7 +xCount = 18 +yCount = 4 +xStart = 1 +yStart = 1 +fillValue = 0xffffff +firstChar = 32 +pixelSize = 1 \ No newline at end of file diff --git a/res/font2.bmp b/res/font2.bmp new file mode 100644 index 0000000000000000000000000000000000000000..1962db214e9d27bdf82af87095deea4186877bb4 GIT binary patch literal 393354 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