diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml deleted file mode 100644 index 2627318..0000000 --- a/.github/workflows/appimage.yml +++ /dev/null @@ -1,98 +0,0 @@ -name: "ci" - -on: - push: - tags: "**" - workflow_dispatch: - -defaults: - run: - shell: bash - -jobs: - appimage: - runs-on: ubuntu-18.04 - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - submodules: true - - - name: Install dependencies - run: | - sudo add-apt-repository -y ppa:beineri/opt-qt-5.15.2-bionic - sudo apt-get update -qq - sudo apt-get install -y \ - build-essential make wget libgl1-mesa-dev \ - qt515declarative qt515graphicaleffects \ - qt515quickcontrols qt515quickcontrols2 - - - name: Download QT appimage builder - run: | - wget -c -O linuxdeployqt.AppImage \ - https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage - chmod a+x linuxdeployqt.AppImage - - - name: Build project - run: | - source /opt/qt*/bin/qt*-env.sh && \ - qmake -v && \ - qmake CONFIG+=release PREFIX=/usr && \ - make -j$(nproc) - - - name: Install to appdir - run: | - source /opt/qt*/bin/qt*-env.sh && \ - make INSTALL_ROOT=appdir -j$(nproc) install - - - name: Extract version number - run: | - # Extract version for linuxdeployqt to name the file. Use the tag as - # release name but remove prefix. - echo "VERSION=$(echo '${{ github.ref }}' | sed 's;.*/;;')" >> $GITHUB_ENV - - - name: Build appimage directory - run: | - mkdir -p \ - appdir/usr/bin \ - appdir/usr/lib \ - appdir/usr/share/applications \ - appdir/usr/share/metainfo \ - appdir/usr/share/icons/hicolor/128x128/apps - - cp cool-retro-term appdir/usr/bin/ - cp cool-retro-term.desktop appdir/usr/share/applications/ - cp packaging/appdata/cool-retro-term.appdata.xml appdir/usr/share/metainfo/ - cp app/icons/128x128/cool-retro-term.png appdir/usr/share/icons/hicolor/128x128/apps/ - cp -r ./app/qml appdir/usr/ - # Workaround for https://github.com/probonopd/linuxdeployqt/issues/78 - cp -r ./qmltermwidget/QMLTermWidget appdir/usr/qml/ - - find appdir | sort - - - name: Build appimage - run: | - source /opt/qt*/bin/qt*-env.sh && \ - ./linuxdeployqt.AppImage appdir/usr/share/applications/cool-retro-term.desktop \ - -verbose=1 -appimage \ - -qmldir=./app/qml/ \ - -qmldir=./qmltermwidget/ - env: - # Unset environment variables - QTDIR: - QT_PLUGIN_PATH: - LD_LIBRARY_PATH: - - - name: Upload release - uses: softprops/action-gh-release@v1 - with: - body: appimage release - files: ./**/Cool_Retro_Term-*-x86_64.AppImage - - - name: Clean up - if: always() - run: | - find appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq - make clean - rm -rf appdir diff --git a/.github/workflows/build-appimage.yml b/.github/workflows/build-appimage.yml new file mode 100644 index 0000000..de6321e --- /dev/null +++ b/.github/workflows/build-appimage.yml @@ -0,0 +1,54 @@ +name: Build AppImage + +on: + workflow_dispatch: + push: + branches: + - main + pull_request: + +jobs: + build-appimage: + name: Build (Linux, AppImage) + runs-on: ubuntu-22.04 + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install build deps + run: | + sudo apt update + sudo apt install -y build-essential rsync wget + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: 6.10.0 + dir: .. + modules: qtshadertools + setup-python: false + cache: true + + - name: Build AppImage + run: | + ./scripts/build-appimage.sh + + - name: Collect artifact + run: | + mkdir -p release + mv ./*.AppImage release/ + + - name: Attestation + uses: actions/attest-build-provenance@v1 + with: + subject-path: ./release/* + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: cool-retro-term-appimage + path: ./release/* diff --git a/.github/workflows/build-dmg.yml b/.github/workflows/build-dmg.yml new file mode 100644 index 0000000..84c0b83 --- /dev/null +++ b/.github/workflows/build-dmg.yml @@ -0,0 +1,50 @@ +name: Build DMG + +on: + workflow_dispatch: + push: + branches: + - main + pull_request: + +jobs: + build-dmg: + name: Build (macOS, DMG) + runs-on: macos-14 + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: 6.10.* + modules: qtshadertools + setup-python: true + python-version: '3.11' + cache: true + + - name: Build DMG + run: | + JOBS="$(sysctl -n hw.ncpu)" + ./scripts/build-dmg.sh + + - name: Collect artifact + run: | + mkdir -p release + mv ./*.dmg release/ + + - name: Attestation + uses: actions/attest-build-provenance@v1 + with: + subject-path: ./release/* + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: cool-retro-term-dmg + path: ./release/* diff --git a/.gitignore b/.gitignore index a6f396d..c96737e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,10 +41,17 @@ Makefile* *.json # Excludes compiled files + imports cool-retro-term +build + +# Linux + +*.AppImage # Mac OSX .DS_Store *.app +*.dmg diff --git a/.gitmodules b/.gitmodules index e1c714f..44b34fb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,6 @@ path = qmltermwidget url = https://github.com/Swordfish90/qmltermwidget branch = unstable +[submodule "KDSingleApplication"] + path = KDSingleApplication + url = https://github.com/KDAB/KDSingleApplication.git diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ce8f803..0000000 --- a/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -sudo: required -dist: trusty -language: c++ - -install: - - sudo add-apt-repository -y ppa:beineri/opt-qt58-trusty - - sudo apt-get update -qq - - sudo apt-get -y install build-essential qt58declarative qt58graphicaleffects qt58quickcontrols libgl1-mesa-dev - - source /opt/qt*/bin/qt*-env.sh - -script: - - qmake CONFIG+=release PREFIX=/usr - - make -j$(nproc) - - mkdir -p appdir/usr/share/metainfo appdir/usr/bin - - cp packaging/appdata/cool-retro-term.appdata.xml appdir/usr/share/metainfo/ - - cp cool-retro-term appdir/usr/bin/ - - cp ./cool-retro-term.desktop appdir/ - - cp ./app/icons/128x128/cool-retro-term.png appdir/ - - cp -r ./app/qml appdir/usr/ - - cp -r ./qmltermwidget/QMLTermWidget appdir/usr/qml/ # Workaround for https://github.com/probonopd/linuxdeployqt/issues/78 - - wget -c https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage - - chmod a+x linuxdeployqt-*.AppImage - - unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH - - export VERSION=$(git rev-parse --short HEAD) # linuxdeployqt uses this for naming the file - - ./linuxdeployqt-*.AppImage appdir/usr/bin/cool-retro-term -qmldir=./app/qml/ -qmldir=./qmltermwidget/ # -verbose=3 2>&1 | grep "path:" -C 3 - - ./linuxdeployqt-*.AppImage appdir/usr/bin/cool-retro-term -qmldir=./app/qml/ -qmldir=./qmltermwidget/ -verbose=2 -appimage - -after_success: - - find appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq - - # curl --upload-file Cool*.AppImage https://transfer.sh/Cool_Retro_Term-git.$(git rev-parse --short HEAD)-x86_64.AppImage - - wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh - - bash upload.sh Cool*.AppImage* - -branches: - except: - - # Do not build tags that we create when we upload to GitHub Releases - - /^(?i:continuous)/ diff --git a/KDSingleApplication b/KDSingleApplication new file mode 160000 index 0000000..1848dd6 --- /dev/null +++ b/KDSingleApplication @@ -0,0 +1 @@ +Subproject commit 1848dd64e80e37326da4a22b2c1f45f2a1c4f231 diff --git a/README.md b/README.md index df89bb1..b591352 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ It has been designed to be eye-candy, customizable, and reasonably lightweight. It uses the QML port of qtermwidget (Konsole): https://github.com/Swordfish90/qmltermwidget. -This terminal emulator works under Linux and macOS and requires Qt5. It's suggested that you stick to the latest LTS version. +This terminal emulator works under Linux and macOS and requires Qt6. Settings such as colors, fonts, and effects can be accessed via context menu. diff --git a/app/app.pro b/app/app.pro index 1e42dcc..685fdc1 100644 --- a/app/app.pro +++ b/app/app.pro @@ -1,20 +1,99 @@ QT += qml quick widgets sql quickcontrols2 -TARGET = cool-retro-term +TARGET = cool-retro-term +APP_VERSION = $$system(git -C $$PWD/.. describe --tags --always --dirty=-dirty) +isEmpty(APP_VERSION): APP_VERSION = "unknown" +DEFINES += APP_VERSION=\\\"$$APP_VERSION\\\" + +# TODO: When migrating to CMake, use KDSingleApplication's CMakeLists.txt instead of these manual sources. +INCLUDEPATH += $$PWD/../KDSingleApplication/src +HEADERS += \ + $$PWD/../KDSingleApplication/src/kdsingleapplication.h \ + $$PWD/../KDSingleApplication/src/kdsingleapplication_lib.h \ + $$PWD/../KDSingleApplication/src/kdsingleapplication_localsocket_p.h +SOURCES += \ + $$PWD/../KDSingleApplication/src/kdsingleapplication.cpp \ + $$PWD/../KDSingleApplication/src/kdsingleapplication_localsocket.cpp +DEFINES += KDSINGLEAPPLICATION_STATIC_BUILD DESTDIR = $$OUT_PWD/../ HEADERS += \ fileio.h \ - monospacefontmanager.h + fontmanager.h \ + fontlistmodel.h -SOURCES = main.cpp \ +SOURCES += main.cpp \ fileio.cpp \ - monospacefontmanager.cpp + fontmanager.cpp \ + fontlistmodel.cpp macx:ICON = icons/crt.icns RESOURCES += qml/resources.qrc +# Shader compilation (Qt Shader Baker) +QSB_BIN = $$[QT_HOST_BINS]/qsb +isEmpty(QSB_BIN): QSB_BIN = $$[QT_INSTALL_BINS]/qsb + +SHADERS_DIR = $${_PRO_FILE_PWD_}/shaders +SHADERS += $$files($$SHADERS_DIR/*.frag) $$files($$SHADERS_DIR/*.vert) +SHADERS -= $$SHADERS_DIR/terminal_dynamic.frag +SHADERS -= $$SHADERS_DIR/terminal_static.frag +SHADERS -= $$SHADERS_DIR/passthrough.vert + +qsb.input = SHADERS +qsb.output = ../../app/shaders/${QMAKE_FILE_NAME}.qsb +qsb.commands = $$QSB_BIN --glsl \"100 es,120,150\" --hlsl 50 --msl 12 --qt6 -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN} +qsb.clean = $$qsb.output +qsb.name = qsb ${QMAKE_FILE_IN} +qsb.variable_out = QSB_FILES +QMAKE_EXTRA_COMPILERS += qsb +PRE_TARGETDEPS += $$QSB_FILES +OTHER_FILES += $$SHADERS $$QSB_FILES + +DYNAMIC_SHADER = $$SHADERS_DIR/terminal_dynamic.frag +STATIC_SHADER = $$SHADERS_DIR/terminal_static.frag + +RASTER_MODES = 0 1 2 3 4 +BINARY_FLAGS = 0 1 +VARIANT_SHADER_DIR = $$relative_path($$PWD/shaders, $$OUT_PWD) +VARIANT_OUTPUTS = + +for(raster_mode, RASTER_MODES) { + for(burn_in, BINARY_FLAGS) { + for(display_frame, BINARY_FLAGS) { + for(chroma_on, BINARY_FLAGS) { + dynamic_variant = terminal_dynamic_raster$${raster_mode}_burn$${burn_in}_frame$${display_frame}_chroma$${chroma_on} + dynamic_output = $${VARIANT_SHADER_DIR}/$${dynamic_variant}.frag.qsb + dynamic_target = shader_variant_$${dynamic_variant} + $${dynamic_target}.target = $${dynamic_output} + $${dynamic_target}.depends = $$DYNAMIC_SHADER + $${dynamic_target}.commands = $$QSB_BIN --glsl \"100 es,120,150\" --hlsl 50 --msl 12 --qt6 -DCRT_RASTER_MODE=$${raster_mode} -DCRT_BURN_IN=$${burn_in} -DCRT_DISPLAY_FRAME=$${display_frame} -DCRT_CHROMA=$${chroma_on} -o $${dynamic_output} $$DYNAMIC_SHADER + QMAKE_EXTRA_TARGETS += $${dynamic_target} + VARIANT_OUTPUTS += $${dynamic_output} + } + } + } +} + +for(rgb_shift, BINARY_FLAGS) { + for(bloom_on, BINARY_FLAGS) { + for(curve_on, BINARY_FLAGS) { + for(shine_on, BINARY_FLAGS) { + static_variant = terminal_static_rgb$${rgb_shift}_bloom$${bloom_on}_curve$${curve_on}_shine$${shine_on} + static_output = $${VARIANT_SHADER_DIR}/$${static_variant}.frag.qsb + static_target = shader_variant_$${static_variant} + $${static_target}.target = $${static_output} + $${static_target}.depends = $$STATIC_SHADER + $${static_target}.commands = $$QSB_BIN --glsl \"100 es,120,150\" --hlsl 50 --msl 12 --qt6 -DCRT_RGB_SHIFT=$${rgb_shift} -DCRT_BLOOM=$${bloom_on} -DCRT_CURVATURE=$${curve_on} -DCRT_FRAME_SHININESS=$${shine_on} -o $${static_output} $$STATIC_SHADER + QMAKE_EXTRA_TARGETS += $${static_target} + VARIANT_OUTPUTS += $${static_output} + } + } + } +} +PRE_TARGETDEPS += $${VARIANT_OUTPUTS} + ######################################### ## INTALLS ######################################### diff --git a/app/fontlistmodel.cpp b/app/fontlistmodel.cpp new file mode 100644 index 0000000..4d176c8 --- /dev/null +++ b/app/fontlistmodel.cpp @@ -0,0 +1,94 @@ +#include "fontlistmodel.h" + +FontListModel::FontListModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +int FontListModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_fonts.size(); +} + +QVariant FontListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_fonts.size()) { + return QVariant(); + } + + const FontEntry &font = m_fonts.at(index.row()); + + switch (role) { + case NameRole: + return font.name; + case TextRole: + return font.text; + case SourceRole: + return font.source; + case BaseWidthRole: + return font.baseWidth; + case PixelSizeRole: + return font.pixelSize; + case LowResolutionRole: + return font.lowResolutionFont; + case IsSystemRole: + return font.isSystemFont; + case FamilyRole: + return font.family; + case FallbackNameRole: + return font.fallbackName; + default: + return QVariant(); + } +} + +QHash FontListModel::roleNames() const +{ + QHash roles; + roles[NameRole] = "name"; + roles[TextRole] = "text"; + roles[SourceRole] = "source"; + roles[BaseWidthRole] = "baseWidth"; + roles[PixelSizeRole] = "pixelSize"; + roles[LowResolutionRole] = "lowResolutionFont"; + roles[IsSystemRole] = "isSystemFont"; + roles[FamilyRole] = "family"; + roles[FallbackNameRole] = "fallbackName"; + return roles; +} + +void FontListModel::setFonts(const QVector &fonts) +{ + beginResetModel(); + m_fonts = fonts; + endResetModel(); + emit countChanged(); +} + +const QVector &FontListModel::fonts() const +{ + return m_fonts; +} + +QVariantMap FontListModel::get(int index) const +{ + QVariantMap map; + if (index < 0 || index >= m_fonts.size()) { + return map; + } + + const FontEntry &font = m_fonts.at(index); + map.insert("name", font.name); + map.insert("text", font.text); + map.insert("source", font.source); + map.insert("baseWidth", font.baseWidth); + map.insert("pixelSize", font.pixelSize); + map.insert("lowResolutionFont", font.lowResolutionFont); + map.insert("isSystemFont", font.isSystemFont); + map.insert("family", font.family); + map.insert("fallbackName", font.fallbackName); + return map; +} diff --git a/app/fontlistmodel.h b/app/fontlistmodel.h new file mode 100644 index 0000000..00fda4c --- /dev/null +++ b/app/fontlistmodel.h @@ -0,0 +1,59 @@ +#ifndef FONTLISTMODEL_H +#define FONTLISTMODEL_H + +#include +#include +#include +#include +#include + +struct FontEntry +{ + QString name; + QString text; + QString source; + qreal baseWidth = 1.0; + int pixelSize = 0; + bool lowResolutionFont = false; + bool isSystemFont = false; + QString family; + QString fallbackName; +}; + +class FontListModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + +public: + explicit FontListModel(QObject *parent = nullptr); + + enum Roles { + NameRole = Qt::UserRole + 1, + TextRole, + SourceRole, + BaseWidthRole, + PixelSizeRole, + LowResolutionRole, + IsSystemRole, + FamilyRole, + FallbackNameRole + }; + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + + void setFonts(const QVector &fonts); + const QVector &fonts() const; + + Q_INVOKABLE QVariantMap get(int index) const; + +signals: + void countChanged(); + +private: + QVector m_fonts; +}; + +#endif // FONTLISTMODEL_H diff --git a/app/fontmanager.cpp b/app/fontmanager.cpp new file mode 100644 index 0000000..3d60423 --- /dev/null +++ b/app/fontmanager.cpp @@ -0,0 +1,584 @@ +#include "fontmanager.h" + +#include +#include +#include +#include +#include + +namespace { +constexpr int kModernRasterization = 4; +constexpr int kBaseFontPixelHeight = 32; +constexpr int kSystemFontPixelSize = 32; +} + +FontManager::FontManager(QObject *parent) + : QObject(parent) + , m_fontListModel(this) + , m_filteredFontListModel(this) +{ + populateBundledFonts(); + populateSystemFonts(); + m_fontListModel.setFonts(m_allFonts); + updateFilteredFonts(); + updateComputedFont(); +} + +QStringList FontManager::retrieveMonospaceFonts() +{ + QStringList result; + + QFontDatabase fontDatabase; + const QStringList fontFamilies = fontDatabase.families(); + + for (const QString &fontFamily : fontFamilies) { + QFont font(fontFamily); + if (fontDatabase.isFixedPitch(font.family())) { + result.append(fontFamily); + } + } + + return result; +} + +void FontManager::refresh() +{ + updateFilteredFonts(); + updateComputedFont(); +} + +FontListModel *FontManager::fontList() +{ + return &m_fontListModel; +} + +FontListModel *FontManager::filteredFontList() +{ + return &m_filteredFontListModel; +} + +int FontManager::fontSource() const +{ + return m_fontSource; +} + +void FontManager::setFontSource(int fontSource) +{ + if (m_fontSource == fontSource) { + return; + } + m_fontSource = fontSource; + emit fontSourceChanged(); + updateFilteredFonts(); + updateComputedFont(); +} + +int FontManager::rasterization() const +{ + return m_rasterization; +} + +void FontManager::setRasterization(int rasterization) +{ + if (m_rasterization == rasterization) { + return; + } + m_rasterization = rasterization; + emit rasterizationChanged(); + updateFilteredFonts(); + updateComputedFont(); +} + +QString FontManager::fontName() const +{ + return m_fontName; +} + +void FontManager::setFontName(const QString &fontName) +{ + if (m_fontName == fontName) { + return; + } + m_fontName = fontName; + emit fontNameChanged(); + updateFilteredFonts(); + updateComputedFont(); +} + +qreal FontManager::fontScaling() const +{ + return m_fontScaling; +} + +void FontManager::setFontScaling(qreal fontScaling) +{ + if (qFuzzyCompare(m_fontScaling, fontScaling)) { + return; + } + m_fontScaling = fontScaling; + emit fontScalingChanged(); + updateComputedFont(); +} + +qreal FontManager::fontWidth() const +{ + return m_fontWidth; +} + +void FontManager::setFontWidth(qreal fontWidth) +{ + if (qFuzzyCompare(m_fontWidth, fontWidth)) { + return; + } + m_fontWidth = fontWidth; + emit fontWidthChanged(); + updateComputedFont(); +} + +qreal FontManager::lineSpacing() const +{ + return m_lineSpacing; +} + +void FontManager::setLineSpacing(qreal lineSpacing) +{ + if (qFuzzyCompare(m_lineSpacing, lineSpacing)) { + return; + } + m_lineSpacing = lineSpacing; + emit lineSpacingChanged(); + updateComputedFont(); +} + +qreal FontManager::baseFontScaling() const +{ + return m_baseFontScaling; +} + +void FontManager::setBaseFontScaling(qreal baseFontScaling) +{ + if (qFuzzyCompare(m_baseFontScaling, baseFontScaling)) { + return; + } + m_baseFontScaling = baseFontScaling; + emit baseFontScalingChanged(); + updateComputedFont(); +} + +bool FontManager::lowResolutionFont() const +{ + return m_lowResolutionFont; +} + +void FontManager::setFontSubstitutions(const QString &family, const QStringList &substitutes) +{ + if (family.isEmpty()) { + return; + } + + QFont::removeSubstitutions(family); + + if (substitutes.isEmpty()) { + return; + } + + QFont::insertSubstitutions(family, substitutes); +} + +void FontManager::removeFontSubstitution(const QString &family) +{ + if (family.isEmpty()) { + return; + } + + QFont::removeSubstitutions(family); +} + +void FontManager::populateBundledFonts() +{ + m_allFonts.clear(); + + addBundledFont( + "TERMINESS_SCALED", + "Terminess", + ":/fonts/terminus/TerminessNerdFontMono-Regular.ttf", + 1.0, + 12, + true); + addBundledFont( + "BIGBLUE_TERMINAL_SCALED", + "BigBlue Terminal", + ":/fonts/bigblue-terminal/BigBlueTerm437NerdFontMono-Regular.ttf", + 1.0, + 12, + true); + addBundledFont( + "EXCELSIOR_SCALED", + "Fixedsys Excelsior", + ":/fonts/fixedsys-excelsior/FSEX301-L2.ttf", + 1.0, + 16, + true, + "UNSCII_16_SCALED"); + addBundledFont( + "GREYBEARD_SCALED", + "Greybeard", + ":/fonts/greybeard/Greybeard-16px.ttf", + 1.0, + 16, + true, + "UNSCII_16_SCALED"); + addBundledFont( + "COMMODORE_PET_SCALED", + "Commodore PET", + ":/fonts/pet-me/PetMe.ttf", + 0.5, + 8, + true, + "UNSCII_8_SCALED"); + addBundledFont( + "GOHU_11_SCALED", + "Gohu 11", + ":/fonts/gohu/GohuFont11NerdFontMono-Regular.ttf", + 1.0, + 11, + true); + addBundledFont( + "COZETTE_SCALED", + "Cozette", + ":/fonts/cozette/CozetteVector.ttf", + 1.0, + 13, + true); + addBundledFont( + "UNSCII_8_SCALED", + "Unscii 8", + ":/fonts/unscii/unscii-8.ttf", + 0.5, + 8, + true, + "UNSCII_8_SCALED"); + addBundledFont( + "UNSCII_8_THIN_SCALED", + "Unscii 8 Thin", + ":/fonts/unscii/unscii-8-thin.ttf", + 0.5, + 8, + true, + "UNSCII_8_SCALED"); + addBundledFont( + "UNSCII_16_SCALED", + "Unscii 16", + ":/fonts/unscii/unscii-16-full.ttf", + 1.0, + 16, + true, + "UNSCII_16_SCALED"); + addBundledFont( + "APPLE_II_SCALED", + "Apple ][", + ":/fonts/apple2/PrintChar21.ttf", + 0.5, + 8, + true, + "UNSCII_8_SCALED"); + addBundledFont( + "ATARI_400_SCALED", + "Atari 400-800", + ":/fonts/atari-400-800/AtariClassic-Regular.ttf", + 0.5, + 8, + true, + "UNSCII_8_SCALED"); + addBundledFont( + "COMMODORE_64_SCALED", + "Commodore 64", + ":/fonts/pet-me/PetMe64.ttf", + 0.5, + 8, + true, + "UNSCII_8_SCALED"); + addBundledFont( + "IBM_EGA_8x8", + "IBM EGA 8x8", + ":/fonts/oldschool-pc-fonts/PxPlus_IBM_EGA_8x8.ttf", + 0.5, + 8, + true, + "UNSCII_8_SCALED"); + addBundledFont( + "IBM_VGA_8x16", + "IBM VGA 8x16", + ":/fonts/oldschool-pc-fonts/PxPlus_IBM_VGA_8x16.ttf", + 1.0, + 16, + true, + "UNSCII_16_SCALED"); + + addBundledFont( + "TERMINESS", + "Terminess", + ":/fonts/terminus/TerminessNerdFontMono-Regular.ttf", + 1.0, + 32, + false); + addBundledFont( + "HACK", + "Hack", + ":/fonts/hack/HackNerdFontMono-Regular.ttf", + 1.0, + 32, + false); + addBundledFont( + "FIRA_CODE", + "Fira Code", + ":/fonts/fira-code/FiraCodeNerdFontMono-Regular.ttf", + 1.0, + 32, + false); + addBundledFont( + "IOSEVKA", + "Iosevka", + ":/fonts/iosevka/IosevkaTermNerdFontMono-Regular.ttf", + 1.0, + 32, + false); + addBundledFont( + "JETBRAINS_MONO", + "JetBrains Mono", + ":/fonts/jetbrains-mono/JetBrainsMonoNerdFontMono-Regular.ttf", + 1.0, + 32, + false); + addBundledFont( + "IBM_3278", + "IBM 3278", + ":/fonts/ibm-3278/3270NerdFontMono-Regular.ttf", + 1.0, + 32, + false); + addBundledFont( + "SOURCE_CODE_PRO", + "Source Code Pro", + ":/fonts/source-code-pro/SauceCodeProNerdFontMono-Regular.ttf", + 1.0, + 32, + false); + addBundledFont( + "DEPARTURE_MONO_SCALED", + "Departure Mono", + ":/fonts/departure-mono/DepartureMonoNerdFontMono-Regular.otf", + 1.0, + 11, + true); + addBundledFont( + "OPENDYSLEXIC", + "OpenDyslexic", + ":/fonts/opendyslexic/OpenDyslexicMNerdFontMono-Regular.otf", + 1.0, + 32, + false); +} + +void FontManager::addBundledFont(const QString &name, + const QString &text, + const QString &source, + qreal baseWidth, + int pixelSize, + bool lowResolutionFont, + const QString &fallbackName) +{ + FontEntry entry; + entry.name = name; + entry.text = text; + entry.source = source; + entry.pixelSize = pixelSize; + entry.lowResolutionFont = lowResolutionFont; + entry.isSystemFont = false; + entry.fallbackName = fallbackName; + entry.family = resolveFontFamily(source); + entry.baseWidth = lowResolutionFont + ? computeBaseWidth(entry.family, pixelSize, baseWidth) + : baseWidth; + m_allFonts.append(entry); +} + +void FontManager::populateSystemFonts() +{ + const QStringList families = retrieveMonospaceFonts(); + for (const QString &family : families) { + if (m_bundledFamilies.contains(family)) { + continue; + } + FontEntry entry; + entry.name = family; + entry.text = family; + entry.source = QString(); + entry.baseWidth = 1.0; + entry.pixelSize = kSystemFontPixelSize; + entry.lowResolutionFont = false; + entry.isSystemFont = true; + entry.family = family; + m_allFonts.append(entry); + } +} + +void FontManager::updateFilteredFonts() +{ + QVector filtered; + bool fontNameFound = false; + const bool modernMode = (m_rasterization == kModernRasterization); + + for (const FontEntry &font : m_allFonts) { + const bool isBundled = !font.isSystemFont; + const bool matchesSource = (m_fontSource == 0 && isBundled) + || (m_fontSource == 1 && font.isSystemFont); + + if (!matchesSource) { + continue; + } + + const bool matchesRasterization = font.isSystemFont + || (modernMode == !font.lowResolutionFont); + + if (!matchesRasterization) { + continue; + } + + filtered.append(font); + if (font.name == m_fontName) { + fontNameFound = true; + } + } + + if (!fontNameFound && !filtered.isEmpty()) { + if (m_fontName != filtered.first().name) { + m_fontName = filtered.first().name; + emit fontNameChanged(); + } + } + + m_filteredFontListModel.setFonts(filtered); + emit filteredFontListChanged(); +} + +void FontManager::updateComputedFont() +{ + const FontEntry *font = findFontByName(m_fontName); + if (!font) { + const QVector &filteredFonts = m_filteredFontListModel.fonts(); + if (!filteredFonts.isEmpty()) { + font = &filteredFonts.first(); + } + } + + if (!font) { + return; + } + + const qreal totalFontScaling = m_baseFontScaling * m_fontScaling; + const qreal targetPixelHeight = kBaseFontPixelHeight * totalFontScaling; + const qreal lineSpacingFactor = m_lineSpacing; + + const int lineSpacing = qRound(targetPixelHeight * lineSpacingFactor); + const int pixelSize = font->lowResolutionFont + ? font->pixelSize + : static_cast(targetPixelHeight); + + const qreal nativeLineHeight = font->pixelSize + qRound(font->pixelSize * lineSpacingFactor); + const qreal targetLineHeight = targetPixelHeight + lineSpacing; + const qreal screenScaling = font->lowResolutionFont + ? (nativeLineHeight > 0 ? targetLineHeight / nativeLineHeight : 1.0) + : 1.0; + + const qreal fontWidth = font->baseWidth * m_fontWidth; + + QString fontFamily = font->family.isEmpty() ? font->name : font->family; + QString fallbackFontFamily; + + if (!font->fallbackName.isEmpty() && font->fallbackName != font->name) { + const FontEntry *fallback = findFontByName(font->fallbackName); + if (fallback) { + fallbackFontFamily = fallback->family.isEmpty() ? fallback->name : fallback->family; + } + } + + QStringList fallbackChain; + if (!fallbackFontFamily.isEmpty()) { + fallbackChain.append(fallbackFontFamily); + } +#if defined(Q_OS_MAC) + fallbackChain.append(QStringLiteral("Menlo")); +#else + fallbackChain.append(QStringLiteral("Monospace")); +#endif + setFontSubstitutions(fontFamily, fallbackChain); + + if (m_lowResolutionFont != font->lowResolutionFont) { + m_lowResolutionFont = font->lowResolutionFont; + emit lowResolutionFontChanged(); + } + + emit terminalFontChanged(fontFamily, + pixelSize, + lineSpacing, + screenScaling, + fontWidth, + fallbackFontFamily, + font->lowResolutionFont); +} + +const FontEntry *FontManager::findFontByName(const QString &name) const +{ + for (const FontEntry &font : m_allFonts) { + if (font.name == name) { + return &font; + } + } + return nullptr; +} + +QString FontManager::resolveFontFamily(const QString &sourcePath) +{ + const auto cached = m_loadedFamilies.constFind(sourcePath); + if (cached != m_loadedFamilies.constEnd()) { + return cached.value(); + } + + const int fontId = QFontDatabase::addApplicationFont(sourcePath); + QString family; + if (fontId != -1) { + const QStringList families = QFontDatabase::applicationFontFamilies(fontId); + if (!families.isEmpty()) { + family = families.first(); + } + } + + if (!family.isEmpty()) { + m_bundledFamilies.insert(family); + } + + m_loadedFamilies.insert(sourcePath, family); + return family; +} + +qreal FontManager::computeBaseWidth(const QString &family, int pixelSize, qreal fallbackWidth) const +{ + if (family.isEmpty()) { + return fallbackWidth; + } + + QFont font(family); + font.setPixelSize(pixelSize); + QFontMetricsF metrics(font); + + const qreal glyphWidth = metrics.horizontalAdvance(QLatin1String("M")); + const qreal glyphHeight = metrics.height(); + if (glyphWidth <= 0.0 || glyphHeight <= 0.0) { + return fallbackWidth; + } + + const qreal targetRatio = 0.5; + qreal computedWidth = (targetRatio * glyphHeight) / glyphWidth; + return qBound(0.25, computedWidth, 2.0); +} diff --git a/app/fontmanager.h b/app/fontmanager.h new file mode 100644 index 0000000..b8621df --- /dev/null +++ b/app/fontmanager.h @@ -0,0 +1,111 @@ +#ifndef FONTMANAGER_H +#define FONTMANAGER_H + +#include +#include +#include +#include + +#include "fontlistmodel.h" + +class FontManager : public QObject +{ + Q_OBJECT + Q_PROPERTY(FontListModel *fontList READ fontList CONSTANT) + Q_PROPERTY(FontListModel *filteredFontList READ filteredFontList NOTIFY filteredFontListChanged) + Q_PROPERTY(int fontSource READ fontSource WRITE setFontSource NOTIFY fontSourceChanged) + Q_PROPERTY(int rasterization READ rasterization WRITE setRasterization NOTIFY rasterizationChanged) + Q_PROPERTY(QString fontName READ fontName WRITE setFontName NOTIFY fontNameChanged) + Q_PROPERTY(qreal fontScaling READ fontScaling WRITE setFontScaling NOTIFY fontScalingChanged) + Q_PROPERTY(qreal fontWidth READ fontWidth WRITE setFontWidth NOTIFY fontWidthChanged) + Q_PROPERTY(qreal lineSpacing READ lineSpacing WRITE setLineSpacing NOTIFY lineSpacingChanged) + Q_PROPERTY(qreal baseFontScaling READ baseFontScaling WRITE setBaseFontScaling NOTIFY baseFontScalingChanged) + Q_PROPERTY(bool lowResolutionFont READ lowResolutionFont NOTIFY lowResolutionFontChanged) + +public: + explicit FontManager(QObject *parent = nullptr); + + Q_INVOKABLE void refresh(); + + FontListModel *fontList(); + FontListModel *filteredFontList(); + + int fontSource() const; + void setFontSource(int fontSource); + + int rasterization() const; + void setRasterization(int rasterization); + + QString fontName() const; + void setFontName(const QString &fontName); + + qreal fontScaling() const; + void setFontScaling(qreal fontScaling); + + qreal fontWidth() const; + void setFontWidth(qreal fontWidth); + + qreal lineSpacing() const; + void setLineSpacing(qreal lineSpacing); + + qreal baseFontScaling() const; + void setBaseFontScaling(qreal baseFontScaling); + + bool lowResolutionFont() const; + +signals: + void fontSourceChanged(); + void rasterizationChanged(); + void fontNameChanged(); + void fontScalingChanged(); + void fontWidthChanged(); + void lineSpacingChanged(); + void baseFontScalingChanged(); + void lowResolutionFontChanged(); + void filteredFontListChanged(); + + void terminalFontChanged(QString fontFamily, + int pixelSize, + int lineSpacing, + qreal screenScaling, + qreal fontWidth, + QString fallbackFontFamily, + bool lowResolutionFont); + +private: + QStringList retrieveMonospaceFonts(); + void populateBundledFonts(); + void populateSystemFonts(); + void addBundledFont(const QString &name, + const QString &text, + const QString &source, + qreal baseWidth, + int pixelSize, + bool lowResolutionFont, + const QString &fallbackName = QString()); + void setFontSubstitutions(const QString &family, const QStringList &substitutes); + void removeFontSubstitution(const QString &family); + void updateFilteredFonts(); + void updateComputedFont(); + const FontEntry *findFontByName(const QString &name) const; + QString resolveFontFamily(const QString &sourcePath); + qreal computeBaseWidth(const QString &family, int pixelSize, qreal fallbackWidth) const; + + FontListModel m_fontListModel; + FontListModel m_filteredFontListModel; + QVector m_allFonts; + + int m_fontSource = 0; + int m_rasterization = 0; + QString m_fontName = QStringLiteral("TERMINESS_SCALED"); + qreal m_fontScaling = 1.0; + qreal m_fontWidth = 1.0; + qreal m_lineSpacing = 0.1; + qreal m_baseFontScaling = 0.75; + bool m_lowResolutionFont = false; + + QHash m_loadedFamilies; + QSet m_bundledFamilies; +}; + +#endif // FONTMANAGER_H diff --git a/app/main.cpp b/app/main.cpp index 30cbf31..da0da72 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -7,15 +7,24 @@ #include #include #include +#include + +#include #include #include -#include #include #include -#include +#include +#include + +#if defined(Q_OS_MAC) +#include +#include +#include +#endif QString getNamedArgument(QStringList args, QString name, QString defaultName) { @@ -31,60 +40,77 @@ QString getNamedArgument(QStringList args, QString name) int main(int argc, char *argv[]) { // Some environmental variable are necessary on certain platforms. - - // This disables QT appmenu under Ubuntu, which is not working with QML apps. - setenv("QT_QPA_PLATFORMTHEME", "", 1); - // Disable Connections slot warnings QLoggingCategory::setFilterRules("qt.qml.connections.warning=false"); + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); -#if defined (Q_OS_LINUX) - setenv("QSG_RENDER_LOOP", "threaded", 0); -#endif +// #if defined (Q_OS_LINUX) +// setenv("QSG_RENDER_LOOP", "threaded", 0); +// #endif #if defined(Q_OS_MAC) // This allows UTF-8 characters usage in OSX. setenv("LC_CTYPE", "UTF-8", 1); + + // Ensure key repeat works for letter keys (disable macOS press-and-hold for this app). + CFPreferencesSetAppValue(CFSTR("ApplePressAndHoldEnabled"), kCFBooleanFalse, kCFPreferencesCurrentApplication); + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); + + // Qt6 macOS default look is still lacking, so let's force Fusion for now + QQuickStyle::setStyle(QStringLiteral("Fusion")); #endif if (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))) { QTextStream cout(stdout, QIODevice::WriteOnly); - cout << "Usage: " << argv[0] << " [--default-settings] [--workdir ] [--program ] [-p|--profile ] [--fullscreen] [-h|--help]" << endl; - cout << " --default-settings Run cool-retro-term with the default settings" << endl; - cout << " --workdir Change working directory to 'dir'" << endl; - cout << " -e Command to execute. This option will catch all following arguments, so use it as the last option." << endl; - cout << " -T Set window title to 'title'." << endl; - cout << " --fullscreen Run cool-retro-term in fullscreen." << endl; - cout << " -p|--profile <prof> Run cool-retro-term with the given profile." << endl; - cout << " -h|--help Print this help." << endl; - cout << " --verbose Print additional information such as profiles and settings." << endl; + cout << "Usage: " << argv[0] << " [--default-settings] [--workdir <dir>] [--program <prog>] [-p|--profile <prof>] [--fullscreen] [-h|--help]" << Qt::endl; + cout << " --default-settings Run cool-retro-term with the default settings" << Qt::endl; + cout << " --workdir <dir> Change working directory to 'dir'" << Qt::endl; + cout << " -e <cmd> Command to execute. This option will catch all following arguments, so use it as the last option." << Qt::endl; + cout << " --fullscreen Run cool-retro-term in fullscreen." << Qt::endl; + cout << " -p|--profile <prof> Run cool-retro-term with the given profile." << Qt::endl; + cout << " -h|--help Print this help." << Qt::endl; + cout << " --verbose Print additional information such as profiles and settings." << Qt::endl; return 0; } - QString appVersion("1.2.0"); + QString appVersion(QStringLiteral(APP_VERSION)); if (argc>1 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) { QTextStream cout(stdout, QIODevice::WriteOnly); - cout << "cool-retro-term " << appVersion << endl; + cout << "cool-retro-term " << appVersion << Qt::endl; return 0; } QApplication app(argc, argv); app.setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, true); + app.setApplicationName(QStringLiteral("cool-retro-term")); + app.setOrganizationName(QStringLiteral("cool-retro-term")); + app.setOrganizationDomain(QStringLiteral("cool-retro-term")); + app.setApplicationVersion(appVersion); + + KDSingleApplication singleApp(QStringLiteral("cool-retro-term")); + + if (!singleApp.isPrimaryInstance()) { + if (singleApp.sendMessage("new-window")) + return 0; + qWarning() << "KDSingleApplication: primary not reachable, continuing as independent instance."; + } QQmlApplicationEngine engine; FileIO fileIO; - MonospaceFontManager monospaceFontManager; + + qmlRegisterType<FontManager>("CoolRetroTerm", 1, 0, "FontManager"); + qmlRegisterUncreatableType<FontListModel>("CoolRetroTerm", 1, 0, "FontListModel", "FontListModel is created by FontManager"); #if !defined(Q_OS_MAC) app.setWindowIcon(QIcon::fromTheme("cool-retro-term", QIcon(":../icons/32x32/cool-retro-term.png"))); +#if defined(Q_OS_LINUX) + QGuiApplication::setDesktopFileName(QStringLiteral("cool-retro-term")); +#endif #else app.setWindowIcon(QIcon(":../icons/32x32/cool-retro-term.png")); #endif - app.setOrganizationName("cool-retro-term"); - app.setOrganizationDomain("cool-retro-term"); - // Manage command line arguments from the cpp side QStringList args = app.arguments(); @@ -101,15 +127,12 @@ int main(int argc, char *argv[]) engine.rootContext()->setContextProperty("workdir", getNamedArgument(args, "--workdir", "$HOME")); engine.rootContext()->setContextProperty("fileIO", &fileIO); - engine.rootContext()->setContextProperty("monospaceSystemFonts", monospaceFontManager.retrieveMonospaceFonts()); - - engine.rootContext()->setContextProperty("devicePixelRatio", app.devicePixelRatio()); // Manage import paths for Linux and OSX. QStringList importPathList = engine.importPathList(); - importPathList.prepend(QCoreApplication::applicationDirPath() + "/qmltermwidget"); - importPathList.prepend(QCoreApplication::applicationDirPath() + "/../PlugIns"); - importPathList.prepend(QCoreApplication::applicationDirPath() + "/../../../qmltermwidget"); + importPathList.append(QCoreApplication::applicationDirPath() + "/qmltermwidget"); + importPathList.append(QCoreApplication::applicationDirPath() + "/../PlugIns"); + importPathList.append(QCoreApplication::applicationDirPath() + "/../../../qmltermwidget"); engine.setImportPathList(importPathList); engine.load(QUrl(QStringLiteral ("qrc:/main.qml"))); @@ -122,5 +145,25 @@ int main(int argc, char *argv[]) // Quit the application when the engine closes. QObject::connect((QObject*) &engine, SIGNAL(quit()), (QObject*) &app, SLOT(quit())); + auto requestNewWindow = [&engine]() { + if (engine.rootObjects().isEmpty()) + return; + + QObject *rootObject = engine.rootObjects().constFirst(); + QMetaObject::invokeMethod(rootObject, "createWindow", Qt::QueuedConnection); + }; + + QObject::connect(&singleApp, &KDSingleApplication::messageReceived, &app, + [&requestNewWindow](const QByteArray &message) { + if (message.isEmpty() || message == QByteArray("new-window")) + requestNewWindow(); + }); + +#if defined(Q_OS_MAC) + QMenu *dockMenu = new QMenu(nullptr); + dockMenu->addAction(QObject::tr("New Window"), [&requestNewWindow]() { requestNewWindow(); }); + dockMenu->setAsDockMenu(); +#endif + return app.exec(); } diff --git a/app/monospacefontmanager.cpp b/app/monospacefontmanager.cpp deleted file mode 100644 index 28e910f..0000000 --- a/app/monospacefontmanager.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "monospacefontmanager.h" - -#include <QDebug> - -MonospaceFontManager::MonospaceFontManager(QObject *parent) : QObject(parent) -{ - -} - -QStringList MonospaceFontManager::retrieveMonospaceFonts() { - QStringList result; - - QFontDatabase fontDatabase; - QStringList fontFamilies = fontDatabase.families(); - - for (int i = 0; i < fontFamilies.size(); i++) { - QString fontFamily = fontFamilies[i]; - QFont font(fontFamily); - if (fontDatabase.isFixedPitch(font.family())) { - result.append(fontFamily); - } - } - - return result; -} diff --git a/app/monospacefontmanager.h b/app/monospacefontmanager.h deleted file mode 100644 index 53064a8..0000000 --- a/app/monospacefontmanager.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MONOSPACEFONTMANAGER_H -#define MONOSPACEFONTMANAGER_H - -#include <QObject> -#include <QFontDatabase> - -class MonospaceFontManager : public QObject -{ - Q_OBJECT -public: - explicit MonospaceFontManager(QObject *parent = nullptr); - Q_INVOKABLE QStringList retrieveMonospaceFonts(); -}; - -#endif // MONOSPACEFONTMANAGER_H diff --git a/app/qml/AboutDialog.qml b/app/qml/AboutDialog.qml index 22becce..c7726db 100644 --- a/app/qml/AboutDialog.qml +++ b/app/qml/AboutDialog.qml @@ -22,14 +22,12 @@ import QtQuick.Controls 2.2 import QtQuick.Layouts 1.1 import QtQuick.Window 2.0 -Window { +ApplicationWindow { id: dialogwindow title: qsTr("About") width: 600 height: 400 - modality: Qt.ApplicationModal - ColumnLayout { anchors.fill: parent anchors.margins: 15 @@ -37,6 +35,7 @@ Window { Text { Layout.alignment: Qt.AlignHCenter text: "cool-retro-term" + color: palette.text font { bold: true pointSize: 18 @@ -100,6 +99,7 @@ Window { Text { Layout.alignment: Qt.AlignCenter horizontalAlignment: Text.AlignHCenter + color: palette.text text: appSettings.version + "\n" + qsTr( "Author: ") + "Filippo Scognamiglio\n" + qsTr( "Email: ") + "flscogna@gmail.com\n" + qsTr( @@ -115,7 +115,8 @@ Window { TextArea { readOnly: true wrapMode: TextEdit.Wrap - text: "Copyright (c) 2013-2021 Filippo Scognamiglio <flscogna@gmail.com>\n\n" + color: palette.text + text: "Copyright (c) 2013-2025 Filippo Scognamiglio <flscogna@gmail.com>\n\n" + "https://github.com/Swordfish90/cool-retro-term\n\n" + "cool-retro-term is free software: you can redistribute it and/or modify " + "it under the terms of the GNU General Public License as published by " diff --git a/app/qml/ApplicationSettings.qml b/app/qml/ApplicationSettings.qml index 424f0bd..b975a22 100644 --- a/app/qml/ApplicationSettings.qml +++ b/app/qml/ApplicationSettings.qml @@ -19,6 +19,7 @@ *******************************************************************************/ import QtQuick 2.2 import QtQuick.Controls 2.0 +import CoolRetroTerm 1.0 import "utils.js" as Utils @@ -27,30 +28,24 @@ QtObject { readonly property int profileVersion: 2 // STATIC CONSTANTS //////////////////////////////////////////////////////// - readonly property real screenCurvatureSize: 0.4 + readonly property real screenCurvatureSize: 0.6 readonly property real minimumFontScaling: 0.25 readonly property real maximumFontScaling: 2.50 - readonly property real minBurnInFadeTime: 160 - readonly property real maxBurnInFadeTime: 1600 + readonly property int defaultMargin: 16 + + readonly property real minBurnInFadeTime: 0.16 + readonly property real maxBurnInFadeTime: 1.6 property bool isMacOS: Qt.platform.os === "osx" // GENERAL SETTINGS /////////////////////////////////////////////////////// - property int x: 100 - property int y: 100 - property int width: 1024 - property int height: 768 - - property bool fullscreen: false property bool showMenubar: false - property string wintitle: "cool-retro-term" - property bool showTerminalSize: true property real windowScaling: 1.0 - property real fps: 20 + property int effectsFrameSkip: 3 property bool verbose: false property real bloomQuality: 0.5 @@ -58,7 +53,6 @@ QtObject { property bool blinkingCursor: false - onWindowScalingChanged: handleFontChanged() // PROFILE SETTINGS /////////////////////////////////////////////////////// property real windowOpacity: 1.0 @@ -71,16 +65,11 @@ QtObject { property string _backgroundColor: "#000000" property string _fontColor: "#ff8100" - property string saturatedColor: Utils.mix(Utils.strToColor("#FFFFFF"), - Utils.strToColor(_fontColor), - saturationColor * 0.5) - property color fontColor: Utils.mix(Utils.strToColor(saturatedColor), - Utils.strToColor(_backgroundColor), - 0.7 + (contrast * 0.3)) - property color backgroundColor: Utils.mix(Utils.strToColor( - _backgroundColor), - Utils.strToColor(saturatedColor), - 0.7 + (contrast * 0.3)) + property string _frameColor: "#ffffff" + property string saturatedColor: Utils.mix(Utils.strToColor(_fontColor), Utils.strToColor("#FFFFFF"), (saturationColor * 0.5)) + property color fontColor: Utils.mix(Utils.strToColor(_backgroundColor), Utils.strToColor(saturatedColor), (0.7 + (contrast * 0.3))) + property color backgroundColor: Utils.mix(Utils.strToColor(saturatedColor), Utils.strToColor(_backgroundColor), (0.7 + (contrast * 0.3))) + property color frameColor: Utils.strToColor(_frameColor) property real staticNoise: 0.12 property real screenCurvature: 0.3 @@ -96,126 +85,67 @@ QtObject { property real horizontalSync: 0.08 property real flickering: 0.1 - property real rbgShift: 0.0 + property real rgbShift: 0.0 + + property real _frameShininess: 0.2 + property real frameShininess: _frameShininess * 0.5 + + property real _frameSize: 0.2 + property real frameSize: _frameSize * 0.05 + + property real _screenRadius: 0.2 + property real screenRadius: Utils.lint(4.0, 120.0, _screenRadius) property real _margin: 0.5 - property real _frameMargin: 0.5 + property real margin: Utils.lint(1.0, 40.0, _margin) + (1.0 - Math.SQRT1_2) * screenRadius - property real margin: Utils.lint(1.0, 20.0, _margin) - property real frameMargin: Utils.lint(1.0, 50.0, _frameMargin) - - property real totalMargin: frameMargin + margin + readonly property bool frameEnabled: ambientLight > 0 || _frameSize > 0 || screenCurvature > 0 readonly property int no_rasterization: 0 readonly property int scanline_rasterization: 1 readonly property int pixel_rasterization: 2 readonly property int subpixel_rasterization: 3 + readonly property int modern_rasterization: 4 - property int rasterization: no_rasterization + property alias rasterization: fontManager.rasterization + + readonly property int bundled_fonts: 0 + readonly property int system_fonts: 1 + + property alias fontSource: fontManager.fontSource // FONTS ////////////////////////////////////////////////////////////////// readonly property real baseFontScaling: 0.75 - property real fontScaling: 1.0 + property alias fontScaling: fontManager.fontScaling property real totalFontScaling: baseFontScaling * fontScaling - property real fontWidth: 1.0 + property alias fontWidth: fontManager.fontWidth + property alias lineSpacing: fontManager.lineSpacing - property bool lowResolutionFont: false + property alias lowResolutionFont: fontManager.lowResolutionFont - property var fontNames: ["TERMINUS_SCALED", "COMMODORE_PET", "COMMODORE_PET"] - property var fontlist: fontManager.item.fontlist + property alias fontName: fontManager.fontName + property alias filteredFontList: fontManager.filteredFontList - signal terminalFontChanged(string fontFamily, int pixelSize, int lineSpacing, real screenScaling, real fontWidth) + property FontManager fontManager: FontManager { + id: fontManager + baseFontScaling: baseFontScaling + } signal initializedSettings - property Loader fontManager: Loader { - states: [ - State { - when: rasterization == no_rasterization - PropertyChanges { - target: fontManager - source: "Fonts.qml" - } - }, - State { - when: rasterization == scanline_rasterization - PropertyChanges { - target: fontManager - source: "FontScanlines.qml" - } - }, - State { - when: rasterization == pixel_rasterization - PropertyChanges { - target: fontManager - source: "FontPixels.qml" - } - }, - State { - when: rasterization == subpixel_rasterization - PropertyChanges { - target: fontManager - source: "FontPixels.qml" - } - } - ] - - onLoaded: handleFontChanged() - } - - property FontLoader fontLoader: FontLoader {} - - onTotalFontScalingChanged: handleFontChanged() - onFontWidthChanged: handleFontChanged() - - function getIndexByName(name) { - for (var i = 0; i < fontlist.count; i++) { - var requestedName = fontlist.get(i).name - if (name === requestedName) - return i - } - return 0 // If the font is not available default to 0. - } - function incrementScaling() { fontScaling = Math.min(fontScaling + 0.05, maximumFontScaling) - handleFontChanged() } function decrementScaling() { fontScaling = Math.max(fontScaling - 0.05, minimumFontScaling) - handleFontChanged() } - function handleFontChanged() { - if (!fontManager.item) - return - - var index = getIndexByName(fontNames[rasterization]) - if (index === undefined) - return - - fontManager.item.selectedFontIndex = index - fontManager.item.scaling = totalFontScaling - - var fontSource = fontManager.item.source - var pixelSize = fontManager.item.pixelSize - var lineSpacing = fontManager.item.lineSpacing - var screenScaling = fontManager.item.screenScaling - var fontWidth = fontManager.item.defaultFontWidth * appSettings.fontWidth - var fontFamily = fontManager.item.family - var isSystemFont = fontManager.item.isSystemFont - - lowResolutionFont = fontManager.item.lowResolutionFont - - if (!isSystemFont) { - fontLoader.source = fontSource - fontFamily = fontLoader.name - } - - terminalFontChanged(fontFamily, pixelSize, lineSpacing, screenScaling, - fontWidth) + function close() { + storeSettings() + storeCustomProfiles() + Qt.quit() } property Storage storage: Storage {} @@ -229,15 +159,10 @@ QtObject { function composeSettingsString() { var settings = { - "fps": fps, - "x": x, - "y": y, - "width": width, - "height": height, + "effectsFrameSkip": effectsFrameSkip, "windowScaling": windowScaling, "showTerminalSize": showTerminalSize, "fontScaling": fontScaling, - "fontNames": fontNames, "showMenubar": showMenubar, "bloomQuality": bloomQuality, "burnInQuality": burnInQuality, @@ -248,7 +173,7 @@ QtObject { } function composeProfileObject() { - var settings = { + var profile = { "backgroundColor": _backgroundColor, "fontColor": _fontColor, "flickering": flickering, @@ -262,18 +187,22 @@ QtObject { "bloom": bloom, "rasterization": rasterization, "jitter": jitter, - "rbgShift": rbgShift, + "rgbShift": rgbShift, "brightness": brightness, "contrast": contrast, "ambientLight": ambientLight, "windowOpacity": windowOpacity, - "fontName": fontNames[rasterization], + "fontName": fontName, + "fontSource": fontSource, "fontWidth": fontWidth, "margin": _margin, "blinkingCursor": blinkingCursor, - "frameMargin": _frameMargin, + "frameSize": _frameSize, + "screenRadius": _screenRadius, + "frameColor": _frameColor, + "frameShininess": _frameShininess } - return settings + return profile } function composeProfileString() { @@ -315,16 +244,10 @@ QtObject { showTerminalSize = settings.showTerminalSize !== undefined ? settings.showTerminalSize : showTerminalSize - fps = settings.fps !== undefined ? settings.fps : fps + effectsFrameSkip = settings.effectsFrameSkip !== undefined ? settings.effectsFrameSkip : effectsFrameSkip windowScaling = settings.windowScaling !== undefined ? settings.windowScaling : windowScaling - x = settings.x !== undefined ? settings.x : x - y = settings.y !== undefined ? settings.y : y - width = settings.width !== undefined ? settings.width : width - height = settings.height !== undefined ? settings.height : height - - fontNames = settings.fontNames !== undefined ? settings.fontNames : fontNames fontScaling = settings.fontScaling !== undefined ? settings.fontScaling : fontScaling showMenubar = settings.showMenubar !== undefined ? settings.showMenubar : showMenubar @@ -365,7 +288,7 @@ QtObject { jitter = settings.jitter !== undefined ? settings.jitter : jitter - rbgShift = settings.rbgShift !== undefined ? settings.rbgShift : rbgShift + rgbShift = settings.rgbShift !== undefined ? settings.rgbShift : rgbShift ambientLight = settings.ambientLight !== undefined ? settings.ambientLight : ambientLight contrast = settings.contrast !== undefined ? settings.contrast : contrast @@ -373,16 +296,18 @@ QtObject { windowOpacity = settings.windowOpacity !== undefined ? settings.windowOpacity : windowOpacity - fontNames[rasterization] = settings.fontName - !== undefined ? settings.fontName : fontNames[rasterization] + fontName = settings.fontName !== undefined ? settings.fontName : fontName + fontSource = settings.fontSource !== undefined ? settings.fontSource : fontSource fontWidth = settings.fontWidth !== undefined ? settings.fontWidth : fontWidth + lineSpacing = settings.lineSpacing !== undefined ? settings.lineSpacing : lineSpacing _margin = settings.margin !== undefined ? settings.margin : _margin - _frameMargin = settings.frameMargin !== undefined ? settings.frameMargin : _frameMargin + _frameSize = settings.frameSize !== undefined ? settings.frameSize : _frameSize + _screenRadius = settings.screenRadius !== undefined ? settings.screenRadius : _screenRadius + _frameColor = settings.frameColor !== undefined ? settings.frameColor : _frameColor + _frameShininess = settings.frameShininess !== undefined ? settings.frameShininess : _frameShininess blinkingCursor = settings.blinkingCursor !== undefined ? settings.blinkingCursor : blinkingCursor - - handleFontChanged() } function storeCustomProfiles() { @@ -441,261 +366,476 @@ QtObject { ListElement { text: "Default Amber" obj_string: '{ - "ambientLight": 0.2, + "ambientLight": 0.3, "backgroundColor": "#000000", - "bloom": 0.5538, + "bloom": 0.6, "brightness": 0.5, - "burnIn": 0.2517, - "chromaColor": 0.2483, - "contrast": 0.7959, + "burnIn": 0.3, + "chromaColor": 0.2, + "contrast": 0.8, "flickering": 0.1, "fontColor": "#ff8100", - "fontName": "TERMINUS_SCALED", + "fontName": "TERMINESS_SCALED", + "fontSource": 0, "fontWidth": 1, + "lineSpacing": 0.1, "glowingLine": 0.2, - "horizontalSync": 0.08, - "jitter": 0.1997, + "horizontalSync": 0.1, + "jitter": 0.2, "rasterization": 0, - "rbgShift": 0, - "saturationColor": 0.2483, - "screenCurvature": 0.3, - "staticNoise": 0.1198, + "rgbShift": 0, + "saturationColor": 0.2, + "screenCurvature": 0.2, + "screenRadius": 0.1, + "staticNoise": 0.1, "windowOpacity": 1, - "margin": 0.5, + "margin": 0.3, "blinkingCursor": false, - "frameMargin": 0.1 + "frameSize": 0.1, + "frameColor": "#cfcfcf", + "frameShininess": 0.3 }' builtin: true } ListElement { text: "Monochrome Green" obj_string: '{ - "ambientLight": 0.2, + "ambientLight": 0.3, "backgroundColor": "#000000", - "bloom": 0.5538, + "bloom": 0.5, "brightness": 0.5, - "burnIn": 0.2517, + "burnIn": 0.3, "chromaColor": 0.0, - "contrast": 0.7959, + "contrast": 0.8, "flickering": 0.1, "fontColor": "#0ccc68", - "fontName": "TERMINUS_SCALED", + "fontName": "DEPARTURE_MONO_SCALED", + "fontSource": 0, "fontWidth": 1, + "lineSpacing": 0.1, "glowingLine": 0.2, - "horizontalSync": 0.08, - "jitter": 0.1997, + "horizontalSync": 0.1, + "jitter": 0.2, "rasterization": 0, - "rbgShift": 0, + "rgbShift": 0, "saturationColor": 0.0, "screenCurvature": 0.3, - "staticNoise": 0.1198, + "screenRadius": 0.2, + "staticNoise": 0.1, "windowOpacity": 1, - "margin": 0.5, + "margin": 0.3, "blinkingCursor": false, - "frameMargin": 0.1 + "frameSize": 0.1, + "frameColor": "#d4d4d4", + "frameShininess": 0.1 }' builtin: true } ListElement { - text: "Green Scanlines" + text: "Deep Blue" obj_string: '{ - "ambientLight": 0, + "ambientLight": 0.0, "backgroundColor": "#000000", "bloom": 0.6, "brightness": 0.5, "burnIn": 0.3, - "chromaColor": 0.5, - "contrast": 0.6, + "chromaColor": 1.0, + "contrast": 0.8, "flickering": 0.1, - "fontColor": "#7cff4f", - "fontName": "PRO_FONT_SCALED", + "fontColor": "#7fb4ff", + "fontName": "BIGBLUE_TERMINAL_SCALED", + "fontSource": 0, "fontWidth": 1, + "lineSpacing": 0.1, "glowingLine": 0.2, - "horizontalSync": 0.151, - "jitter": 0.11, - "rasterization": 1, - "rbgShift": 0, - "saturationColor": 0.5, - "screenCurvature": 0.3, - "staticNoise": 0.15, + "horizontalSync": 0.1, + "jitter": 0.2, + "rasterization": 0, + "rgbShift": 0, + "saturationColor": 0.2, + "screenCurvature": 0.4, + "screenRadius": 0.1, + "staticNoise": 0.1, "windowOpacity": 1, - "margin": 0.5, + "margin": 0.3, "blinkingCursor": false, - "frameMargin": 0.1 + "frameSize": 0.1, + "frameColor": "#ffffff", + "frameShininess": 0.9 }' builtin: true } ListElement { - text: "Default Pixelated" + text: "Commodore 64" obj_string: '{ - "ambientLight": 0, - "backgroundColor": "#000000", - "bloom": 0.4045, - "brightness": 0.6041, - "burnIn": 0.1024, - "chromaColor": 0.7517, - "contrast": 0.7473, - "flickering": 0.1962, - "fontColor": "#ffffff", - "fontName": "COMMODORE_PET", + "ambientLight": 0.4, + "backgroundColor": "#3b3b8f", + "bloom": 0.4, + "brightness": 0.6, + "burnIn": 0.1, + "chromaColor": 0.0, + "contrast": 0.7, + "flickering": 0.1, + "fontColor": "#a9a7ff", + "fontName": "COMMODORE_64_SCALED", + "fontSource": 0, "fontWidth": 1, - "glowingLine": 0.2, - "horizontalSync": 0.151, - "jitter": 0, - "rasterization": 2, - "rbgShift": 0, + "lineSpacing": 0.1, + "glowingLine": 0.1, + "horizontalSync": 0.0, + "jitter": 0.0, + "rasterization": 1, + "rgbShift": 0, "saturationColor": 0, - "screenCurvature": 0, - "staticNoise": 0.15, + "screenCurvature": 0.5, + "screenRadius": 0.1, + "staticNoise": 0.1, "windowOpacity": 1, - "margin": 0.5, + "margin": 0.3, "blinkingCursor": false, - "frameMargin": 0.1 + "frameSize": 0.5, + "frameColor": "#999999", + "frameShininess": 0.0 + }' + builtin: true + } + ListElement { + text: "Commodore PET" + obj_string: '{ + "ambientLight": 0.0, + "backgroundColor": "#000000", + "bloom": 0.4, + "brightness": 0.5, + "burnIn": 0.4, + "chromaColor": 0, + "contrast": 0.8, + "flickering": 0.2, + "fontColor": "#ffffff", + "fontName": "COMMODORE_PET_SCALED", + "fontSource": 0, + "fontWidth": 1.25, + "lineSpacing": 0.1, + "glowingLine": 0.3, + "horizontalSync": 0.2, + "jitter": 0.15, + "rasterization": 1, + "rgbShift": 0.0, + "saturationColor": 0, + "screenCurvature": 0.7, + "screenRadius": 0.3, + "staticNoise": 0.2, + "windowOpacity": 1, + "margin": 0.2, + "blinkingCursor": false, + "frameSize": 0.5, + "frameColor": "#000000", + "frameShininess": 0.6 }' builtin: true } ListElement { text: "Apple ][" obj_string: '{ - "ambientLight": 0.3038, - "backgroundColor": "#000000", - "bloom": 0.5, + "ambientLight": 1.0, + "backgroundColor": "#001100", + "bloom": 0.3, "brightness": 0.5, - "burnIn": 0.5017, + "burnIn": 0.3, "chromaColor": 0, - "contrast": 0.85, + "contrast": 0.8, "flickering": 0.2, - "fontColor": "#00d56d", - "fontName": "APPLE_II", - "fontWidth": 1, - "glowingLine": 0.22, - "horizontalSync": 0.16, - "jitter": 0.1, - "rasterization": 1, - "rbgShift": 0, - "saturationColor": 0, - "screenCurvature": 0.5, - "staticNoise": 0.099, - "windowOpacity": 1, - "margin": 0.5, - "blinkingCursor": false, - "frameMargin": 0.2 - }' - builtin: true - } - ListElement { - text: "Vintage" - obj_string: '{ - "ambientLight": 0.5, - "backgroundColor": "#000000", - "bloom": 0.4983, - "brightness": 0.5014, - "burnIn": 0.4983, - "chromaColor": 0, - "contrast": 0.7473, - "flickering": 0.9, - "fontColor": "#00ff3e", - "fontName": "COMMODORE_PET", - "fontWidth": 1, + "fontColor": "#4dff6b", + "fontName": "APPLE_II_SCALED", + "fontSource": 0, + "fontWidth": 1.25, + "lineSpacing": 0.1, "glowingLine": 0.3, - "horizontalSync": 0.42, - "jitter": 0.4, + "horizontalSync": 0.2, + "jitter": 0.2, "rasterization": 1, - "rbgShift": 0.2969, + "rgbShift": 0.0, "saturationColor": 0, "screenCurvature": 0.5, - "staticNoise": 0.2969, + "screenRadius": 0.3, + "staticNoise": 0.2, "windowOpacity": 1, - "margin": 0.5, + "margin": 0.0, "blinkingCursor": false, - "frameMargin": 0.5 + "frameSize": 0.2, + "frameColor": "#ffffff", + "frameShininess": 0.8 }' builtin: true } ListElement { - text: "IBM Dos" - obj_string: '{ - "ambientLight": 0.151, - "backgroundColor": "#000000", - "bloom": 0.2969, - "brightness": 0.5, - "burnIn": 0.0469, - "chromaColor": 1, - "contrast": 0.85, - "flickering": 0.0955, - "fontColor": "#ffffff", - "fontName": "IBM_DOS", - "fontWidth": 1, - "glowingLine": 0.1545, - "horizontalSync": 0, - "jitter": 0.1545, - "rasterization": 0, - "rbgShift": 0.3524, - "saturationColor": 0, - "screenCurvature": 0.4, - "staticNoise": 0.0503, - "windowOpacity": 1, - "margin": 0.5, - "blinkingCursor": false, - "frameMargin": 0.2 - }' - builtin: true - } - ListElement { - text: "IBM 3278" + text: "Atari 400" obj_string: '{ "ambientLight": 0.1, - "backgroundColor": "#000000", - "bloom": 0.2969, - "brightness": 0.5, - "burnIn": 0.6, + "backgroundColor": "#0f1f5a", + "bloom": 0.1, + "brightness": 0.6, + "burnIn": 0.2, "chromaColor": 0, - "contrast": 0.85, - "flickering": 0, - "fontColor": "#0ccc68", - "fontName": "IBM_3278", + "contrast": 0.9, + "flickering": 0.1, + "fontColor": "#8ed6ff", + "fontName": "ATARI_400_SCALED", + "fontSource": 0, "fontWidth": 1, - "glowingLine": 0, - "horizontalSync": 0, - "jitter": 0, - "rasterization": 0, - "rbgShift": 0, + "lineSpacing": 0.1, + "glowingLine": 0.1, + "horizontalSync": 0.0, + "jitter": 0.0, + "rasterization": 1, + "rgbShift": 0.0, "saturationColor": 0, - "screenCurvature": 0.2, - "staticNoise": 0, + "screenCurvature": 0.4, + "screenRadius": 0.2, + "staticNoise": 0.1, "windowOpacity": 1, - "margin": 0.5, + "margin": 0.2, "blinkingCursor": false, - "frameMargin": 0.1 + "frameSize": 0.4, + "frameColor": "#cccccc", + "frameShininess": 0.3 }' builtin: true } ListElement { - text: "Futuristic" + text: "IBM VGA 8x16" obj_string: '{ - "ambientLight": 0, + "ambientLight": 0.2, "backgroundColor": "#000000", - "bloom": 0.5017, - "brightness": 0.5014, - "burnIn": 0.0955, - "chromaColor": 1, - "contrast": 0.85, - "flickering": 0.2, - "fontColor": "#729fcf", - "fontName": "TERMINUS", + "bloom": 0.2, + "brightness": 0.6, + "burnIn": 0.1, + "chromaColor": 0.5, + "contrast": 1.0, + "flickering": 0.1, + "fontColor": "#c0c0c0", + "fontName": "IBM_VGA_8x16", + "fontSource": 0, "fontWidth": 1, - "glowingLine": 0.1476, + "lineSpacing": 0.1, + "glowingLine": 0.1, + "horizontalSync": 0.0, + "jitter": 0.0, + "rasterization": 1, + "rgbShift": 0.1, + "saturationColor": 0, + "screenCurvature": 0.3, + "screenRadius": 0.1, + "staticNoise": 0.0, + "windowOpacity": 1, + "margin": 0.2, + "blinkingCursor": false, + "frameSize": 0.1, + "frameColor": "#ffffff", + "frameShininess": 0.3 + }' + builtin: true + } + ListElement { + text: "IBM 3278 Reborn" + obj_string: '{ + "ambientLight": 0.2, + "backgroundColor": "#000000", + "bloom": 0.2, + "brightness": 0.5, + "burnIn": 0.5, + "chromaColor": 0, + "contrast": 0.8, + "flickering": 0, + "fontColor": "#3cff7a", + "fontName": "IBM_3278", + "fontSource": 0, + "fontWidth": 1, + "lineSpacing": 0.1, + "glowingLine": 0.0, "horizontalSync": 0, - "jitter": 0.099, - "rasterization": 0, - "rbgShift": 0, - "saturationColor": 0.4983, + "jitter": 0, + "rasterization": 4, + "rgbShift": 0, + "saturationColor": 0, "screenCurvature": 0, - "staticNoise": 0.0955, + "screenRadius": 0.0, + "staticNoise": 0.0, + "windowOpacity": 1, + "margin": 0.1, + "blinkingCursor": false, + "frameSize": 0, + "frameColor": "#ffffff", + "frameShininess": 0.2 + }' + builtin: true + } + ListElement { + text: "Neon Cyan" + obj_string: '{ + "ambientLight": 0.1, + "backgroundColor": "#001018", + "bloom": 0.6, + "brightness": 0.6, + "burnIn": 0.1, + "chromaColor": 1, + "contrast": 0.9, + "flickering": 0.1, + "fontColor": "#52f7ff", + "fontName": "IOSEVKA", + "fontSource": 0, + "fontWidth": 1, + "lineSpacing": 0.1, + "glowingLine": 0.2, + "horizontalSync": 0.0, + "jitter": 0.1, + "rasterization": 4, + "rgbShift": 0.0, + "saturationColor": 0.6, + "screenCurvature": 0, + "screenRadius": 0.0, + "staticNoise": 0.1, + "windowOpacity": 0.8, + "margin": 0.1, + "blinkingCursor": false, + "frameSize": 0, + "frameColor": "#c3c3c3", + "frameShininess": 0.2 + }' + builtin: true + } + ListElement { + text: "Ghost Terminal" + obj_string: '{ + "ambientLight": 0.3, + "backgroundColor": "#0b1014", + "bloom": 0.3, + "brightness": 0.6, + "burnIn": 0.2, + "chromaColor": 0, + "contrast": 0.5, + "flickering": 0.0, + "fontColor": "#a6b3c0", + "fontName": "JETBRAINS_MONO", + "fontSource": 0, + "fontWidth": 1, + "lineSpacing": 0.1, + "glowingLine": 0.1, + "horizontalSync": 0.0, + "jitter": 0.0, + "rasterization": 4, + "rgbShift": 0.0, + "saturationColor": 0.0, + "screenCurvature": 0, + "screenRadius": 0.0, + "staticNoise": 0.1, "windowOpacity": 0.7, "margin": 0.1, "blinkingCursor": false, - "frameMargin": 0 + "frameSize": 0, + "frameColor": "#a7a7a7", + "frameShininess": 0.2 + }' + builtin: true + } + ListElement { + text: "Plasma" + obj_string: '{ + "ambientLight": 0.1, + "backgroundColor": "#070014", + "bloom": 0.7, + "brightness": 0.6, + "burnIn": 0.1, + "chromaColor": 1, + "contrast": 0.8, + "flickering": 0.1, + "fontColor": "#ff9bd6", + "fontName": "FIRA_CODE", + "fontSource": 0, + "fontWidth": 1, + "lineSpacing": 0.1, + "glowingLine": 0.2, + "horizontalSync": 0.0, + "jitter": 0.1, + "rasterization": 4, + "rgbShift": 0.1, + "saturationColor": 0.8, + "screenCurvature": 0, + "screenRadius": 0.0, + "staticNoise": 0.1, + "windowOpacity": 1.0, + "margin": 0.1, + "blinkingCursor": false, + "frameSize": 0, + "frameColor": "#d0d0d0", + "frameShininess": 0.2 + }' + builtin: true + } + ListElement { + text: "Boring" + obj_string: '{ + "ambientLight": 0.1, + "backgroundColor": "#000000", + "bloom": 0.5, + "brightness": 0.5, + "burnIn": 0.05, + "chromaColor": 1, + "contrast": 0.8, + "flickering": 0.0, + "fontColor": "#ffffff", + "fontName": "JETBRAINS_MONO", + "fontSource": 0, + "fontWidth": 1, + "lineSpacing": 0.1, + "glowingLine": 0.1, + "horizontalSync": 0, + "jitter": 0.0, + "rasterization": 4, + "rgbShift": 0, + "saturationColor": 0.0, + "screenCurvature": 0, + "screenRadius": 0.0, + "staticNoise": 0.0, + "windowOpacity": 1.0, + "margin": 0.0, + "blinkingCursor": false, + "frameSize": 0, + "frameColor": "#c0c0c0", + "frameShininess": 0.2 + }' + builtin: true + } + ListElement { + text: "E-Ink" + obj_string: '{ + "ambientLight": 0.6, + "backgroundColor": "#f2f2ec", + "bloom": 0.0, + "brightness": 1.0, + "burnIn": 0.6, + "chromaColor": 0, + "contrast": 0.5, + "flickering": 0.0, + "fontColor": "#101010", + "fontName": "HACK", + "fontSource": 0, + "fontWidth": 1, + "lineSpacing": 0.1, + "glowingLine": 0.0, + "horizontalSync": 0.0, + "jitter": 0.0, + "rasterization": 4, + "rgbShift": 0, + "saturationColor": 0, + "screenCurvature": 0, + "screenRadius": 0.0, + "staticNoise": 0.0, + "windowOpacity": 1, + "margin": 0.1, + "blinkingCursor": false, + "frameSize": 0, + "frameColor": "#cdcdcd", + "frameShininess": 0.2 }' builtin: true } @@ -723,30 +863,16 @@ QtObject { var profileArgPosition = args.indexOf("--profile") if (profileArgPosition !== -1) { - var profileIndex = getProfileIndexByName( - args[profileArgPosition + 1]) - if (profileIndex !== -1) + var profileIndex = getProfileIndexByName(args[profileArgPosition + 1]) + if (profileIndex !== -1) { loadProfile(profileIndex) - else + } else { console.log("Warning: selected profile is not valid; ignoring it") - } - - if (args.indexOf("--fullscreen") !== -1) { - fullscreen = true - showMenubar = false - } - - if (args.indexOf("-T") !== -1) { - wintitle = args[args.indexOf("-T") + 1] + } } initializedSettings() } - Component.onDestruction: { - storeSettings() - storeCustomProfiles() - // storage.dropSettings(); //DROPS THE SETTINGS!.. REMEMBER TO DISABLE ONCE ENABLED!! - } // VARS /////////////////////////////////////////////////////////////////// property Label _sampleLabel: Label { diff --git a/app/qml/BurnInEffect.qml b/app/qml/BurnInEffect.qml index 6016e25..bc2bd9f 100644 --- a/app/qml/BurnInEffect.qml +++ b/app/qml/BurnInEffect.qml @@ -24,7 +24,7 @@ import "utils.js" as Utils Loader { id: burnInEffect - property ShaderEffectSource source: item ? item.source : null + property ShaderEffectSource effectSource: item ? item.source : null property real lastUpdate: 0 property real prevLastUpdate: 0 @@ -81,6 +81,14 @@ Loader { } } // Restart blurred source settings change. + Connections { + target: appSettings.fontManager + + onTerminalFontChanged: { + burnInEffect.restartBlurSource() + } + } + Connections { target: appSettings @@ -88,10 +96,6 @@ Loader { burnInEffect.restartBlurSource() } - onTerminalFontChanged: { - burnInEffect.restartBlurSource() - } - onRasterizationChanged: { burnInEffect.restartBlurSource() } @@ -102,58 +106,22 @@ Loader { } } - ShaderLibrary { - id: shaderLibrary - } - ShaderEffect { id: burnInShaderEffect + property real time: timeManager.time + property variant txt_source: kterminalSource property variant burnInSource: burnInEffectSource property real burnInTime: burnInFadeTime - property real lastUpdate: burnInEffect.lastUpdate + property real burnInLastUpdate: burnInEffect.lastUpdate property real prevLastUpdate: burnInEffect.prevLastUpdate anchors.fill: parent blending: false - fragmentShader: - "#ifdef GL_ES - precision mediump float; - #endif\n" + - - "uniform lowp float qt_Opacity;" + - "uniform lowp sampler2D txt_source;" + - - "varying highp vec2 qt_TexCoord0; - - uniform lowp sampler2D burnInSource; - uniform highp float burnInTime; - - uniform highp float lastUpdate; - - uniform highp float prevLastUpdate;" + - - shaderLibrary.rgb2grey + - - "void main() { - vec2 coords = qt_TexCoord0; - - vec3 txtColor = texture2D(txt_source, coords).rgb; - vec4 accColor = texture2D(burnInSource, coords); - - float prevMask = accColor.a; - float currMask = rgb2grey(txtColor); - - highp float blurDecay = clamp((lastUpdate - prevLastUpdate) * burnInTime, 0.0, 1.0); - blurDecay = max(0.0, blurDecay - prevMask); - vec3 blurColor = accColor.rgb - vec3(blurDecay); - vec3 color = max(blurColor, txtColor); - - gl_FragColor = vec4(color, currMask); - } - " + fragmentShader: "qrc:/shaders/burn_in.frag.qsb" + vertexShader: "qrc:/shaders/burn_in.vert.qsb" onStatusChanged: if (log) console.log(log) //Print warning messages } diff --git a/app/qml/ColorButton.qml b/app/qml/ColorButton.qml index a2d97e3..2a925db 100644 --- a/app/qml/ColorButton.qml +++ b/app/qml/ColorButton.qml @@ -18,7 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ import QtQuick 2.2 -import QtQuick.Dialogs 1.1 +import QtQuick.Dialogs Item { id: rootItem @@ -31,11 +31,13 @@ Item { id: colorDialog title: qsTr("Choose a color") modality: Qt.ApplicationModal - visible: false + selectedColor: rootItem.color - //This is a workaround to a Qt 5.2 bug. - onColorChanged: if (!appSettings.isMacOS) colorSelected(color) - onAccepted: if (appSettings.isMacOS) colorSelected(color) + onSelectedColorChanged: { + if (!appSettings.isMacOS && visible) + colorSelected(selectedColor) + } + onAccepted: colorSelected(selectedColor) } Rectangle { anchors.fill: parent @@ -57,6 +59,6 @@ Item { } MouseArea { anchors.fill: parent - onClicked: colorDialog.visible = true + onClicked: colorDialog.open() } } diff --git a/app/qml/FontPixels.qml b/app/qml/FontPixels.qml deleted file mode 100644 index 0978480..0000000 --- a/app/qml/FontPixels.qml +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2013-2021 "Filippo Scognamiglio" -* https://github.com/Swordfish90/cool-retro-term -* -* This file is part of cool-retro-term. -* -* cool-retro-term is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*******************************************************************************/ -import QtQuick 2.2 - -QtObject { - property int selectedFontIndex - property real scaling - property var _font: fontlist.get(selectedFontIndex) - property var source: _font.source - property int pixelSize: _font.pixelSize - property int lineSpacing: _font.lineSpacing - property real screenScaling: scaling * _font.baseScaling - property real defaultFontWidth: fontlist.get(selectedFontIndex).fontWidth - property bool lowResolutionFont: true - - property ListModel fontlist: ListModel { - ListElement { - name: "COMMODORE_PET" - text: "Commodore PET (1977)" - source: "fonts/1977-commodore-pet/PetMe.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - } - ListElement { - name: "IBM_PC" - text: "IBM PC (1981)" - source: "fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - } - ListElement { - name: "PROGGY_TINY" - text: "Proggy Tiny (Modern)" - source: "fonts/modern-proggy-tiny/ProggyTiny.ttf" - lineSpacing: 1 - pixelSize: 16 - baseScaling: 3.3 - fontWidth: 0.9 - } - ListElement { - name: "TERMINUS_SCALED" - text: "Terminus (Modern)" - source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" - lineSpacing: 1 - pixelSize: 12 - baseScaling: 3.0 - fontWidth: 1.0 - } - ListElement { - name: "PRO_FONT_SCALED" - text: "Pro Font (Modern)" - source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" - lineSpacing: 1 - pixelSize: 12 - baseScaling: 3.0 - fontWidth: 1.0 - } - ListElement { - name: "APPLE_II" - text: "Apple ][ (1977)" - source: "fonts/1977-apple2/PrintChar21.ttf" - lineSpacing: 2 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.9 - } - ListElement { - name: "ATARI_400" - text: "Atari 400-800 (1979)" - source: "fonts/1979-atari-400-800/AtariClassic-Regular.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - } - ListElement { - name: "COMMODORE_64" - text: "Commodore 64 (1982)" - source: "fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - } - } -} diff --git a/app/qml/FontScanlines.qml b/app/qml/FontScanlines.qml deleted file mode 100644 index 37003ed..0000000 --- a/app/qml/FontScanlines.qml +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2013-2021 "Filippo Scognamiglio" -* https://github.com/Swordfish90/cool-retro-term -* -* This file is part of cool-retro-term. -* -* cool-retro-term is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*******************************************************************************/ -import QtQuick 2.2 - -QtObject { - property int selectedFontIndex - property real scaling - property var _font: fontlist.get(selectedFontIndex) - property var source: _font.source - property int pixelSize: _font.pixelSize - property int lineSpacing: _font.lineSpacing - property real screenScaling: scaling * _font.baseScaling - property real defaultFontWidth: fontlist.get(selectedFontIndex).fontWidth - property bool lowResolutionFont: true - - property ListModel fontlist: ListModel { - ListElement { - name: "COMMODORE_PET" - text: "Commodore PET (1977)" - source: "fonts/1977-commodore-pet/PetMe.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.7 - } - ListElement { - name: "IBM_PC" - text: "IBM PC (1981)" - source: "fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - } - ListElement { - name: "PROGGY_TINY" - text: "Proggy Tiny (Modern)" - source: "fonts/modern-proggy-tiny/ProggyTiny.ttf" - lineSpacing: 1 - pixelSize: 16 - baseScaling: 3.3 - fontWidth: 0.9 - } - ListElement { - name: "TERMINUS_SCALED" - text: "Terminus (Modern)" - source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" - lineSpacing: 1 - pixelSize: 12 - baseScaling: 3.0 - fontWidth: 1.0 - } - ListElement { - name: "PRO_FONT_SCALED" - text: "Pro Font (Modern)" - source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" - lineSpacing: 1 - pixelSize: 12 - baseScaling: 3.0 - fontWidth: 1.0 - } - ListElement { - name: "APPLE_II" - text: "Apple ][ (1977)" - source: "fonts/1977-apple2/PrintChar21.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - } - ListElement { - name: "ATARI_400" - text: "Atari 400-800 (1979)" - source: "fonts/1979-atari-400-800/AtariClassic-Regular.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.7 - } - ListElement { - name: "COMMODORE_64" - text: "Commodore 64 (1982)" - source: "fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.7 - } - } -} diff --git a/app/qml/Fonts.qml b/app/qml/Fonts.qml deleted file mode 100644 index 1dc15aa..0000000 --- a/app/qml/Fonts.qml +++ /dev/null @@ -1,252 +0,0 @@ -/******************************************************************************* -* Copyright (c) 2013-2021 "Filippo Scognamiglio" -* https://github.com/Swordfish90/cool-retro-term -* -* This file is part of cool-retro-term. -* -* cool-retro-term is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*******************************************************************************/ -import QtQuick 2.2 - -QtObject { - property int selectedFontIndex - property real scaling - property var source: fontlist.get(selectedFontIndex).source - property var _font: fontlist.get(selectedFontIndex) - property bool lowResolutionFont: _font.lowResolutionFont - - property int pixelSize: lowResolutionFont ? _font.pixelSize : _font.pixelSize * scaling - - property int lineSpacing: lowResolutionFont ? _font.lineSpacing : pixelSize * _font.lineSpacing - - property real screenScaling: lowResolutionFont ? _font.baseScaling * scaling : 1.0 - - property real defaultFontWidth: fontlist.get(selectedFontIndex).fontWidth - - property string family: fontlist.get(selectedFontIndex).family - - property bool isSystemFont: fontlist.get(selectedFontIndex).isSystemFont - - // There are two kind of fonts: low resolution and high resolution. - // Low resolution font sets the lowResolutionFont property to true. - // They are rendered at a fixed pixel size and the texture is upscaled - // to fill the screen (they are much faster to render). - // High resolution fonts are instead drawn on a texture which has the - // size of the screen, and the scaling directly controls their pixels size. - // Those are slower to render but are not pixelated. - property ListModel fontlist: ListModel { - ListElement { - name: "TERMINUS_SCALED" - text: "Terminus (Modern)" - source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" - lineSpacing: 1 - pixelSize: 12 - baseScaling: 3.0 - fontWidth: 1.0 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "PRO_FONT_SCALED" - text: "Pro Font (Modern)" - source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" - lineSpacing: 1 - pixelSize: 12 - baseScaling: 3.0 - fontWidth: 1.0 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "EXCELSIOR_SCALED" - text: "Fixedsys Excelsior (Modern)" - source: "fonts/modern-fixedsys-excelsior/FSEX301-L2.ttf" - lineSpacing: 0 - pixelSize: 16 - baseScaling: 2.4 - fontWidth: 1.0 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "COMMODORE_PET_SCALED" - text: "Commodore PET (1977)" - source: "fonts/1977-commodore-pet/PetMe.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.7 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "PROGGY_TINY_SCALED" - text: "Proggy Tiny (Modern)" - source: "fonts/modern-proggy-tiny/ProggyTiny.ttf" - lineSpacing: 1 - pixelSize: 16 - baseScaling: 3.3 - fontWidth: 0.9 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "APPLE_II_SCALED" - text: "Apple ][ (1977)" - source: "fonts/1977-apple2/PrintChar21.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "ATARI_400_SCALED" - text: "Atari 400-800 (1979)" - source: "fonts/1979-atari-400-800/AtariClassic-Regular.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.7 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "IBM_PC_SCALED" - text: "IBM PC (1981)" - source: "fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.8 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "COMMODORE_64_SCALED" - text: "Commodore 64 (1982)" - source: "fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf" - lineSpacing: 3 - pixelSize: 8 - baseScaling: 3.5 - fontWidth: 0.7 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "IBM_DOS" - text: "IBM DOS (1985)" - source: "fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf" - lineSpacing: 3 - pixelSize: 16 - baseScaling: 2.0 - fontWidth: 1.0 - lowResolutionFont: true - isSystemFont: false - family: "" - } - ListElement { - name: "HERMIT" - text: "HD: Hermit (Modern)" - source: "fonts/modern-hermit/Hermit-medium.otf" - lineSpacing: 0.05 - pixelSize: 27 - fontWidth: 1.0 - lowResolutionFont: false - isSystemFont: false - family: "" - } - ListElement { - name: "TERMINUS" - text: "HD: Terminus (Modern)" - source: "fonts/modern-terminus/TerminusTTF-4.46.0.ttf" - lineSpacing: 0.1 - pixelSize: 35 - fontWidth: 1.0 - lowResolutionFont: false - isSystemFont: false - family: "" - } - ListElement { - name: "PRO_FONT" - text: "HD: Pro Font (Modern)" - source: "fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf" - lineSpacing: 0.1 - pixelSize: 35 - fontWidth: 1.0 - lowResolutionFont: false - isSystemFont: false - family: "" - } - ListElement { - name: "INCONSOLATA" - text: "HD: Inconsolata (Modern)" - source: "fonts/modern-inconsolata/Inconsolata.otf" - lineSpacing: 0.1 - pixelSize: 35 - fontWidth: 1.0 - lowResolutionFont: false - isSystemFont: false - family: "" - } - ListElement { - name: "IBM_3278" - text: "HD: IBM 3278 (1971)" - source: "fonts/1971-ibm-3278/3270-Regular.ttf" - lineSpacing: 0.2 - pixelSize: 32 - fontWidth: 1.0 - lowResolutionFont: false - isSystemFont: false - family: "" - } - } - - Component.onCompleted: addSystemFonts() - - function addSystemFonts() { - var families = monospaceSystemFonts - for (var i = 0; i < families.length; i++) { - if (verbose) { - console.log("Adding system font: ", families[i]) - } - fontlist.append(convertToListElement(families[i])) - } - } - - function convertToListElement(family) { - return { - "name": "System: " + family, - "text": qsTr("System: ") + family, - "source": "", - "lineSpacing": 0.1, - "pixelSize": 30, - "fontWidth": 1.0, - "baseScaling": 1.0, - "lowResolutionFont": false, - "isSystemFont": true, - "family": family - } - } -} diff --git a/app/qml/InsertNameDialog.qml b/app/qml/InsertNameDialog.qml index fb4d7e9..ae2ea0a 100644 --- a/app/qml/InsertNameDialog.qml +++ b/app/qml/InsertNameDialog.qml @@ -21,7 +21,7 @@ import QtQuick 2.2 import QtQuick.Window 2.0 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.1 -import QtQuick.Dialogs 1.1 +import QtQuick.Dialogs Window { id: insertnamedialog diff --git a/app/qml/PreprocessedTerminal.qml b/app/qml/PreprocessedTerminal.qml index 916ae5b..81eb705 100644 --- a/app/qml/PreprocessedTerminal.qml +++ b/app/qml/PreprocessedTerminal.qml @@ -20,14 +20,16 @@ import QtQuick 2.2 import QtQuick.Controls 2.0 +import QtQml -import QMLTermWidget 1.0 +import QMLTermWidget 2.0 import "menus" import "utils.js" as Utils -Item{ - id: terminalContainer +Item { + id: preprocessedTerminal + signal sessionFinished() property size virtualResolution: Qt.size(kterminal.totalWidth, kterminal.totalHeight) property alias mainTerminal: kterminal @@ -46,14 +48,14 @@ Item{ // Manage copy and paste Connections { target: copyAction - + enabled: terminalContainer.hasFocus onTriggered: { kterminal.copyClipboard() } } Connections { target: pasteAction - + enabled: terminalContainer.hasFocus onTriggered: { kterminal.pasteClipboard() } @@ -64,29 +66,22 @@ Item{ target: appSettings onFontScalingChanged: { - terminalContainer.updateSources() + preprocessedTerminal.updateSources() } onFontWidthChanged: { - terminalContainer.updateSources() + preprocessedTerminal.updateSources() } } Connections { - target: terminalContainer + target: preprocessedTerminal onWidthChanged: { - terminalContainer.updateSources() + preprocessedTerminal.updateSources() } onHeightChanged: { - terminalContainer.updateSources() - } - } - Connections { - target: terminalWindow - - onActiveChanged: { - kterminal.forceActiveFocus() + preprocessedTerminal.updateSources() } } @@ -97,8 +92,8 @@ Item{ QMLTermWidget { id: kterminal - property int textureResolutionScale: appSettings.lowResolutionFont ? devicePixelRatio : 1 - property int margin: appSettings.totalMargin / screenScaling + property int textureResolutionScale: appSettings.lowResolutionFont ? Screen.devicePixelRatio : 1 + property int margin: appSettings.margin / screenScaling property int totalWidth: Math.floor(parent.width / (screenScaling * fontWidth)) property int totalHeight: Math.floor(parent.height / screenScaling) @@ -107,26 +102,24 @@ Item{ textureSize: Qt.size(width / textureResolutionScale, height / textureResolutionScale) - width: ensureMultiple(rawWidth, devicePixelRatio) - height: ensureMultiple(rawHeight, devicePixelRatio) + width: ensureMultiple(rawWidth, Screen.devicePixelRatio) + height: ensureMultiple(rawHeight, Screen.devicePixelRatio) /** Ensure size is a multiple of factor. This is needed for pixel perfect scaling on highdpi screens. */ function ensureMultiple(size, factor) { return Math.round(size / factor) * factor; } - colorScheme: "cool-retro-term" - - smooth: !appSettings.lowResolutionFont - enableBold: false fullCursorHeight: true blinkingCursor: appSettings.blinkingCursor + colorScheme: "cool-retro-term" + session: QMLTermSession { id: ksession onFinished: { - Qt.quit() + preprocessedTerminal.sessionFinished() } } @@ -140,26 +133,36 @@ Item{ anchors.topMargin: 1 anchors.bottomMargin: 1 color: "white" - radius: width * 0.25 opacity: 0.7 } } - function handleFontChanged(fontFamily, pixelSize, lineSpacing, screenScaling, fontWidth) { - kterminal.antialiasText = !appSettings.lowResolutionFont; - font.pixelSize = pixelSize; - font.family = fontFamily; - - terminalContainer.fontWidth = fontWidth; - terminalContainer.screenScaling = screenScaling; - scaleTexture = Math.max(1.0, Math.floor(screenScaling * appSettings.windowScaling)); - + function handleFontChanged(fontFamily, pixelSize, lineSpacing, screenScaling, fontWidth, fallbackFontFamily, lowResolutionFont) { kterminal.lineSpacing = lineSpacing; + kterminal.antialiasText = !lowResolutionFont; + kterminal.smooth = !lowResolutionFont; + kterminal.enableBold = !lowResolutionFont; + kterminal.enableItalic = !lowResolutionFont; + + kterminal.font = Qt.font({ + family: fontFamily, + pixelSize: pixelSize + }); + + preprocessedTerminal.fontWidth = fontWidth; + preprocessedTerminal.screenScaling = screenScaling; + scaleTexture = Math.max(1.0, Math.floor(screenScaling * appSettings.windowScaling)); + } + + Connections { + target: appSettings + + onWindowScalingChanged: { + scaleTexture = Math.max(1.0, Math.floor(preprocessedTerminal.screenScaling * appSettings.windowScaling)); + } } function startSession() { - appSettings.initializedSettings.disconnect(startSession); - // Retrieve the variable set in main.cpp if arguments are passed. if (defaultCmd) { ksession.setShellProgram(defaultCmd); @@ -180,9 +183,9 @@ Item{ forceActiveFocus(); } Component.onCompleted: { - appSettings.terminalFontChanged.connect(handleFontChanged); - appSettings.initializedSettings.connect(startSession); - appSettings.handleFontChanged() + appSettings.fontManager.terminalFontChanged.connect(handleFontChanged); + appSettings.fontManager.refresh() + startSession(); } } @@ -198,51 +201,58 @@ Item{ Loader { id: menuLoader - sourceComponent: (appSettings.isMacOS || appSettings.showMenubar ? shortContextMenu : fullContextMenu) + sourceComponent: (appSettings.isMacOS || (appSettings.showMenubar && !terminalWindow.fullscreen) ? shortContextMenu : fullContextMenu) } property alias contextmenu: menuLoader.item MouseArea { - property real margin: appSettings.totalMargin + property real margin: appSettings.margin + property real frameSize: appSettings.frameSize * terminalWindow.normalizedWindowScale acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton anchors.fill: parent cursorShape: kterminal.terminalUsesMouse ? Qt.ArrowCursor : Qt.IBeamCursor - onWheel:{ - if(wheel.modifiers & Qt.ControlModifier){ - wheel.angleDelta.y > 0 ? zoomIn.trigger() : zoomOut.trigger(); + onWheel: function(wheel) { + if (wheel.modifiers & Qt.ControlModifier) { + wheel.angleDelta.y > 0 ? zoomInAction.trigger() : zoomOutAction.trigger(); } else { var coord = correctDistortion(wheel.x, wheel.y); kterminal.simulateWheel(coord.x, coord.y, wheel.buttons, wheel.modifiers, wheel.angleDelta); } } - onDoubleClicked: { + onDoubleClicked: function(mouse) { var coord = correctDistortion(mouse.x, mouse.y); kterminal.simulateMouseDoubleClick(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers); } - onPressed: { - if((!kterminal.terminalUsesMouse || mouse.modifiers & Qt.ShiftModifier) && mouse.button == Qt.RightButton) { + onPressed: function(mouse) { + kterminal.forceActiveFocus() + if ((!kterminal.terminalUsesMouse || mouse.modifiers & Qt.ShiftModifier) && mouse.button == Qt.RightButton) { contextmenu.popup(); } else { var coord = correctDistortion(mouse.x, mouse.y); kterminal.simulateMousePress(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers) } } - onReleased: { + onReleased: function(mouse) { var coord = correctDistortion(mouse.x, mouse.y); kterminal.simulateMouseRelease(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers); } - onPositionChanged: { + onPositionChanged: function(mouse) { var coord = correctDistortion(mouse.x, mouse.y); kterminal.simulateMouseMove(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers); } - function correctDistortion(x, y){ + function correctDistortion(x, y) { x = (x - margin) / width; y = (y - margin) / height; + x = x * (1 + frameSize * 2) - frameSize; + y = y * (1 + frameSize * 2) - frameSize; + var cc = Qt.size(0.5 - x, 0.5 - y); - var distortion = (cc.height * cc.height + cc.width * cc.width) * appSettings.screenCurvature * appSettings.screenCurvatureSize; + var distortion = (cc.height * cc.height + cc.width * cc.width) + * appSettings.screenCurvature * appSettings.screenCurvatureSize + * terminalWindow.normalizedWindowScale; return Qt.point((x - cc.width * (1+distortion) * distortion) * (kterminal.totalWidth), (y - cc.height * (1+distortion) * distortion) * (kterminal.totalHeight)) diff --git a/app/qml/SettingsAdvancedTab.qml b/app/qml/SettingsAdvancedTab.qml index 0adf851..a84cad2 100644 --- a/app/qml/SettingsAdvancedTab.qml +++ b/app/qml/SettingsAdvancedTab.qml @@ -27,7 +27,9 @@ import "Components" ColumnLayout { GroupBox { Layout.fillWidth: true - title: qsTr("Command") + Layout.fillHeight: true + title: qsTr("Miscellaneous") + padding: appSettings.defaultMargin ColumnLayout { anchors.fill: parent @@ -37,12 +39,6 @@ ColumnLayout { checked: appSettings.useCustomCommand onCheckedChanged: appSettings.useCustomCommand = checked } - // Workaround for QTBUG-31627 for pre 5.3.0 - Binding { - target: useCustomCommand - property: "checked" - value: appSettings.useCustomCommand - } TextField { id: customCommand Layout.fillWidth: true @@ -57,12 +53,27 @@ ColumnLayout { Component.onCompleted: settings_window.closing.connect( saveSetting) } + CheckBox { + id: blinkingCursor + text: qsTr("Blinking Cursor") + checked: appSettings.blinkingCursor + onCheckedChanged: appSettings.blinkingCursor = checked + } + CheckBox { + id: showMenubar + text: qsTr("Show Menubar") + enabled: !appSettings.isMacOS + checked: appSettings.showMenubar + onCheckedChanged: appSettings.showMenubar = checked + } } } GroupBox { title: qsTr("Performance") Layout.fillWidth: true + Layout.fillHeight: true + padding: appSettings.defaultMargin GridLayout { anchors.fill: parent columns: 4 @@ -73,24 +84,17 @@ ColumnLayout { Slider { Layout.fillWidth: true Layout.columnSpan: 2 - id: fpsSlider - onValueChanged: { - if (enabled) { - appSettings.fps = value !== 60 ? value + 1 : 0 - } - } + id: effectsFpsSlider + onValueChanged: appSettings.effectsFrameSkip = Math.round(value) stepSize: 1 - enabled: false - Component.onCompleted: { - from = 0 - to = 60 - value = appSettings.fps !== 0 ? appSettings.fps - 1 : 60 - enabled = true - } + enabled: true + from: 5 + to: 1 + value: appSettings.effectsFrameSkip } SizedLabel { - text: appSettings.fps !== 0 ? appSettings.fps : qsTr("Max") + text: Math.round(100 / Math.max(1, Math.round(effectsFpsSlider.value))) + "%" } Label { text: qsTr("Texture Quality") @@ -99,15 +103,11 @@ ColumnLayout { id: txtslider Layout.fillWidth: true Layout.columnSpan: 2 - onValueChanged: if (enabled) - appSettings.windowScaling = value + onValueChanged: appSettings.windowScaling = value stepSize: 0.05 - enabled: false - Component.onCompleted: { - from = 0.25 //Without this value gets set to 0.5 - value = appSettings.windowScaling - enabled = true - } + enabled: true + from: 0.25 + value: appSettings.windowScaling } SizedLabel { text: Math.round(txtslider.value * 100) + "%" @@ -120,15 +120,11 @@ ColumnLayout { Layout.fillWidth: true Layout.columnSpan: 2 id: bloomSlider - onValueChanged: if (enabled) - appSettings.bloomQuality = value + onValueChanged: appSettings.bloomQuality = value stepSize: 0.05 - enabled: false - Component.onCompleted: { - from = 0.25 - value = appSettings.bloomQuality - enabled = true - } + enabled: true + from: 0.25 + value: appSettings.bloomQuality } SizedLabel { text: Math.round(bloomSlider.value * 100) + "%" @@ -141,15 +137,11 @@ ColumnLayout { Layout.fillWidth: true id: burnInSlider Layout.columnSpan: 2 - onValueChanged: if (enabled) - appSettings.burnInQuality = value + onValueChanged: appSettings.burnInQuality = value stepSize: 0.05 - enabled: false - Component.onCompleted: { - from = 0.25 - value = appSettings.burnInQuality - enabled = true - } + enabled: true + from: 0.25 + value: appSettings.burnInQuality } SizedLabel { text: Math.round(burnInSlider.value * 100) + "%" diff --git a/app/qml/SettingsEffectsTab.qml b/app/qml/SettingsEffectsTab.qml index 9c97e55..2186aee 100644 --- a/app/qml/SettingsEffectsTab.qml +++ b/app/qml/SettingsEffectsTab.qml @@ -22,65 +22,74 @@ import QtQuick.Controls 2.0 import QtQuick.Layouts 1.1 ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true spacing: 2 GroupBox { title: qsTr("Effects") Layout.fillWidth: true + Layout.fillHeight: true + padding: appSettings.defaultMargin ColumnLayout { anchors.fill: parent CheckableSlider { name: qsTr("Bloom") - onNewValue: appSettings.bloom = newValue + onNewValue: function(newValue) { appSettings.bloom = newValue } value: appSettings.bloom } CheckableSlider { name: qsTr("BurnIn") - onNewValue: appSettings.burnIn = newValue + onNewValue: function(newValue) { appSettings.burnIn = newValue } value: appSettings.burnIn } CheckableSlider { name: qsTr("Static Noise") - onNewValue: appSettings.staticNoise = newValue + onNewValue: function(newValue) { appSettings.staticNoise = newValue } value: appSettings.staticNoise } CheckableSlider { name: qsTr("Jitter") - onNewValue: appSettings.jitter = newValue + onNewValue: function(newValue) { appSettings.jitter = newValue } value: appSettings.jitter } CheckableSlider { name: qsTr("Glow Line") - onNewValue: appSettings.glowingLine = newValue + onNewValue: function(newValue) { appSettings.glowingLine = newValue } value: appSettings.glowingLine } CheckableSlider { name: qsTr("Screen Curvature") - onNewValue: appSettings.screenCurvature = newValue + onNewValue: function(newValue) { appSettings.screenCurvature = newValue } value: appSettings.screenCurvature } CheckableSlider { name: qsTr("Ambient Light") - onNewValue: appSettings.ambientLight = newValue + onNewValue: function(newValue) { appSettings.ambientLight = newValue } value: appSettings.ambientLight enabled: appSettings.framesIndex !== 0 } CheckableSlider { name: qsTr("Flickering") - onNewValue: appSettings.flickering = newValue + onNewValue: function(newValue) { appSettings.flickering = newValue } value: appSettings.flickering } CheckableSlider { name: qsTr("Horizontal Sync") - onNewValue: appSettings.horizontalSync = newValue + onNewValue: function(newValue) { appSettings.horizontalSync = newValue } value: appSettings.horizontalSync } CheckableSlider { name: qsTr("RGB Shift") - onNewValue: appSettings.rbgShift = newValue - value: appSettings.rbgShift + onNewValue: function(newValue) { appSettings.rgbShift = newValue } + value: appSettings.rgbShift + } + CheckableSlider { + name: qsTr("Frame Shininess") + onNewValue: function(newValue) { appSettings._frameShininess = newValue } + value: appSettings._frameShininess } } } diff --git a/app/qml/SettingsGeneralTab.qml b/app/qml/SettingsGeneralTab.qml index 40fbc0d..66fa272 100644 --- a/app/qml/SettingsGeneralTab.qml +++ b/app/qml/SettingsGeneralTab.qml @@ -20,12 +20,14 @@ import QtQuick 2.2 import QtQuick.Controls 2.4 import QtQuick.Layouts 1.1 -import QtQuick.Dialogs 1.1 +import QtQuick.Dialogs ColumnLayout { GroupBox { Layout.fillWidth: true + Layout.fillHeight: true title: qsTr("Profile") + padding: appSettings.defaultMargin RowLayout { anchors.fill: parent ListView { @@ -183,6 +185,8 @@ ColumnLayout { GroupBox { title: qsTr("Screen") Layout.fillWidth: true + Layout.fillHeight: true + padding: appSettings.defaultMargin GridLayout { anchors.fill: parent columns: 2 @@ -207,12 +211,19 @@ ColumnLayout { onValueChanged: appSettings._margin = value value: appSettings._margin } + Label { + text: qsTr("Radius") + } + SimpleSlider { + onValueChanged: appSettings._screenRadius = value + value: appSettings._screenRadius + } Label { text: qsTr("Frame size") } SimpleSlider { - onValueChanged: appSettings._frameMargin = value - value: appSettings._frameMargin + onValueChanged: appSettings._frameSize = value + value: appSettings._frameSize } Label { text: qsTr("Opacity") @@ -237,6 +248,7 @@ ColumnLayout { MessageDialog { id: messageDialog title: qsTr("File Error") + buttons: MessageDialog.Ok onAccepted: { messageDialog.close() } @@ -248,10 +260,8 @@ ColumnLayout { sourceComponent: FileDialog { nameFilters: ["Json files (*.json)"] - selectMultiple: false - selectFolder: false - selectExisting: fileDialog.selectExisting - onAccepted: callBack(fileUrl) + fileMode: fileDialog.selectExisting ? FileDialog.OpenFile : FileDialog.SaveFile + onAccepted: callBack(selectedFile) } onSelectExistingChanged: reload() diff --git a/app/qml/SettingsTerminalTab.qml b/app/qml/SettingsTerminalTab.qml index 222ea78..c76831d 100644 --- a/app/qml/SettingsTerminalTab.qml +++ b/app/qml/SettingsTerminalTab.qml @@ -25,27 +25,50 @@ import QtQml 2.0 import "Components" ColumnLayout { - GroupBox { title: qsTr("Font") Layout.fillWidth: true + Layout.fillHeight: true + padding: appSettings.defaultMargin GridLayout { anchors.fill: parent columns: 2 Label { - text: qsTr("Rasterization") + text: qsTr("Source") + } + RowLayout { + Layout.fillWidth: true + RadioButton { + text: qsTr("Bundled") + checked: appSettings.fontSource === appSettings.bundled_fonts + onClicked: { + appSettings.fontSource = appSettings.bundled_fonts + } + } + RadioButton { + text: qsTr("System") + checked: appSettings.fontSource === appSettings.system_fonts + onClicked: { + appSettings.fontSource = appSettings.system_fonts + } + } + } + Label { + text: qsTr("Rendering") + enabled: appSettings.fontSource === appSettings.bundled_fonts } ComboBox { - id: rasterizationBox + id: renderingBox property string selectedElement: model[currentIndex] Layout.fillWidth: true - model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels"), qsTr("Sub-Pixels")] + model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels"), qsTr("Sub-Pixels"), qsTr("Modern")] currentIndex: appSettings.rasterization onCurrentIndexChanged: { appSettings.rasterization = currentIndex } + enabled: appSettings.fontSource === appSettings.bundled_fonts } Label { text: qsTr("Name") @@ -53,25 +76,43 @@ ColumnLayout { ComboBox { id: fontChanger Layout.fillWidth: true - model: appSettings.fontlist + model: appSettings.filteredFontList textRole: "text" onActivated: { - var name = appSettings.fontlist.get(index).name - appSettings.fontNames[appSettings.rasterization] = name - appSettings.handleFontChanged() + var font = appSettings.filteredFontList.get(currentIndex) + + // If selecting a high-res font while not in Modern mode, + // switch to Modern to render at full resolution. + if (!font.lowResolutionFont && appSettings.rasterization !== appSettings.modern_rasterization) { + appSettings.rasterization = appSettings.modern_rasterization + } + // If selecting a low-res font while in Modern mode, switch back to default. + if (font.lowResolutionFont && appSettings.rasterization === appSettings.modern_rasterization) { + appSettings.rasterization = appSettings.no_rasterization + } + + appSettings.fontName = font.name } function updateIndex() { - var name = appSettings.fontNames[appSettings.rasterization] - var index = appSettings.getIndexByName(name) - if (index !== undefined) - currentIndex = index + for (var i = 0; i < appSettings.filteredFontList.count; i++) { + var font = appSettings.filteredFontList.get(i) + if (font.name === appSettings.fontName) { + currentIndex = i + return + } + } + currentIndex = 0 } Connections { - target: appSettings + target: appSettings.fontManager onTerminalFontChanged: { fontChanger.updateIndex() } + + onFilteredFontListChanged: { + fontChanger.updateIndex() + } } Component.onCompleted: updateIndex() } @@ -111,41 +152,43 @@ ColumnLayout { text: Math.round(widthChanger.value * 100) + "%" } } - } - } - GroupBox { - title: qsTr("Cursor") - Layout.fillWidth: true - ColumnLayout { - anchors.fill: parent - CheckBox { - id: blinkingCursor - text: qsTr("Blinking Cursor") - checked: appSettings.blinkingCursor - onCheckedChanged: appSettings.blinkingCursor = checked + Label { + text: qsTr("Line Spacing") } - Binding { - target: blinkingCursor - property: "checked" - value: appSettings.blinkingCursor + RowLayout { + Layout.fillWidth: true + Slider { + Layout.fillWidth: true + id: lineSpacingChanger + onValueChanged: appSettings.lineSpacing = value + value: appSettings.lineSpacing + stepSize: 0.01 + from: 0.0 + to: 1.0 + } + SizedLabel { + text: Math.round(lineSpacingChanger.value * 100) + "%" + } } } } GroupBox { title: qsTr("Colors") Layout.fillWidth: true + Layout.fillHeight: true + padding: appSettings.defaultMargin ColumnLayout { anchors.fill: parent ColumnLayout { Layout.fillWidth: true CheckableSlider { name: qsTr("Chroma Color") - onNewValue: appSettings.chromaColor = newValue + onNewValue: function(newValue) { appSettings.chromaColor = newValue } value: appSettings.chromaColor } CheckableSlider { name: qsTr("Saturation Color") - onNewValue: appSettings.saturationColor = newValue + onNewValue: function(newValue) { appSettings.saturationColor = newValue } value: appSettings.saturationColor enabled: appSettings.chromaColor !== 0 } @@ -166,6 +209,13 @@ ColumnLayout { onColorSelected: appSettings._backgroundColor = color color: appSettings._backgroundColor } + ColorButton { + name: qsTr("Frame") + height: 50 + Layout.fillWidth: true + onColorSelected: appSettings._frameColor = color + color: appSettings._frameColor + } } } } diff --git a/app/qml/SettingsWindow.qml b/app/qml/SettingsWindow.qml index 435516b..eae71ff 100644 --- a/app/qml/SettingsWindow.qml +++ b/app/qml/SettingsWindow.qml @@ -22,54 +22,55 @@ import QtQuick 2.2 import QtQuick.Controls 2.1 import QtQuick.Window 2.1 import QtQuick.Layouts 1.3 -import QtQuick.Dialogs 1.1 +import QtQuick.Dialogs + +ApplicationWindow { + readonly property real tabButtonPadding: 10 -Window { id: settings_window title: qsTr("Settings") width: 640 - height: 640 - - property int tabmargins: 15 + height: 520 Item { - anchors { fill: parent; margins: tabmargins } + anchors { fill: parent; } TabBar { id: bar anchors { left: parent.left; right: parent.right; top: parent.top; } TabButton { + padding: tabButtonPadding text: qsTr("General") } TabButton { + padding: tabButtonPadding text: qsTr("Terminal") } TabButton { + padding: tabButtonPadding text: qsTr("Effects") } TabButton { + padding: tabButtonPadding text: qsTr("Advanced") } } - Frame { + StackLayout { anchors { top: bar.bottom left: parent.left right: parent.right bottom: parent.bottom + margins: 16 } - StackLayout { - anchors.fill: parent + currentIndex: bar.currentIndex - currentIndex: bar.currentIndex - - SettingsGeneralTab { } - SettingsTerminalTab { } - SettingsEffectsTab { } - SettingsAdvancedTab { } - } + SettingsGeneralTab { } + SettingsTerminalTab { } + SettingsEffectsTab { } + SettingsAdvancedTab { } } } } diff --git a/app/qml/ShaderLibrary.qml b/app/qml/ShaderLibrary.qml deleted file mode 100644 index ae95f05..0000000 --- a/app/qml/ShaderLibrary.qml +++ /dev/null @@ -1,91 +0,0 @@ -import QtQuick 2.0 - -QtObject { - property string rasterizationShader: - (appSettings.rasterization === appSettings.no_rasterization ? " - lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { - return texel; - }" : "") + - - (appSettings.rasterization === appSettings.scanline_rasterization ? " - #define INTENSITY 0.30 - #define BRIGHTBOOST 0.30 - - lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { - lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel; - lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel; - - vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0); - lowp float mask = 1.0 - abs(coords.y); - - lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); - return mix(texel, rasterizationColor, intensity); - }" : "") + - - (appSettings.rasterization === appSettings.pixel_rasterization ? " - #define INTENSITY 0.30 - #define BRIGHTBOOST 0.30 - - lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { - lowp vec3 result = texel; - - lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel; - lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel; - - vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0); - coords = coords * coords; - lowp float mask = 1.0 - coords.x - coords.y; - - lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); - return mix(texel, rasterizationColor, intensity); - }" : "") + - - (appSettings.rasterization === appSettings.subpixel_rasterization ? " - #define INTENSITY 0.30 - #define BRIGHTBOOST 0.30 - #define SUBPIXELS 3.0 - const vec3 offsets = vec3(3.141592654) * vec3(1.0/2.0,1.0/2.0 - 2.0/3.0,1.0/2.0-4.0/3.0); - - lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) { - vec2 omega = vec2(3.141592654) * vec2(2.0) * virtualResolution; - vec2 angle = screenCoords * omega; - vec3 xfactors = (SUBPIXELS + sin(angle.x + offsets)) / (SUBPIXELS + 1.0); - - lowp vec3 result = texel * xfactors; - lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * result)) * result; - lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * result)) * result; - - vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0); - lowp float mask = 1.0 - abs(coords.y); - - lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); - return mix(texel, rasterizationColor, intensity); - }" : "") + - - "\n\n" - - property string min2: " - float min2(vec2 v) { - return min(v.x, v.y); - }\n\n" - - property string rgb2grey: " - float rgb2grey(vec3 v) { - return dot(v, vec3(0.21, 0.72, 0.04)); - }\n\n" - - property string max2: " - float max2(vec2 v) { - return max(v.x, v.y); - }\n\n" - - property string prod2: " - float prod2(vec2 v) { - return v.x * v.y; - }\n\n" - - property string sum2: " - float sum2(vec2 v) { - return v.x + v.y; - }\n\n" -} diff --git a/app/qml/ShaderTerminal.qml b/app/qml/ShaderTerminal.qml index 2de0d9b..45deac8 100644 --- a/app/qml/ShaderTerminal.qml +++ b/app/qml/ShaderTerminal.qml @@ -19,11 +19,34 @@ *******************************************************************************/ import QtQuick 2.2 -import QtGraphicalEffects 1.0 import "utils.js" as Utils Item { + function dynamicFragmentPath() { + var rasterMode = appSettings.rasterization; + var burnInOn = appSettings.burnIn > 0 ? 1 : 0; + var frameOn = appSettings.frameEnabled ? 1 : 0; + var chromaOn = appSettings.chromaColor > 0 ? 1 : 0; + return "qrc:/shaders/terminal_dynamic_raster" + rasterMode + + "_burn" + burnInOn + + "_frame" + frameOn + + "_chroma" + chromaOn + + ".frag.qsb"; + } + + function staticFragmentPath() { + var rgbShiftOn = appSettings.rgbShift > 0 ? 1 : 0; + var bloomOn = appSettings.bloom > 0 ? 1 : 0; + var curvatureOn = (appSettings.screenCurvature > 0 || appSettings.frameSize > 0) ? 1 : 0; + var shineOn = appSettings.frameShininess > 0 ? 1 : 0; + return "qrc:/shaders/terminal_static_rgb" + rgbShiftOn + + "_bloom" + bloomOn + + "_curve" + curvatureOn + + "_shine" + shineOn + + ".frag.qsb"; + } + property ShaderEffectSource source property BurnInEffect burnInEffect property ShaderEffectSource bloomSource @@ -31,7 +54,8 @@ Item { property color fontColor: appSettings.fontColor property color backgroundColor: appSettings.backgroundColor - property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize + property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize * terminalWindow.normalizedWindowScale + property real frameSize: appSettings.frameSize * terminalWindow.normalizedWindowScale property real chromaColor: appSettings.chromaColor @@ -45,469 +69,132 @@ Item { screenResolution.height / virtualResolution.height ) - ShaderEffect { - id: dynamicShader + ShaderEffect { + id: dynamicShader + + property ShaderEffectSource screenBuffer: frameBuffer + property ShaderEffectSource burnInSource: burnInEffect.effectSource + property ShaderEffectSource frameSource: terminalFrameLoader.item - property ShaderLibrary shaderLibrary: ShaderLibrary { } + property color fontColor: parent.fontColor + property color backgroundColor: parent.backgroundColor + property real screenCurvature: parent.screenCurvature + property real chromaColor: parent.chromaColor + property real ambientLight: parent.ambientLight - property ShaderEffectSource screenBuffer: frameBuffer - property ShaderEffectSource burnInSource: burnInEffect.source - property ShaderEffectSource frameSource: terminalFrameLoader.item + property real flickering: appSettings.flickering + property real horizontalSync: appSettings.horizontalSync + property real horizontalSyncStrength: Utils.lint(0.05, 0.35, horizontalSync) + property real glowingLine: appSettings.glowingLine * 0.2 - property color fontColor: parent.fontColor - property color backgroundColor: parent.backgroundColor - property real screenCurvature: parent.screenCurvature - property real chromaColor: parent.chromaColor - property real ambientLight: parent.ambientLight + // Fast burnin properties + property real burnIn: appSettings.burnIn + property real burnInLastUpdate: burnInEffect.lastUpdate + property real burnInTime: burnInEffect.burnInFadeTime - property real flickering: appSettings.flickering - property real horizontalSync: appSettings.horizontalSync - property real horizontalSyncStrength: Utils.lint(0.05, 0.35, horizontalSync) - property real glowingLine: appSettings.glowingLine * 0.2 + property real jitter: appSettings.jitter + property size jitterDisplacement: Qt.size(0.007 * jitter, 0.002 * jitter) + property real staticNoise: appSettings.staticNoise + property size scaleNoiseSize: Qt.size((width * 0.75) / (noiseTexture.width * appSettings.windowScaling * appSettings.totalFontScaling), + (height * 0.75) / (noiseTexture.height * appSettings.windowScaling * appSettings.totalFontScaling)) + + property size virtualResolution: parent.virtualResolution + + // Rasterization might display oversamping issues if virtual resolution is close to physical display resolution. + // We progressively disable rasterization from 4x up to 2x resolution. + property real rasterizationIntensity: Utils.smoothstep(2.0, 4.0, _screenDensity) + + property real time: timeManager ? timeManager.time : 0 + property ShaderEffectSource noiseSource: noiseShaderSource + + property real frameSize: parent.frameSize + property real frameShininess: appSettings.frameShininess + property real bloom: parent.bloomSource ? appSettings.bloom * 2.5 : 0 + + anchors.fill: parent + blending: false + + Image { + id: noiseTexture + source: "images/allNoise512.png" + width: 512 + height: 512 + fillMode: Image.Tile + visible: false + } + ShaderEffectSource { + id: noiseShaderSource + sourceItem: noiseTexture + wrapMode: ShaderEffectSource.Repeat + visible: false + smooth: true + } + + vertexShader: "qrc:/shaders/terminal_dynamic.vert.qsb" + fragmentShader: dynamicFragmentPath() + + onStatusChanged: if (log) console.log(log) + } + + Loader { + id: terminalFrameLoader + + active: appSettings.frameEnabled + + width: staticShader.width + height: staticShader.height + + sourceComponent: ShaderEffectSource { + + sourceItem: terminalFrame + hideSource: true + visible: false + format: ShaderEffectSource.RGBA + + TerminalFrame { + id: terminalFrame + blending: false + anchors.fill: parent + } + } + } + + ShaderEffect { + id: staticShader + + width: parent.width * appSettings.windowScaling + height: parent.height * appSettings.windowScaling + + property ShaderEffectSource source: parent.source + property ShaderEffectSource bloomSource: parent.bloomSource + + property color fontColor: parent.fontColor + property color backgroundColor: parent.backgroundColor + property real bloom: bloomSource ? appSettings.bloom * 2.5 : 0 - // Fast burnin properties - property real burnIn: appSettings.burnIn - property real burnInLastUpdate: burnInEffect.lastUpdate - property real burnInTime: burnInEffect.burnInFadeTime + property real screenCurvature: parent.screenCurvature + + property real chromaColor: appSettings.chromaColor; - property real jitter: appSettings.jitter - property size jitterDisplacement: Qt.size(0.007 * jitter, 0.002 * jitter) - property real shadowLength: 0.25 * screenCurvature * Utils.lint(0.50, 1.5, ambientLight) - property real staticNoise: appSettings.staticNoise - property size scaleNoiseSize: Qt.size((width * 0.75) / (noiseTexture.width * appSettings.windowScaling * appSettings.totalFontScaling), - (height * 0.75) / (noiseTexture.height * appSettings.windowScaling * appSettings.totalFontScaling)) + property real rgbShift: appSettings.rgbShift * (4.0 / width) * appSettings.totalFontScaling + + property real screen_brightness: Utils.lint(0.5, 1.5, appSettings.brightness) + property real frameShininess: appSettings.frameShininess + property real frameSize: parent.frameSize - property size virtualResolution: parent.virtualResolution + blending: false + visible: false - // Rasterization might display oversamping issues if virtual resolution is close to physical display resolution. - // We progressively disable rasterization from 4x up to 2x resolution. - property real rasterizationIntensity: Utils.smoothstep(2.0, 4.0, _screenDensity) + vertexShader: "qrc:/shaders/terminal_static.vert.qsb" + fragmentShader: staticFragmentPath() - property real displayTerminalFrame: appSettings._frameMargin > 0 || appSettings.screenCurvature > 0 + onStatusChanged: if (log) console.log(log) + } - property real time: timeManager.time - property ShaderEffectSource noiseSource: noiseShaderSource - - // If something goes wrong activate the fallback version of the shader. - property bool fallBack: false - - anchors.fill: parent - blending: false - - //Smooth random texture used for flickering effect. - Image { - id: noiseTexture - source: "images/allNoise512.png" - width: 512 - height: 512 - fillMode: Image.Tile - visible: false - } - ShaderEffectSource { - id: noiseShaderSource - sourceItem: noiseTexture - wrapMode: ShaderEffectSource.Repeat - visible: false - smooth: true - } - - //Print the number with a reasonable precision for the shader. - function str(num){ - return num.toFixed(8); - } - - vertexShader: " - uniform highp mat4 qt_Matrix; - uniform highp float time; - - attribute highp vec4 qt_Vertex; - attribute highp vec2 qt_MultiTexCoord0; - - varying highp vec2 qt_TexCoord0;" + - - (!fallBack ? " - uniform sampler2D noiseSource;" : "") + - - (!fallBack && flickering !== 0.0 ?" - varying lowp float brightness; - uniform lowp float flickering;" : "") + - - (!fallBack && horizontalSync !== 0.0 ?" - uniform lowp float horizontalSyncStrength; - varying lowp float distortionScale; - varying lowp float distortionFreq;" : "") + - - " - void main() { - qt_TexCoord0 = qt_MultiTexCoord0; - vec2 coords = vec2(fract(time/(1024.0*2.0)), fract(time/(1024.0*1024.0)));" + - - (!fallBack && (flickering !== 0.0 || horizontalSync !== 0.0) ? - "vec4 initialNoiseTexel = texture2D(noiseSource, coords);" - : "") + - - (!fallBack && flickering !== 0.0 ? " - brightness = 1.0 + (initialNoiseTexel.g - 0.5) * flickering;" - : "") + - - (!fallBack && horizontalSync !== 0.0 ? " - float randval = horizontalSyncStrength - initialNoiseTexel.r; - distortionScale = step(0.0, randval) * randval * horizontalSyncStrength; - distortionFreq = mix(4.0, 40.0, initialNoiseTexel.g);" - : "") + - - "gl_Position = qt_Matrix * qt_Vertex; - }" - - fragmentShader: " - #ifdef GL_ES - precision mediump float; - #endif - - uniform sampler2D screenBuffer; - uniform highp float qt_Opacity; - uniform highp float time; - varying highp vec2 qt_TexCoord0; - - uniform highp vec4 fontColor; - uniform highp vec4 backgroundColor; - uniform lowp float shadowLength; - - uniform highp vec2 virtualResolution; - uniform lowp float rasterizationIntensity;\n" + - - (burnIn !== 0 ? " - uniform sampler2D burnInSource; - uniform highp float burnInLastUpdate; - uniform highp float burnInTime;" : "") + - (staticNoise !== 0 ? " - uniform highp float staticNoise;" : "") + - (((staticNoise !== 0 || jitter !== 0) ||(fallBack && (flickering || horizontalSync))) ? " - uniform lowp sampler2D noiseSource; - uniform highp vec2 scaleNoiseSize;" : "") + - (displayTerminalFrame ? " - uniform lowp sampler2D frameSource;" : "") + - (screenCurvature !== 0 ? " - uniform highp float screenCurvature;" : "") + - (glowingLine !== 0 ? " - uniform highp float glowingLine;" : "") + - (chromaColor !== 0 ? " - uniform lowp float chromaColor;" : "") + - (jitter !== 0 ? " - uniform lowp vec2 jitterDisplacement;" : "") + - (ambientLight !== 0 ? " - uniform lowp float ambientLight;" : "") + - - (fallBack && horizontalSync !== 0 ? " - uniform lowp float horizontalSyncStrength;" : "") + - (fallBack && flickering !== 0.0 ?" - uniform lowp float flickering;" : "") + - (!fallBack && flickering !== 0 ? " - varying lowp float brightness;" - : "") + - (!fallBack && horizontalSync !== 0 ? " - varying lowp float distortionScale; - varying lowp float distortionFreq;" : "") + - - (glowingLine !== 0 ? " - float randomPass(vec2 coords){ - return fract(smoothstep(-120.0, 0.0, coords.y - (virtualResolution.y + 120.0) * fract(time * 0.00015))); - }" : "") + - - shaderLibrary.min2 + - shaderLibrary.rgb2grey + - shaderLibrary.rasterizationShader + - - " - float isInScreen(vec2 v) { - return min2(step(0.0, v) - step(1.0, v)); - } - - vec2 barrel(vec2 v, vec2 cc) {" + - - (screenCurvature !== 0 ? " - float distortion = dot(cc, cc) * screenCurvature; - return (v - cc * (1.0 + distortion) * distortion);" - : - "return v;") + - "}" + - - "vec3 convertWithChroma(vec3 inColor) { - vec3 outColor = inColor;" + - - (chromaColor !== 0 ? - "outColor = fontColor.rgb * mix(vec3(rgb2grey(inColor)), inColor, chromaColor);" - : - "outColor = fontColor.rgb * rgb2grey(inColor);") + - - " return outColor; - }" + - - "void main() {" + - "vec2 cc = vec2(0.5) - qt_TexCoord0;" + - "float distance = length(cc);" + - - //FallBack if there are problems - (fallBack && (flickering !== 0.0 || horizontalSync !== 0.0) ? - "vec2 initialCoords = vec2(fract(time/(1024.0*2.0)), fract(time/(1024.0*1024.0))); - vec4 initialNoiseTexel = texture2D(noiseSource, initialCoords);" - : "") + - (fallBack && flickering !== 0.0 ? " - float brightness = 1.0 + (initialNoiseTexel.g - 0.5) * flickering;" - : "") + - (fallBack && horizontalSync !== 0.0 ? " - float randval = horizontalSyncStrength - initialNoiseTexel.r; - float distortionScale = step(0.0, randval) * randval * horizontalSyncStrength; - float distortionFreq = mix(4.0, 40.0, initialNoiseTexel.g);" - : "") + - - (staticNoise ? " - float noise = staticNoise;" : "") + - - (screenCurvature !== 0 ? " - vec2 staticCoords = barrel(qt_TexCoord0, cc);" - :" - vec2 staticCoords = qt_TexCoord0;") + - - "vec2 coords = qt_TexCoord0;" + - - (horizontalSync !== 0 ? " - float dst = sin((coords.y + time * 0.001) * distortionFreq); - coords.x += dst * distortionScale;" + - - (staticNoise ? " - noise += distortionScale * 7.0;" : "") - - : "") + - - (jitter !== 0 || staticNoise !== 0 ? - "vec4 noiseTexel = texture2D(noiseSource, scaleNoiseSize * coords + vec2(fract(time / 51.0), fract(time / 237.0)));" - : "") + - - (jitter !== 0 ? " - vec2 offset = vec2(noiseTexel.b, noiseTexel.a) - vec2(0.5); - vec2 txt_coords = coords + offset * jitterDisplacement;" - : "vec2 txt_coords = coords;") + - - "float color = 0.0001;" + - - (staticNoise !== 0 ? " - float noiseVal = noiseTexel.a; - color += noiseVal * noise * (1.0 - distance * 1.3);" : "") + - - (glowingLine !== 0 ? " - color += randomPass(coords * virtualResolution) * glowingLine;" : "") + - - "vec3 txt_color = texture2D(screenBuffer, txt_coords).rgb;" + - - (burnIn !== 0 ? " - vec4 txt_blur = texture2D(burnInSource, staticCoords); - float blurDecay = clamp((time - burnInLastUpdate) * burnInTime, 0.0, 1.0); - vec3 burnInColor = 0.65 * (txt_blur.rgb - vec3(blurDecay)); - txt_color = max(txt_color, convertWithChroma(burnInColor));" - : "") + - - "txt_color += fontColor.rgb * vec3(color);" + - - "txt_color = applyRasterization(staticCoords, txt_color, virtualResolution, rasterizationIntensity);\n" + - - "vec3 finalColor = txt_color;" + - - (flickering !== 0 ? " - finalColor *= brightness;" : "") + - - (ambientLight !== 0 ? " - finalColor += vec3(ambientLight) * (1.0 - distance) * (1.0 - distance);" : "") + - - (displayTerminalFrame ? - "vec4 frameColor = texture2D(frameSource, qt_TexCoord0); - finalColor = mix(finalColor, frameColor.rgb, frameColor.a);" - : "") + - - "gl_FragColor = vec4(finalColor, qt_Opacity);" + - "}" - - onStatusChanged: { - // Print warning messages - if (log) - console.log(log); - - // Activate fallback mode - if (status == ShaderEffect.Error) { - fallBack = true; - } - } - } - - Loader { - id: terminalFrameLoader - - active: dynamicShader.displayTerminalFrame - - width: staticShader.width - height: staticShader.height - - sourceComponent: ShaderEffectSource { - - sourceItem: terminalFrame - hideSource: true - visible: false - format: ShaderEffectSource.RGBA - - TerminalFrame { - id: terminalFrame - blending: false - anchors.fill: parent - } - } - } - - ShaderLibrary { - id: shaderLibrary - } - - ShaderEffect { - id: staticShader - - width: parent.width * appSettings.windowScaling - height: parent.height * appSettings.windowScaling - - property ShaderEffectSource source: parent.source - property ShaderEffectSource bloomSource: parent.bloomSource - - property color fontColor: parent.fontColor - property color backgroundColor: parent.backgroundColor - property real bloom: appSettings.bloom * 2.5 - - property real screenCurvature: parent.screenCurvature - - property real chromaColor: appSettings.chromaColor; - - property real rbgShift: (appSettings.rbgShift / width) * appSettings.totalFontScaling // TODO FILIPPO width here is wrong. - - property int rasterization: appSettings.rasterization - - property real screen_brightness: Utils.lint(0.5, 1.5, appSettings.brightness) - - property real ambientLight: parent.ambientLight - - property size virtualResolution: parent.virtualResolution - - blending: false - visible: false - - //Print the number with a reasonable precision for the shader. - function str(num){ - return num.toFixed(8); - } - - fragmentShader: " - #ifdef GL_ES - precision mediump float; - #endif - - uniform sampler2D source; - uniform highp float qt_Opacity; - varying highp vec2 qt_TexCoord0; - - uniform highp vec4 fontColor; - uniform highp vec4 backgroundColor; - uniform lowp float screen_brightness; - - uniform highp vec2 virtualResolution;" + - - (bloom !== 0 ? " - uniform highp sampler2D bloomSource; - uniform lowp float bloom;" : "") + - - (screenCurvature !== 0 ? " - uniform highp float screenCurvature;" : "") + - - (chromaColor !== 0 ? " - uniform lowp float chromaColor;" : "") + - - (rbgShift !== 0 ? " - uniform lowp float rbgShift;" : "") + - - (ambientLight !== 0 ? " - uniform lowp float ambientLight;" : "") + - - shaderLibrary.min2 + - shaderLibrary.sum2 + - shaderLibrary.rgb2grey + - - "vec3 convertWithChroma(vec3 inColor) { - vec3 outColor = inColor;" + - - (chromaColor !== 0 ? - "outColor = fontColor.rgb * mix(vec3(rgb2grey(inColor)), inColor, chromaColor);" - : - "outColor = fontColor.rgb * rgb2grey(inColor);") + - - " return outColor; - }" + - - shaderLibrary.rasterizationShader + - - "void main() {" + - "vec2 cc = vec2(0.5) - qt_TexCoord0;" + - - (screenCurvature !== 0 ? " - float distortion = dot(cc, cc) * screenCurvature; - vec2 curvatureCoords = (qt_TexCoord0 - cc * (1.0 + distortion) * distortion); - vec2 txt_coords = - 2.0 * curvatureCoords + 3.0 * step(vec2(0.0), curvatureCoords) * curvatureCoords - 3.0 * step(vec2(1.0), curvatureCoords) * curvatureCoords;" - :" - vec2 txt_coords = qt_TexCoord0;") + - - "vec3 txt_color = texture2D(source, txt_coords).rgb;" + - - (rbgShift !== 0 ? " - vec2 displacement = vec2(12.0, 0.0) * rbgShift; - vec3 rightColor = texture2D(source, txt_coords + displacement).rgb; - vec3 leftColor = texture2D(source, txt_coords - displacement).rgb; - txt_color.r = leftColor.r * 0.10 + rightColor.r * 0.30 + txt_color.r * 0.60; - txt_color.g = leftColor.g * 0.20 + rightColor.g * 0.20 + txt_color.g * 0.60; - txt_color.b = leftColor.b * 0.30 + rightColor.b * 0.10 + txt_color.b * 0.60; - " : "") + - - "txt_color += vec3(0.0001);" + - "float greyscale_color = rgb2grey(txt_color);" + - - (screenCurvature !== 0 ? " - float reflectionMask = sum2(step(vec2(0.0), curvatureCoords) - step(vec2(1.0), curvatureCoords)); - reflectionMask = clamp(reflectionMask, 0.0, 1.0);" - : - "float reflectionMask = 1.0;") + - - (chromaColor !== 0 ? - "vec3 foregroundColor = mix(fontColor.rgb, txt_color * fontColor.rgb / greyscale_color, chromaColor); - vec3 finalColor = mix(backgroundColor.rgb, foregroundColor, greyscale_color * reflectionMask);" - : - "vec3 finalColor = mix(backgroundColor.rgb, fontColor.rgb, greyscale_color * reflectionMask);") + - - (bloom !== 0 ? - "vec4 bloomFullColor = texture2D(bloomSource, txt_coords); - vec3 bloomColor = bloomFullColor.rgb; - float bloomAlpha = bloomFullColor.a; - bloomColor = convertWithChroma(bloomColor); - finalColor += clamp(bloomColor * bloom * bloomAlpha, 0.0, 0.5);" - : "") + - - "finalColor *= screen_brightness;" + - - "gl_FragColor = vec4(finalColor, qt_Opacity);" + - "}" - - onStatusChanged: { - // Print warning messages - if (log) console.log(log); - } - } - - ShaderEffectSource { - id: frameBuffer - visible: false - sourceItem: staticShader - hideSource: true - } + ShaderEffectSource { + id: frameBuffer + visible: false + sourceItem: staticShader + hideSource: true + } } diff --git a/app/qml/SizeOverlay.qml b/app/qml/SizeOverlay.qml index 247534d..055da64 100644 --- a/app/qml/SizeOverlay.qml +++ b/app/qml/SizeOverlay.qml @@ -21,15 +21,13 @@ import QtQuick 2.2 Rectangle { property size terminalSize - property real topOpacity: 0.6 + property real topOpacity: 0.5 width: textSize.width * 2 height: textSize.height * 2 radius: 5 - border.width: 2 - border.color: "white" color: "black" - opacity: sizetimer.running ? 0.6 : 0.0 + opacity: sizetimer.running ? 0.5 : 0.0 Behavior on opacity { NumberAnimation { diff --git a/app/qml/Storage.qml b/app/qml/Storage.qml index cd6699d..1f2014f 100644 --- a/app/qml/Storage.qml +++ b/app/qml/Storage.qml @@ -22,7 +22,7 @@ import QtQuick 2.2 import QtQuick.LocalStorage 2.0 QtObject { - readonly property string dbMajorVersion: "1" + readonly property string dbMajorVersion: "2" readonly property string dbMinorVersion: "1.0" property bool initialized: false diff --git a/app/qml/TerminalContainer.qml b/app/qml/TerminalContainer.qml index b6be435..9074893 100644 --- a/app/qml/TerminalContainer.qml +++ b/app/qml/TerminalContainer.qml @@ -18,15 +18,23 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ import QtQuick 2.2 -import QtGraphicalEffects 1.0 +import Qt5Compat.GraphicalEffects import "utils.js" as Utils ShaderTerminal { property alias title: terminal.title property alias terminalSize: terminal.terminalSize + signal sessionFinished() - property real devicePixelRatio: terminalWindow.screen.devicePixelRatio + property bool loadBloomEffect: appSettings.bloom > 0 || appSettings._frameShininess > 0 + property bool hasFocus + + onHasFocusChanged: { + if (hasFocus) { + activate() + } + } id: mainShader opacity: appSettings.windowOpacity * 0.3 + 0.7 @@ -35,24 +43,25 @@ ShaderTerminal { burnInEffect: terminal.burnInEffect virtualResolution: terminal.virtualResolution screenResolution: Qt.size( - terminalWindow.width * devicePixelRatio * appSettings.windowScaling, - terminalWindow.height * devicePixelRatio * appSettings.windowScaling + terminalWindow.width * Screen.devicePixelRatio * appSettings.windowScaling, + terminalWindow.height * Screen.devicePixelRatio * appSettings.windowScaling ) - - TimeManager { - id: timeManager - enableTimer: terminalWindow.visible - } + bloomSource: bloomSourceLoader.item PreprocessedTerminal { id: terminal anchors.fill: parent + onSessionFinished: mainShader.sessionFinished() + } + + function activate() { + terminal.mainTerminal.forceActiveFocus() } // EFFECTS //////////////////////////////////////////////////////////////// Loader { id: bloomEffectLoader - active: appSettings.bloom + active: loadBloomEffect asynchronous: true width: parent.width * appSettings.bloomQuality height: parent.height * appSettings.bloomQuality @@ -65,16 +74,15 @@ ShaderTerminal { } Loader { id: bloomSourceLoader - active: appSettings.bloom !== 0 + active: loadBloomEffect asynchronous: true sourceComponent: ShaderEffectSource { id: _bloomEffectSource sourceItem: bloomEffectLoader.item + wrapMode: ShaderEffectSource.Repeat hideSource: true smooth: true visible: false } } - - bloomSource: bloomSourceLoader.item } diff --git a/app/qml/TerminalFrame.qml b/app/qml/TerminalFrame.qml index 3e1baef..c651281 100644 --- a/app/qml/TerminalFrame.qml +++ b/app/qml/TerminalFrame.qml @@ -22,83 +22,31 @@ import QtQuick 2.0 import "utils.js" as Utils ShaderEffect { - property color _staticFrameColor: "#fff" + property color _staticFrameColor: Utils.sum(appSettings.frameColor, Qt.rgba(0.1, 0.1, 0.1, 1.0)) property color _backgroundColor: appSettings.backgroundColor property color _fontColor: appSettings.fontColor property color _lightColor: Utils.mix(_fontColor, _backgroundColor, 0.2) - property real _ambientLight: Utils.lint(0.2, 0.8, appSettings.ambientLight) - property color frameColor: Utils.mix(_staticFrameColor, _lightColor, _ambientLight) - property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize - - // Coefficient of the log curve used to approximate shadowing - property real screenShadowCoeff: Utils.lint(20.0, 10.0, _ambientLight) - property real frameShadowCoeff: Utils.lint(20.0, 10.0, _ambientLight) - - property size margin: Qt.size( - appSettings.frameMargin / width * appSettings.windowScaling, - appSettings.frameMargin / height * appSettings.windowScaling + property color frameColor: Utils.mix( + Utils.scaleColor(_lightColor, 0.2), + _staticFrameColor, + 0.125 + 0.750 * ambientLight ) - ShaderLibrary { - id: shaderLibrary - } + property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize * terminalWindow.normalizedWindowScale - fragmentShader: " - #ifdef GL_ES - precision mediump float; - #endif + property real frameShininess: appSettings.frameShininess - uniform lowp float screenCurvature; - uniform lowp float screenShadowCoeff; - uniform lowp float frameShadowCoeff; - uniform highp float qt_Opacity; - uniform lowp vec4 frameColor; - uniform mediump vec2 margin; + property real frameSize: appSettings.frameSize * terminalWindow.normalizedWindowScale - varying highp vec2 qt_TexCoord0; + property real screenRadius: appSettings.screenRadius - vec2 distortCoordinates(vec2 coords){ - vec2 cc = (coords - vec2(0.5)); - float dist = dot(cc, cc) * screenCurvature; - return (coords + cc * (1.0 + dist) * dist); - } - " + + property size viewportSize: Qt.size(width / appSettings.windowScaling, height / appSettings.windowScaling) - shaderLibrary.max2 + - shaderLibrary.min2 + - shaderLibrary.prod2 + - shaderLibrary.sum2 + + property real ambientLight: appSettings.ambientLight - " - - vec2 positiveLog(vec2 x) { - return clamp(log(x), vec2(0.0), vec2(100.0)); - } - - void main() { - vec2 staticCoords = qt_TexCoord0; - vec2 coords = distortCoordinates(staticCoords) * (vec2(1.0) + margin * 2.0) - margin; - - vec2 vignetteCoords = staticCoords * (1.0 - staticCoords.yx); - float vignette = pow(prod2(vignetteCoords) * 15.0, 0.25); - - vec3 color = frameColor.rgb * vec3(1.0 - vignette); - float alpha = 0.0; - - float frameShadow = max2(positiveLog(-coords * frameShadowCoeff + vec2(1.0)) + positiveLog(coords * frameShadowCoeff - (vec2(frameShadowCoeff) - vec2(1.0)))); - frameShadow = max(sqrt(frameShadow), 0.0); - color *= frameShadow; - alpha = sum2(1.0 - step(vec2(0.0), coords) + step(vec2(1.0), coords)); - alpha = clamp(alpha, 0.0, 1.0); - alpha *= mix(1.0, 0.9, frameShadow); - - float screenShadow = 1.0 - prod2(positiveLog(coords * screenShadowCoeff + vec2(1.0)) * positiveLog(-coords * screenShadowCoeff + vec2(screenShadowCoeff + 1.0))); - alpha = max(0.8 * screenShadow, alpha); - - gl_FragColor = vec4(color * alpha, alpha); - } - " + vertexShader: "qrc:/shaders/terminal_frame.vert.qsb" + fragmentShader: "qrc:/shaders/terminal_frame.frag.qsb" onStatusChanged: if (log) console.log(log) //Print warning messages } diff --git a/app/qml/TerminalTabs.qml b/app/qml/TerminalTabs.qml new file mode 100644 index 0000000..5a917b6 --- /dev/null +++ b/app/qml/TerminalTabs.qml @@ -0,0 +1,153 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*******************************************************************************/ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQml.Models + +Item { + id: tabsRoot + + readonly property int innerPadding: 6 + readonly property string currentTitle: tabsModel.get(currentIndex).title ?? "cool-retro-term" + property alias currentIndex: tabBar.currentIndex + readonly property int count: tabsModel.count + property size terminalSize: Qt.size(0, 0) + + function normalizeTitle(rawTitle) { + if (rawTitle === undefined || rawTitle === null) { + return "" + } + return String(rawTitle).trim() + } + + function addTab() { + tabsModel.append({ title: "" }) + tabBar.currentIndex = tabsModel.count - 1 + } + + function closeTab(index) { + if (tabsModel.count <= 1) { + terminalWindow.close() + return + } + + tabsModel.remove(index) + tabBar.currentIndex = Math.min(tabBar.currentIndex, tabsModel.count - 1) + } + + ListModel { + id: tabsModel + } + + Component.onCompleted: addTab() + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + Rectangle { + id: tabRow + Layout.fillWidth: true + height: rowLayout.implicitHeight + color: palette.window + visible: tabsModel.count > 1 + + RowLayout { + id: rowLayout + anchors.fill: parent + spacing: 0 + + TabBar { + id: tabBar + Layout.fillWidth: true + Layout.fillHeight: true + focusPolicy: Qt.NoFocus + + Repeater { + model: tabsModel + TabButton { + id: tabButton + contentItem: RowLayout { + anchors.fill: parent + anchors { leftMargin: innerPadding; rightMargin: innerPadding } + spacing: innerPadding + + Label { + text: model.title + elide: Text.ElideRight + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + ToolButton { + text: "\u00d7" + focusPolicy: Qt.NoFocus + padding: innerPadding + Layout.alignment: Qt.AlignVCenter + onClicked: tabsRoot.closeTab(index) + } + } + } + } + } + + ToolButton { + id: addTabButton + text: "+" + focusPolicy: Qt.NoFocus + Layout.fillHeight: true + padding: innerPadding + Layout.alignment: Qt.AlignVCenter + onClicked: tabsRoot.addTab() + } + } + } + + StackLayout { + id: stack + Layout.fillWidth: true + Layout.fillHeight: true + currentIndex: tabBar.currentIndex + + Repeater { + model: tabsModel + TerminalContainer { + id: terminalContainer + hasFocus: terminalWindow.active && StackLayout.isCurrentItem + + onTerminalSizeChanged: updateTerminalSize() + + onTitleChanged: tabsModel.setProperty(index, "title", normalizeTitle(title)) + Layout.fillWidth: true + Layout.fillHeight: true + onSessionFinished: tabsRoot.closeTab(index) + + function updateTerminalSize() { + // Every tab will have the same size so we can simply take the first one. + if (index == 0) { + tabsRoot.terminalSize = terminalSize + } + } + } + } + } + } +} diff --git a/app/qml/TerminalWindow.qml b/app/qml/TerminalWindow.qml new file mode 100644 index 0000000..003a50e --- /dev/null +++ b/app/qml/TerminalWindow.qml @@ -0,0 +1,88 @@ +/******************************************************************************* +* Copyright (c) 2013-2021 "Filippo Scognamiglio" +* https://github.com/Swordfish90/cool-retro-term +* +* This file is part of cool-retro-term. +* +* cool-retro-term is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*******************************************************************************/ +import QtQuick 2.2 +import QtQuick.Window 2.1 +import QtQuick.Controls 2.3 +import QtQml + +import "menus" + +ApplicationWindow { + id: terminalWindow + + width: 1024 + height: 768 + + // Show the window once it is ready. + Component.onCompleted: { + visible = true + } + + minimumWidth: 320 + minimumHeight: 240 + + visible: false + + property bool fullscreen: false + onFullscreenChanged: visibility = (fullscreen ? Window.FullScreen : Window.Windowed) + + menuBar: qtquickMenuLoader.item + + Loader { + id: qtquickMenuLoader + active: !appSettings.isMacOS && (appSettings.showMenubar && !fullscreen) + sourceComponent: WindowMenu { } + } + + Connections { + target: newTabAction + enabled: terminalWindow.active + onTriggered: terminalTabs.addTab() + } + + Connections { + target: fullscreenAction + enabled: terminalWindow.active + onTriggered: terminalWindow.fullscreen = !terminalWindow.fullscreen + } + + property real normalizedWindowScale: 1024 / ((0.5 * width + 0.5 * height)) + + color: "#00000000" + + title: terminalTabs.currentTitle + + TerminalTabs { + id: terminalTabs + width: parent.width + height: (parent.height + Math.abs(y)) + } + Loader { + anchors.centerIn: parent + active: appSettings.showTerminalSize + sourceComponent: SizeOverlay { + z: 3 + terminalSize: terminalTabs.terminalSize + } + } + onClosing: { + appRoot.closeWindow(terminalWindow) + } +} diff --git a/app/qml/TimeManager.qml b/app/qml/TimeManager.qml index 6424af2..7f0a428 100644 --- a/app/qml/TimeManager.qml +++ b/app/qml/TimeManager.qml @@ -17,22 +17,29 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ -import QtQuick 2.2 +import QtQuick -Timer { - default property bool enableTimer: false - property real time +QtObject { + id: timeManager - NumberAnimation on time { - from: 0 - to: 100000 - running: appSettings.fps === 0 && enableTimer - duration: 100000 - loops: Animation.Infinite + property bool enableTimer: false + property real time: 0 + + property int framesPerUpdate: Math.max(1, appSettings.effectsFrameSkip) + property int _frameCounter: 0 + + property var frameDriver: FrameAnimation { + running: enableTimer + onTriggered: { + timeManager._frameCounter += 1 + + if (timeManager._frameCounter >= timeManager.framesPerUpdate) { + time = elapsedTime + timeManager._frameCounter = 0 + } + } } - onTriggered: time += interval - running: appSettings.fps !== 0 && enableTimer - interval: Math.round(1000 / appSettings.fps) - repeat: true + onEnableTimerChanged: if (!enableTimer) _frameCounter = 0 + onFramesPerUpdateChanged: _frameCounter = 0 } diff --git a/app/qml/fonts/1971-ibm-3278/3270-Regular.ttf b/app/qml/fonts/1971-ibm-3278/3270-Regular.ttf deleted file mode 100644 index d0a7271..0000000 Binary files a/app/qml/fonts/1971-ibm-3278/3270-Regular.ttf and /dev/null differ diff --git a/app/qml/fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf b/app/qml/fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf deleted file mode 100644 index 672aac7..0000000 Binary files a/app/qml/fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf and /dev/null differ diff --git a/app/qml/fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf b/app/qml/fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf deleted file mode 100644 index 3e1a82a..0000000 Binary files a/app/qml/fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf and /dev/null differ diff --git a/app/qml/fonts/1982-commodore64/license.txt b/app/qml/fonts/1982-commodore64/license.txt deleted file mode 100644 index 5826ede..0000000 --- a/app/qml/fonts/1982-commodore64/license.txt +++ /dev/null @@ -1,8 +0,0 @@ - -Fonts in this package are (c) 2010-2014 Style. - -This license is applicable to each font file included in this package in all their variants (ttf, eot, woff, woff2, svg). - -You MAY NOT: sell this font; include/redistribute the font in any font collection regardless of pricing; provide the font for direct download from any web site, modify or rename the font. You MAY: link to "http://style64.org/c64-truetype" in order for others to download and install the font; embed the font (without any modification or file renaming) for display on any web site using @font-face rules; use this font in static images and vector art; include this font (without any modification or file renaming) as part of a software package but ONLY if said software package is freely provided to end users. You may also contact us to negotiate a (possibly commercial) license for your use outside of these guidelines at "http://style64.org/contact-style". - -At all times the most recent version of this license can be found at "http://style64.org/c64-truetype/license". diff --git a/app/qml/fonts/1977-apple2/FreeLicense.txt b/app/qml/fonts/apple2/FreeLicense.txt similarity index 100% rename from app/qml/fonts/1977-apple2/FreeLicense.txt rename to app/qml/fonts/apple2/FreeLicense.txt diff --git a/app/qml/fonts/1977-apple2/PRNumber3.ttf b/app/qml/fonts/apple2/PRNumber3.ttf similarity index 73% rename from app/qml/fonts/1977-apple2/PRNumber3.ttf rename to app/qml/fonts/apple2/PRNumber3.ttf index d4ff1a1..4843041 100644 Binary files a/app/qml/fonts/1977-apple2/PRNumber3.ttf and b/app/qml/fonts/apple2/PRNumber3.ttf differ diff --git a/app/qml/fonts/1977-apple2/PrintChar21.ttf b/app/qml/fonts/apple2/PrintChar21.ttf similarity index 73% rename from app/qml/fonts/1977-apple2/PrintChar21.ttf rename to app/qml/fonts/apple2/PrintChar21.ttf index 91f8438..7204e97 100644 Binary files a/app/qml/fonts/1977-apple2/PrintChar21.ttf and b/app/qml/fonts/apple2/PrintChar21.ttf differ diff --git a/app/qml/fonts/1979-atari-400-800/AtariClassic-Regular.ttf b/app/qml/fonts/atari-400-800/AtariClassic-Regular.ttf similarity index 100% rename from app/qml/fonts/1979-atari-400-800/AtariClassic-Regular.ttf rename to app/qml/fonts/atari-400-800/AtariClassic-Regular.ttf diff --git a/app/qml/fonts/1979-atari-400-800/Read Me.pdf b/app/qml/fonts/atari-400-800/Read Me.pdf similarity index 100% rename from app/qml/fonts/1979-atari-400-800/Read Me.pdf rename to app/qml/fonts/atari-400-800/Read Me.pdf diff --git a/app/qml/fonts/bigblue-terminal/BigBlueTerm437NerdFontMono-Regular.ttf b/app/qml/fonts/bigblue-terminal/BigBlueTerm437NerdFontMono-Regular.ttf new file mode 100644 index 0000000..407cace Binary files /dev/null and b/app/qml/fonts/bigblue-terminal/BigBlueTerm437NerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/1981-ibm-pc/LICENSE.TXT b/app/qml/fonts/bigblue-terminal/LICENSE.TXT similarity index 100% rename from app/qml/fonts/1981-ibm-pc/LICENSE.TXT rename to app/qml/fonts/bigblue-terminal/LICENSE.TXT diff --git a/app/qml/fonts/cozette/CozetteVector.ttf b/app/qml/fonts/cozette/CozetteVector.ttf new file mode 100644 index 0000000..ff273b7 Binary files /dev/null and b/app/qml/fonts/cozette/CozetteVector.ttf differ diff --git a/app/qml/fonts/departure-mono/DepartureMonoNerdFontMono-Regular.otf b/app/qml/fonts/departure-mono/DepartureMonoNerdFontMono-Regular.otf new file mode 100644 index 0000000..f9dc2e8 Binary files /dev/null and b/app/qml/fonts/departure-mono/DepartureMonoNerdFontMono-Regular.otf differ diff --git a/app/qml/fonts/departure-mono/LICENSE b/app/qml/fonts/departure-mono/LICENSE new file mode 100644 index 0000000..de52476 --- /dev/null +++ b/app/qml/fonts/departure-mono/LICENSE @@ -0,0 +1,93 @@ +Copyright 2022–2024 Helena Zhang (helenazhang.com). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/qml/fonts/fira-code/FiraCodeNerdFontMono-Regular.ttf b/app/qml/fonts/fira-code/FiraCodeNerdFontMono-Regular.ttf new file mode 100644 index 0000000..328e61d Binary files /dev/null and b/app/qml/fonts/fira-code/FiraCodeNerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/modern-hermit/LICENSE b/app/qml/fonts/fira-code/LICENSE.txt old mode 100755 new mode 100644 similarity index 95% rename from app/qml/fonts/modern-hermit/LICENSE rename to app/qml/fonts/fira-code/LICENSE.txt index 6dde5dd..805e0b3 --- a/app/qml/fonts/modern-hermit/LICENSE +++ b/app/qml/fonts/fira-code/LICENSE.txt @@ -1,94 +1,93 @@ -Copyright (c) 2013, Pablo Caro <me AT pcaro DOT es> - http://pcaro.es/ -with Reserved Font Name Hermit. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. +Copyright (c) 2014, The Fira Code Project Authors (https://github.com/tonsky/FiraCode) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/qml/fonts/modern-fixedsys-excelsior/FSEX301-L2.ttf b/app/qml/fonts/fixedsys-excelsior/FSEX301-L2.ttf similarity index 100% rename from app/qml/fonts/modern-fixedsys-excelsior/FSEX301-L2.ttf rename to app/qml/fonts/fixedsys-excelsior/FSEX301-L2.ttf diff --git a/app/qml/fonts/gohu/GohuFont11NerdFontMono-Regular.ttf b/app/qml/fonts/gohu/GohuFont11NerdFontMono-Regular.ttf new file mode 100644 index 0000000..df88b09 Binary files /dev/null and b/app/qml/fonts/gohu/GohuFont11NerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/gohu/LICENSE b/app/qml/fonts/gohu/LICENSE new file mode 100644 index 0000000..b73a68c --- /dev/null +++ b/app/qml/fonts/gohu/LICENSE @@ -0,0 +1,13 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + 14 rue de Plaisance, 75014 Paris, France + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/app/qml/fonts/greybeard/Greybeard-12px.ttf b/app/qml/fonts/greybeard/Greybeard-12px.ttf new file mode 100644 index 0000000..d57ea63 Binary files /dev/null and b/app/qml/fonts/greybeard/Greybeard-12px.ttf differ diff --git a/app/qml/fonts/greybeard/Greybeard-16px.ttf b/app/qml/fonts/greybeard/Greybeard-16px.ttf new file mode 100644 index 0000000..9ff0988 Binary files /dev/null and b/app/qml/fonts/greybeard/Greybeard-16px.ttf differ diff --git a/app/qml/fonts/modern-pro-font-win-tweaked/LICENSE b/app/qml/fonts/greybeard/LICENSE similarity index 85% rename from app/qml/fonts/modern-pro-font-win-tweaked/LICENSE rename to app/qml/fonts/greybeard/LICENSE index dcc3f12..e1369b6 100644 --- a/app/qml/fonts/modern-pro-font-win-tweaked/LICENSE +++ b/app/qml/fonts/greybeard/LICENSE @@ -1,7 +1,7 @@ -ProFont MIT License -Copyright (c) 2014 Carl Osterwald, Stephen C. Gilardi, Andrew Welch +Copyright (c) 2012-2015 Uwe Waldmann +Modified work Copyright 2018 Andy Walker Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -10,13 +10,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/app/qml/fonts/hack/HackNerdFontMono-Regular.ttf b/app/qml/fonts/hack/HackNerdFontMono-Regular.ttf new file mode 100644 index 0000000..2dc643c Binary files /dev/null and b/app/qml/fonts/hack/HackNerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/hack/LICENSE.txt b/app/qml/fonts/hack/LICENSE.txt new file mode 100644 index 0000000..08927e5 --- /dev/null +++ b/app/qml/fonts/hack/LICENSE.txt @@ -0,0 +1,45 @@ +The work in the Hack project is Copyright 2018 Source Foundry Authors and licensed under the MIT License + +The work in the DejaVu project was committed to the public domain. + +Bitstream Vera Sans Mono Copyright 2003 Bitstream Inc. and licensed under the Bitstream Vera License with Reserved Font Names "Bitstream" and "Vera" + +### MIT License + +Copyright (c) 2018 Source Foundry Authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +### BITSTREAM VERA LICENSE + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: + +The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". + +This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. + +The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org. diff --git a/app/qml/fonts/ibm-3278/3270NerdFontMono-Regular.ttf b/app/qml/fonts/ibm-3278/3270NerdFontMono-Regular.ttf new file mode 100644 index 0000000..b3dd3eb Binary files /dev/null and b/app/qml/fonts/ibm-3278/3270NerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/1971-ibm-3278/LICENSE.txt b/app/qml/fonts/ibm-3278/LICENSE.txt similarity index 87% rename from app/qml/fonts/1971-ibm-3278/LICENSE.txt rename to app/qml/fonts/ibm-3278/LICENSE.txt index 3ca71cb..b8f248a 100644 --- a/app/qml/fonts/1971-ibm-3278/LICENSE.txt +++ b/app/qml/fonts/ibm-3278/LICENSE.txt @@ -1,4 +1,6 @@ -Copyright (c) 2011-2017, Ricardo Banffy. +Copyright 2022 The 3270font Authors (https://github.com/rbanffy/3270font) + +Copyright (c) 2011-2022, Ricardo Banffy. Copyright (c) 1993-2011, Paul Mattes. Copyright (c) 2004-2005, Don Russell. Copyright (c) 2004, Dick Altenbern. @@ -10,27 +12,27 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - - * Neither the name of Ricardo Banffy, Paul Mattes, Don Russell, - Dick Altenbern, Jeff Sparkes, GTRC nor the names of their contributors - may be used to endorse or promote products derived from this software + + * Neither the name of Ricardo Banffy, Paul Mattes, Don Russell, + Dick Altenbern, Jeff Sparkes, GTRC nor the names of their contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL RICARDO BANFFY, PAUL MATTES, DON RUSSELL, DICK ALTENBERN, JEFF -SPARKES OR GTRC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL RICARDO BANFFY, PAUL MATTES, DON RUSSELL, DICK ALTENBERN, JEFF +SPARKES OR GTRC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The Debian Logo glyph is based on the Debian Open Use Logo and is diff --git a/app/qml/fonts/1971-ibm-3278/README.md b/app/qml/fonts/ibm-3278/README.md similarity index 100% rename from app/qml/fonts/1971-ibm-3278/README.md rename to app/qml/fonts/ibm-3278/README.md diff --git a/app/qml/fonts/iosevka/IosevkaTermNerdFontMono-Regular.ttf b/app/qml/fonts/iosevka/IosevkaTermNerdFontMono-Regular.ttf new file mode 100644 index 0000000..b511955 Binary files /dev/null and b/app/qml/fonts/iosevka/IosevkaTermNerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/iosevka/LICENSE.txt b/app/qml/fonts/iosevka/LICENSE.txt new file mode 100644 index 0000000..b2a7b6a --- /dev/null +++ b/app/qml/fonts/iosevka/LICENSE.txt @@ -0,0 +1,110 @@ +Copyright (c) 2015-2023, Renzhi Li (aka. Belleve Invis, belleve@typeof.net) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +-------------------------- + + +SIL Open Font License v1.1 +==================================================== + + +Preamble +---------- + +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + + +Definitions +------------- + +`"Font Software"` refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +`"Reserved Font Name"` refers to any names specified as such after the +copyright statement(s). + +`"Original Version"` refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +`"Modified Version"` refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +`"Author"` refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + + +Permission & Conditions +------------------------ + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1. Neither the Font Software nor any of its individual components, + in Original or Modified Versions, may be sold by itself. + +2. Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + +3. No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the corresponding + Copyright Holder. This restriction only applies to the primary font name as + presented to the users. + +4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + +5. The Font Software, modified or unmodified, in part or in whole, + must be distributed entirely under this license, and must not be + distributed under any other license. The requirement for fonts to + remain under this license does not apply to any document created + using the Font Software. + + + +Termination +----------- + +This license becomes null and void if any of the above conditions are +not met. + + + DISCLAIMER + + THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/qml/fonts/jetbrains-mono/JetBrainsMonoNerdFontMono-Regular.ttf b/app/qml/fonts/jetbrains-mono/JetBrainsMonoNerdFontMono-Regular.ttf new file mode 100644 index 0000000..f693474 Binary files /dev/null and b/app/qml/fonts/jetbrains-mono/JetBrainsMonoNerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/jetbrains-mono/LICENSE.txt b/app/qml/fonts/jetbrains-mono/LICENSE.txt new file mode 100644 index 0000000..8bee414 --- /dev/null +++ b/app/qml/fonts/jetbrains-mono/LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/qml/fonts/modern-hermit/Hermit-bold.otf b/app/qml/fonts/modern-hermit/Hermit-bold.otf deleted file mode 100644 index 49c46b8..0000000 Binary files a/app/qml/fonts/modern-hermit/Hermit-bold.otf and /dev/null differ diff --git a/app/qml/fonts/modern-hermit/Hermit-light.otf b/app/qml/fonts/modern-hermit/Hermit-light.otf deleted file mode 100644 index 610a39a..0000000 Binary files a/app/qml/fonts/modern-hermit/Hermit-light.otf and /dev/null differ diff --git a/app/qml/fonts/modern-hermit/Hermit-medium.otf b/app/qml/fonts/modern-hermit/Hermit-medium.otf deleted file mode 100644 index 8b826cf..0000000 Binary files a/app/qml/fonts/modern-hermit/Hermit-medium.otf and /dev/null differ diff --git a/app/qml/fonts/modern-inconsolata/Inconsolata.otf b/app/qml/fonts/modern-inconsolata/Inconsolata.otf deleted file mode 100644 index 3488898..0000000 Binary files a/app/qml/fonts/modern-inconsolata/Inconsolata.otf and /dev/null differ diff --git a/app/qml/fonts/modern-pro-font-win-tweaked/._LICENSE b/app/qml/fonts/modern-pro-font-win-tweaked/._LICENSE deleted file mode 100644 index 89a7054..0000000 Binary files a/app/qml/fonts/modern-pro-font-win-tweaked/._LICENSE and /dev/null differ diff --git a/app/qml/fonts/modern-pro-font-win-tweaked/._readme.txt b/app/qml/fonts/modern-pro-font-win-tweaked/._readme.txt deleted file mode 100644 index 89a7054..0000000 Binary files a/app/qml/fonts/modern-pro-font-win-tweaked/._readme.txt and /dev/null differ diff --git a/app/qml/fonts/modern-pro-font-win-tweaked/Comments for ProFontWindows b/app/qml/fonts/modern-pro-font-win-tweaked/Comments for ProFontWindows deleted file mode 100644 index 66ce074..0000000 --- a/app/qml/fonts/modern-pro-font-win-tweaked/Comments for ProFontWindows +++ /dev/null @@ -1 +0,0 @@ -dopustz:-480 \ No newline at end of file diff --git a/app/qml/fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf b/app/qml/fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf deleted file mode 100644 index b3d66b2..0000000 Binary files a/app/qml/fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf and /dev/null differ diff --git a/app/qml/fonts/modern-pro-font-win-tweaked/readme.txt b/app/qml/fonts/modern-pro-font-win-tweaked/readme.txt deleted file mode 100644 index 76298e0..0000000 --- a/app/qml/fonts/modern-pro-font-win-tweaked/readme.txt +++ /dev/null @@ -1,31 +0,0 @@ -WHAT IS THIS? - -This is ProFont TrueType, converted to Windows TrueType format -by Mike Smith, with some tweaks added by "ardu". - -Modifications include: -- A Euro character -- Missing characters from the Latin 1 code page -- Full support for CodePage 850. These are mostly the famous - block/box characters you know from DOS. Very useful if you use - Mightnight Commander through PuTTY. -- Fixed metrics so that point size of 9 works correctly. Until now - you had to select 7 to obtain the native point size of 9. -- Added some quick&dirty hinting for point size of 9. Most characters - now match closely the look of the bitmap version. - Don't expect it to look good on anything else than Windows... - - - -To get the full original Distribution, other ProFont builds -and more information -go to <http://tobiasjung.name/profont/> - - -DISCLAIMER -See LICENSE file - - -Tobias Jung -January 2014 -profont@tobiasjung.name diff --git a/app/qml/fonts/modern-proggy-tiny/Licence.txt b/app/qml/fonts/modern-proggy-tiny/Licence.txt deleted file mode 100644 index d67eb33..0000000 --- a/app/qml/fonts/modern-proggy-tiny/Licence.txt +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2004, 2005 Tristan Grimmer - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/app/qml/fonts/modern-proggy-tiny/ProggyTiny.ttf b/app/qml/fonts/modern-proggy-tiny/ProggyTiny.ttf deleted file mode 100644 index 1c4312c..0000000 Binary files a/app/qml/fonts/modern-proggy-tiny/ProggyTiny.ttf and /dev/null differ diff --git a/app/qml/fonts/modern-terminus/TerminusTTF-4.46.0.ttf b/app/qml/fonts/modern-terminus/TerminusTTF-4.46.0.ttf deleted file mode 100644 index eafa3a6..0000000 Binary files a/app/qml/fonts/modern-terminus/TerminusTTF-4.46.0.ttf and /dev/null differ diff --git a/app/qml/fonts/1985-ibm-pc-vga/LICENSE.TXT b/app/qml/fonts/oldschool-pc-fonts/LICENSE.TXT similarity index 100% rename from app/qml/fonts/1985-ibm-pc-vga/LICENSE.TXT rename to app/qml/fonts/oldschool-pc-fonts/LICENSE.TXT diff --git a/app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_EGA_8x8.ttf b/app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_EGA_8x8.ttf new file mode 100644 index 0000000..18eb7d4 Binary files /dev/null and b/app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_EGA_8x8.ttf differ diff --git a/app/qml/fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf b/app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_VGA8.ttf similarity index 100% rename from app/qml/fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf rename to app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_VGA8.ttf diff --git a/app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_VGA_8x16.ttf b/app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_VGA_8x16.ttf new file mode 100644 index 0000000..3bf32d0 Binary files /dev/null and b/app/qml/fonts/oldschool-pc-fonts/PxPlus_IBM_VGA_8x16.ttf differ diff --git a/app/qml/fonts/opendyslexic/LICENSE.txt b/app/qml/fonts/opendyslexic/LICENSE.txt new file mode 100644 index 0000000..4803fb9 --- /dev/null +++ b/app/qml/fonts/opendyslexic/LICENSE.txt @@ -0,0 +1,22 @@ +License +------- +The license for this font is: + +♡ Copying is an act of love. Please copy. +Bitstream License: + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license (“Fonts”) and associated documentation files (the “Font Software”), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: + +The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words “Bitstream” or the word “Vera”. + +This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the “Bitstream Vera” names. + +The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org. diff --git a/app/qml/fonts/opendyslexic/OpenDyslexicMNerdFontMono-Regular.otf b/app/qml/fonts/opendyslexic/OpenDyslexicMNerdFontMono-Regular.otf new file mode 100644 index 0000000..d40c804 Binary files /dev/null and b/app/qml/fonts/opendyslexic/OpenDyslexicMNerdFontMono-Regular.otf differ diff --git a/app/qml/fonts/1977-commodore-pet/FreeLicense.txt b/app/qml/fonts/pet-me/FreeLicense.txt similarity index 100% rename from app/qml/fonts/1977-commodore-pet/FreeLicense.txt rename to app/qml/fonts/pet-me/FreeLicense.txt diff --git a/app/qml/fonts/1977-commodore-pet/PetMe.ttf b/app/qml/fonts/pet-me/PetMe.ttf similarity index 52% rename from app/qml/fonts/1977-commodore-pet/PetMe.ttf rename to app/qml/fonts/pet-me/PetMe.ttf index 0c8c74e..507063f 100644 Binary files a/app/qml/fonts/1977-commodore-pet/PetMe.ttf and b/app/qml/fonts/pet-me/PetMe.ttf differ diff --git a/app/qml/fonts/pet-me/PetMe64.ttf b/app/qml/fonts/pet-me/PetMe64.ttf new file mode 100644 index 0000000..c4bd2c3 Binary files /dev/null and b/app/qml/fonts/pet-me/PetMe64.ttf differ diff --git a/app/qml/fonts/source-code-pro/LICENSE.txt b/app/qml/fonts/source-code-pro/LICENSE.txt new file mode 100644 index 0000000..db2a8ba --- /dev/null +++ b/app/qml/fonts/source-code-pro/LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010-2020 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/app/qml/fonts/source-code-pro/SauceCodeProNerdFontMono-Regular.ttf b/app/qml/fonts/source-code-pro/SauceCodeProNerdFontMono-Regular.ttf new file mode 100644 index 0000000..79368e7 Binary files /dev/null and b/app/qml/fonts/source-code-pro/SauceCodeProNerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/modern-terminus/COPYING b/app/qml/fonts/terminus/LICENSE-Terminess.txt similarity index 96% rename from app/qml/fonts/modern-terminus/COPYING rename to app/qml/fonts/terminus/LICENSE-Terminess.txt index c964194..8cd25e3 100644 --- a/app/qml/fonts/modern-terminus/COPYING +++ b/app/qml/fonts/terminus/LICENSE-Terminess.txt @@ -1,7 +1,7 @@ Copyright (c) 2010 Dimitar Toshkov Zhekov, with Reserved Font Name "Terminus Font". -Copyright (c) 2011 Tilman Blumenbach, +Copyright (c) 2011-2021 Tilman Blumenbach, with Reserved Font Name "Terminus (TTF)". This Font Software is licensed under the SIL Open Font License, Version 1.1. diff --git a/app/qml/fonts/terminus/TerminessNerdFontMono-Regular.ttf b/app/qml/fonts/terminus/TerminessNerdFontMono-Regular.ttf new file mode 100644 index 0000000..5337b7f Binary files /dev/null and b/app/qml/fonts/terminus/TerminessNerdFontMono-Regular.ttf differ diff --git a/app/qml/fonts/unscii/LICENSE b/app/qml/fonts/unscii/LICENSE new file mode 100644 index 0000000..6b819fc --- /dev/null +++ b/app/qml/fonts/unscii/LICENSE @@ -0,0 +1 @@ +You can consider it Public Domain (or CC-0) except for the files derived from or containing parts of Roman Czyborra's Unifont project (unifont.hex, hex2bdf.pl, unscii-16-full.*) which fall under GPL. See https://savannah.gnu.org/projects/unifont/ for more. diff --git a/app/qml/fonts/unscii/unscii-16-full.ttf b/app/qml/fonts/unscii/unscii-16-full.ttf new file mode 100644 index 0000000..0a3a84e Binary files /dev/null and b/app/qml/fonts/unscii/unscii-16-full.ttf differ diff --git a/app/qml/fonts/unscii/unscii-8-thin.ttf b/app/qml/fonts/unscii/unscii-8-thin.ttf new file mode 100644 index 0000000..48c1f29 Binary files /dev/null and b/app/qml/fonts/unscii/unscii-8-thin.ttf differ diff --git a/app/qml/fonts/unscii/unscii-8.ttf b/app/qml/fonts/unscii/unscii-8.ttf new file mode 100644 index 0000000..9b5532a Binary files /dev/null and b/app/qml/fonts/unscii/unscii-8.ttf differ diff --git a/app/qml/main.qml b/app/qml/main.qml index 8ae0774..dc4f426 100644 --- a/app/qml/main.qml +++ b/app/qml/main.qml @@ -18,118 +18,92 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ import QtQuick 2.2 -import QtQuick.Window 2.1 import QtQuick.Controls 2.3 import "menus" -ApplicationWindow { - id: terminalWindow +QtObject { + id: appRoot - width: 1024 - height: 768 - - // Save window properties automatically - onXChanged: appSettings.x = x - onYChanged: appSettings.y = y - onWidthChanged: appSettings.width = width - onHeightChanged: appSettings.height = height - - // Load saved window geometry and show the window - Component.onCompleted: { - x = appSettings.x - y = appSettings.y - width = appSettings.width - height = appSettings.height - - visible = true + property ApplicationSettings appSettings: ApplicationSettings { + onInitializedSettings: appRoot.createWindow() } - minimumWidth: 320 - minimumHeight: 240 - - visible: false - - property bool fullscreen: appSettings.fullscreen - onFullscreenChanged: visibility = (fullscreen ? Window.FullScreen : Window.Windowed) - - menuBar: qtquickMenuLoader.item - - Loader { - id: qtquickMenuLoader - active: !appSettings.isMacOS && appSettings.showMenubar - sourceComponent: WindowMenu { } + property TimeManager timeManager: TimeManager { + enableTimer: windowsModel.count > 0 } - Loader { - id: globalMenuLoader + property SettingsWindow settingsWindow: SettingsWindow { + visible: false + } + + property AboutDialog aboutDialog: AboutDialog { + visible: false + } + + property Component windowComponent: Component { + TerminalWindow { } + } + + property ListModel windowsModel: ListModel { } + + property Loader globalMenuLoader: Loader { active: appSettings.isMacOS sourceComponent: OSXMenu { } } - property string wintitle: appSettings.wintitle - - color: "#00000000" - - title: terminalContainer.title || qsTr(appSettings.wintitle) - - Action { - id: showMenubarAction - text: qsTr("Show Menubar") - enabled: !appSettings.isMacOS - shortcut: "Ctrl+Shift+M" - checkable: true - checked: appSettings.showMenubar - onTriggered: appSettings.showMenubar = !appSettings.showMenubar - } - Action { - id: fullscreenAction + property Action fullscreenAction: Action { text: qsTr("Fullscreen") enabled: !appSettings.isMacOS shortcut: "Alt+F11" - onTriggered: appSettings.fullscreen = !appSettings.fullscreen - checkable: true - checked: appSettings.fullscreen } - Action { - id: quitAction + + property bool initialFullscreenRequested: Qt.application.arguments.indexOf("--fullscreen") !== -1 + + property Action newWindowAction: Action { + text: qsTr("New Window") + shortcut: "Ctrl+Shift+N" + onTriggered: appRoot.createWindow() + } + + property Action quitAction: Action { text: qsTr("Quit") shortcut: "Ctrl+Shift+Q" - onTriggered: Qt.quit() + onTriggered: appSettings.close() } - Action { - id: showsettingsAction + + property Action showsettingsAction: Action { text: qsTr("Settings") onTriggered: { - settingswindow.show() - settingswindow.requestActivate() - settingswindow.raise() + settingsWindow.show() + settingsWindow.requestActivate() + settingsWindow.raise() } } - Action { - id: copyAction + + property Action copyAction: Action { text: qsTr("Copy") shortcut: "Ctrl+Shift+C" } - Action { - id: pasteAction + + property Action pasteAction: Action { text: qsTr("Paste") shortcut: "Ctrl+Shift+V" } - Action { - id: zoomIn + + property Action zoomInAction: Action { text: qsTr("Zoom In") shortcut: "Ctrl++" onTriggered: appSettings.incrementScaling() } - Action { - id: zoomOut + + property Action zoomOutAction: Action { text: qsTr("Zoom Out") shortcut: "Ctrl+-" onTriggered: appSettings.decrementScaling() } - Action { - id: showAboutAction + + property Action showAboutAction: Action { text: qsTr("About") onTriggered: { aboutDialog.show() @@ -137,34 +111,35 @@ ApplicationWindow { aboutDialog.raise() } } - ApplicationSettings { - id: appSettings + + property Action newTabAction: Action { + text: qsTr("New Tab") } - TerminalContainer { - id: terminalContainer - width: parent.width - height: (parent.height + Math.abs(y)) + + function createWindow() { + var useFullscreen = initialFullscreenRequested + var window = windowComponent.createObject(null, { fullscreen: useFullscreen }) + if (!window) + return + + windowsModel.append({ window: window }) + initialFullscreenRequested = false + window.show() + window.requestActivate() } - SettingsWindow { - id: settingswindow - visible: false - } - AboutDialog { - id: aboutDialog - visible: false - } - Loader { - anchors.centerIn: parent - active: appSettings.showTerminalSize - sourceComponent: SizeOverlay { - z: 3 - terminalSize: terminalContainer.terminalSize + + function closeWindow(window) { + for (var i = 0; i < windowsModel.count; i++) { + if (windowsModel.get(i).window === window) { + windowsModel.remove(i) + break + } + } + + window.destroy() + + if (windowsModel.count === 0) { + appSettings.close() } } - onClosing: { - // OSX Since we are currently supporting only one window - // quit the application when it is closed. - if (appSettings.isMacOS) - Qt.quit() - } } diff --git a/app/qml/menus/FullContextMenu.qml b/app/qml/menus/FullContextMenu.qml index d9feb58..2d7c70f 100644 --- a/app/qml/menus/FullContextMenu.qml +++ b/app/qml/menus/FullContextMenu.qml @@ -32,10 +32,15 @@ Menu { action: showsettingsAction } - MenuSeparator {} - Menu { title: qsTr("File") + MenuItem { + action: newWindowAction + } + MenuItem { + action: newTabAction + } + MenuSeparator {} MenuItem { action: quitAction } @@ -60,14 +65,10 @@ Menu { visible: fullscreenAction.enabled } MenuItem { - action: showMenubarAction - visible: showMenubarAction.enabled + action: zoomInAction } MenuItem { - action: zoomIn - } - MenuItem { - action: zoomOut + action: zoomOutAction } } Menu { @@ -79,11 +80,10 @@ Menu { text: model.text onTriggered: { appSettings.loadProfileString(obj_string) - appSettings.handleFontChanged() } } - onObjectAdded: profilesMenu.insertItem(index, object) - onObjectRemoved: profilesMenu.removeItem(object) + onObjectAdded: function(index, object) { profilesMenu.insertItem(index, object) } + onObjectRemoved: function(object) { profilesMenu.removeItem(object) } } } Menu { diff --git a/app/qml/menus/OSXMenu.qml b/app/qml/menus/OSXMenu.qml index 3fe9971..7f0926a 100644 --- a/app/qml/menus/OSXMenu.qml +++ b/app/qml/menus/OSXMenu.qml @@ -26,6 +26,17 @@ MenuBar { Menu { title: qsTr("File") + MenuItem { + text: newWindowAction.text + shortcut: newWindowAction.shortcut + onTriggered: newWindowAction.trigger() + } + MenuItem { + text: newTabAction.text + shortcut: newTabAction.shortcut + onTriggered: newTabAction.trigger() + } + MenuSeparator {} MenuItem { text: quitAction.text onTriggered: quitAction.trigger() @@ -53,14 +64,14 @@ MenuBar { Menu { title: qsTr("View") MenuItem { - text: zoomIn.text + text: zoomInAction.text shortcut: "Meta++" - onTriggered: zoomIn.trigger() + onTriggered: zoomInAction.trigger() } MenuItem { - text: zoomOut.text + text: zoomOutAction.text shortcut: "Meta+-" - onTriggered: zoomOut.trigger() + onTriggered: zoomOutAction.trigger() } } Menu { @@ -72,11 +83,10 @@ MenuBar { text: model.text onTriggered: { appSettings.loadProfileString(obj_string) - appSettings.handleFontChanged() } } - onObjectAdded: profilesMenu.insertItem(index, object) - onObjectRemoved: profilesMenu.removeItem(object) + onObjectAdded: function(index, object) { profilesMenu.insertItem(index, object) } + onObjectRemoved: function(object) { profilesMenu.removeItem(object) } } } Menu { diff --git a/app/qml/menus/WindowMenu.qml b/app/qml/menus/WindowMenu.qml index 937153b..6d3f1f7 100644 --- a/app/qml/menus/WindowMenu.qml +++ b/app/qml/menus/WindowMenu.qml @@ -26,6 +26,13 @@ MenuBar { Menu { title: qsTr("File") + MenuItem { + action: newWindowAction + } + MenuItem { + action: newTabAction + } + MenuSeparator {} MenuItem { action: quitAction } @@ -50,14 +57,10 @@ MenuBar { visible: fullscreenAction.enabled } MenuItem { - action: showMenubarAction - visible: showMenubarAction.enabled + action: zoomInAction } MenuItem { - action: zoomIn - } - MenuItem { - action: zoomOut + action: zoomOutAction } } Menu { @@ -69,11 +72,10 @@ MenuBar { text: model.text onTriggered: { appSettings.loadProfileString(obj_string) - appSettings.handleFontChanged() } } - onObjectAdded: profilesMenu.insertItem(index, object) - onObjectRemoved: profilesMenu.removeItem(object) + onObjectAdded: function(index, object) { profilesMenu.insertItem(index, object) } + onObjectRemoved: function(object) { profilesMenu.removeItem(object) } } } Menu { diff --git a/app/qml/resources.qrc b/app/qml/resources.qrc index 1114d8d..961600e 100644 --- a/app/qml/resources.qrc +++ b/app/qml/resources.qrc @@ -5,8 +5,7 @@ <file>CheckableSlider.qml</file> <file>ApplicationSettings.qml</file> <file>SettingsWindow.qml</file> - <file>Fonts.qml</file> - <file>FontPixels.qml</file> + <file>TerminalWindow.qml</file> <file>SettingsGeneralTab.qml</file> <file>PreprocessedTerminal.qml</file> <file>TimeManager.qml</file> @@ -17,34 +16,106 @@ <file>SettingsEffectsTab.qml</file> <file>main.qml</file> <file>SettingsTerminalTab.qml</file> - <file>FontScanlines.qml</file> - <file>fonts/1977-apple2/PrintChar21.ttf</file> - <file>fonts/1971-ibm-3278/3270-Regular.ttf</file> + <file>fonts/apple2/PrintChar21.ttf</file> + <file>fonts/ibm-3278/3270NerdFontMono-Regular.ttf</file> <file>Storage.qml</file> <file>SettingsAdvancedTab.qml</file> <file>TerminalContainer.qml</file> + <file>TerminalTabs.qml</file> <file>images/crt256.png</file> <file>utils.js</file> <file>images/allNoise512.png</file> - <file>fonts/modern-proggy-tiny/ProggyTiny.ttf</file> - <file>fonts/modern-pro-font-win-tweaked/ProFontWindows.ttf</file> - <file>fonts/modern-hermit/Hermit-medium.otf</file> - <file>fonts/modern-inconsolata/Inconsolata.otf</file> - <file>fonts/modern-fixedsys-excelsior/FSEX301-L2.ttf</file> + <file>fonts/fixedsys-excelsior/FSEX301-L2.ttf</file> + <file>fonts/cozette/CozetteVector.ttf</file> + <file>fonts/greybeard/Greybeard-16px.ttf</file> + <file>fonts/gohu/GohuFont11NerdFontMono-Regular.ttf</file> + <file>fonts/hack/HackNerdFontMono-Regular.ttf</file> + <file>fonts/fira-code/FiraCodeNerdFontMono-Regular.ttf</file> + <file>fonts/bigblue-terminal/BigBlueTerm437NerdFontMono-Regular.ttf</file> + <file>fonts/iosevka/IosevkaTermNerdFontMono-Regular.ttf</file> + <file>fonts/jetbrains-mono/JetBrainsMonoNerdFontMono-Regular.ttf</file> <file>../icons/32x32/cool-retro-term.png</file> <file>Components/SizedLabel.qml</file> - <file>fonts/1979-atari-400-800/AtariClassic-Regular.ttf</file> - <file>fonts/1982-commodore64/C64_Pro_Mono-STYLE.ttf</file> - <file>fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf</file> - <file>fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf</file> - <file>fonts/1977-commodore-pet/PetMe.ttf</file> + <file>fonts/atari-400-800/AtariClassic-Regular.ttf</file> + <file>fonts/pet-me/PetMe64.ttf</file> + <file>fonts/pet-me/PetMe.ttf</file> <file>BurnInEffect.qml</file> - <file>fonts/modern-terminus/TerminusTTF-4.46.0.ttf</file> + <file>fonts/terminus/TerminessNerdFontMono-Regular.ttf</file> + <file>fonts/departure-mono/DepartureMonoNerdFontMono-Regular.otf</file> + <file>fonts/opendyslexic/OpenDyslexicMNerdFontMono-Regular.otf</file> + <file>fonts/source-code-pro/SauceCodeProNerdFontMono-Regular.ttf</file> <file>TerminalFrame.qml</file> <file>menus/WindowMenu.qml</file> <file>menus/FullContextMenu.qml</file> <file>menus/ShortContextMenu.qml</file> - <file>ShaderLibrary.qml</file> <file>menus/OSXMenu.qml</file> + <file>../shaders/terminal_dynamic.vert.qsb</file> + <file>../shaders/terminal_static.vert.qsb</file> + <file>../shaders/terminal_frame.vert.qsb</file> + <file>../shaders/burn_in.vert.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn0_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn0_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn0_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn0_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn1_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn1_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn1_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster0_burn1_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn0_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn0_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn0_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn0_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn1_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn1_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn1_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster1_burn1_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn0_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn0_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn0_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn0_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn1_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn1_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn1_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster2_burn1_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn0_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn0_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn0_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn0_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn1_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn1_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn1_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster3_burn1_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn0_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn0_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn0_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn0_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn1_frame0_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn1_frame0_chroma1.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn1_frame1_chroma0.frag.qsb</file> + <file>../shaders/terminal_dynamic_raster4_burn1_frame1_chroma1.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom0_curve0_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom0_curve0_shine1.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom0_curve1_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom0_curve1_shine1.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom1_curve0_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom1_curve0_shine1.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom1_curve1_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb0_bloom1_curve1_shine1.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom0_curve0_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom0_curve0_shine1.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom0_curve1_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom0_curve1_shine1.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom1_curve0_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom1_curve0_shine1.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom1_curve1_shine0.frag.qsb</file> + <file>../shaders/terminal_static_rgb1_bloom1_curve1_shine1.frag.qsb</file> + <file>../shaders/terminal_frame.frag.qsb</file> + <file>../shaders/burn_in.frag.qsb</file> + <file>fonts/unscii/unscii-8-thin.ttf</file> + <file>fonts/unscii/unscii-16-full.ttf</file> + <file>fonts/unscii/unscii-8.ttf</file> + <file>fonts/oldschool-pc-fonts/PxPlus_IBM_EGA_8x8.ttf</file> + <file>fonts/oldschool-pc-fonts/PxPlus_IBM_VGA8.ttf</file> + <file>fonts/oldschool-pc-fonts/PxPlus_IBM_VGA_8x16.ttf</file> </qresource> </RCC> diff --git a/app/qml/utils.js b/app/qml/utils.js index 3cb5a67..83c1877 100644 --- a/app/qml/utils.js +++ b/app/qml/utils.js @@ -32,10 +32,29 @@ function lint(a, b, t) { } function mix(c1, c2, alpha) { - return Qt.rgba(c1.r * alpha + c2.r * (1-alpha), - c1.g * alpha + c2.g * (1-alpha), - c1.b * alpha + c2.b * (1-alpha), - c1.a * alpha + c2.a * (1-alpha)) + return Qt.rgba(c1.r * (1 - alpha) + c2.r * alpha, + c1.g * (1 - alpha) + c2.g * alpha, + c1.b * (1 - alpha) + c2.b * alpha, + c1.a * (1 - alpha) + c2.a * alpha) +} + +function sum(c1, c2) { + let result = Qt.rgba( + clamp(c1.r + c2.r, 0, 1), + clamp(c1.g + c2.g, 0, 1), + clamp(c1.b + c2.b, 0, 1), + clamp(c1.a + c2.a, 0, 1) + ); + return result +} + +function scaleColor(c1, value) { + return Qt.rgba( + clamp(c1.r * value, 0, 1), + clamp(c1.g * value, 0, 1), + clamp(c1.b * value, 0, 1), + clamp(c1.a, 0, 1) + ); } function smoothstep(min, max, value) { diff --git a/app/shaders/burn_in.frag b/app/shaders/burn_in.frag new file mode 100644 index 0000000..dd23473 --- /dev/null +++ b/app/shaders/burn_in.frag @@ -0,0 +1,36 @@ +#version 440 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float burnInLastUpdate; + float burnInTime; + float prevLastUpdate; +}; + +layout(binding = 1) uniform sampler2D txt_source; +layout(binding = 2) uniform sampler2D burnInSource; + +float rgb2grey(vec3 v) { + return dot(v, vec3(0.21, 0.72, 0.04)); +} + +void main() { + vec2 coords = qt_TexCoord0; + + vec3 txtColor = texture(txt_source, coords).rgb; + vec4 accColor = texture(burnInSource, coords); + + float prevMask = accColor.a; + + float blurDecay = clamp((burnInLastUpdate - prevLastUpdate) * burnInTime, 0.0, 1.0); + blurDecay = max(0.0, blurDecay - prevMask); + vec3 color = max(accColor.rgb - vec3(blurDecay), txtColor); + + float currMask = step(rgb2grey(color), rgb2grey(txtColor)); + + fragColor = vec4(color, currMask) * qt_Opacity; +} diff --git a/app/shaders/burn_in.frag.qsb b/app/shaders/burn_in.frag.qsb new file mode 100644 index 0000000..368c7d2 Binary files /dev/null and b/app/shaders/burn_in.frag.qsb differ diff --git a/app/shaders/burn_in.vert b/app/shaders/burn_in.vert new file mode 100644 index 0000000..8e478c9 --- /dev/null +++ b/app/shaders/burn_in.vert @@ -0,0 +1,19 @@ +#version 440 + +layout(location = 0) in vec4 qt_Vertex; +layout(location = 1) in vec2 qt_MultiTexCoord0; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float burnInLastUpdate; + float burnInTime; + float prevLastUpdate; +}; + +layout(location = 0) out vec2 qt_TexCoord0; + +void main() { + qt_TexCoord0 = qt_MultiTexCoord0; + gl_Position = qt_Matrix * qt_Vertex; +} diff --git a/app/shaders/burn_in.vert.qsb b/app/shaders/burn_in.vert.qsb new file mode 100644 index 0000000..539661c Binary files /dev/null and b/app/shaders/burn_in.vert.qsb differ diff --git a/app/shaders/passthrough.vert b/app/shaders/passthrough.vert new file mode 100644 index 0000000..5ad4dea --- /dev/null +++ b/app/shaders/passthrough.vert @@ -0,0 +1,45 @@ +#version 440 + +layout(location = 0) in vec4 qt_Vertex; +layout(location = 1) in vec2 qt_MultiTexCoord0; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float time; + vec4 fontColor; + vec4 backgroundColor; + float shadowLength; + vec2 virtualResolution; + float rasterizationIntensity; + int rasterizationMode; + float burnInLastUpdate; + float burnInTime; + float burnIn; + float staticNoise; + float screenCurvature; + float glowingLine; + float chromaColor; + vec2 jitterDisplacement; + float ambientLight; + float jitter; + float horizontalSync; + float horizontalSyncStrength; + float flickering; + vec2 scaleNoiseSize; + float screen_brightness; + float bloom; + float rgbShift; + float frameShadowCoeff; + float frameShininess; + vec4 frameColor; + float frameSize; + float prevLastUpdate; +}; + +layout(location = 0) out vec2 qt_TexCoord0; + +void main() { + qt_TexCoord0 = qt_MultiTexCoord0; + gl_Position = qt_Matrix * qt_Vertex; +} diff --git a/app/shaders/passthrough.vert.qsb b/app/shaders/passthrough.vert.qsb new file mode 100644 index 0000000..20a79f3 Binary files /dev/null and b/app/shaders/passthrough.vert.qsb differ diff --git a/app/shaders/terminal_dynamic.frag b/app/shaders/terminal_dynamic.frag new file mode 100644 index 0000000..ea48c74 --- /dev/null +++ b/app/shaders/terminal_dynamic.frag @@ -0,0 +1,180 @@ +#version 440 + +#ifndef CRT_RASTER_MODE +#define CRT_RASTER_MODE 0 +#endif +#ifndef CRT_BURN_IN +#define CRT_BURN_IN 1 +#endif +#ifndef CRT_DISPLAY_FRAME +#define CRT_DISPLAY_FRAME 1 +#endif +#ifndef CRT_CHROMA +#define CRT_CHROMA 1 +#endif + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 1) in float vBrightness; +layout(location = 2) in float vDistortionScale; +layout(location = 3) in float vDistortionFreq; + +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float time; + vec4 fontColor; + vec4 backgroundColor; + vec2 virtualResolution; + float rasterizationIntensity; + float burnInLastUpdate; + float burnInTime; + float burnIn; + float staticNoise; + float screenCurvature; + float glowingLine; + float chromaColor; + vec2 jitterDisplacement; + float jitter; + float horizontalSync; + float horizontalSyncStrength; + float flickering; + vec2 scaleNoiseSize; + float frameShininess; + float frameSize; + float bloom; +}; + +layout(binding = 0) uniform sampler2D noiseSource; +layout(binding = 1) uniform sampler2D screenBuffer; +layout(binding = 2) uniform sampler2D burnInSource; +layout(binding = 3) uniform sampler2D frameSource; + +float min2(vec2 v) { return min(v.x, v.y); } +float prod2(vec2 v) { return v.x * v.y; } +float sum2(vec2 v) { return v.x + v.y; } +float rgb2grey(vec3 v) { return dot(v, vec3(0.21, 0.72, 0.04)); } + +vec2 distortCoordinates(vec2 coords){ + vec2 paddedCoords = coords * (vec2(1.0) + frameSize * 2.0) - frameSize; + vec2 cc = (paddedCoords - vec2(0.5)); + float dist = dot(cc, cc) * screenCurvature; + return (paddedCoords + cc * (1.0 + dist) * dist); +} + +vec3 applyRasterization(vec2 screenCoords, vec3 texel, vec2 virtualRes, float intensity) { +#if CRT_RASTER_MODE == 0 || CRT_RASTER_MODE == 4 + return texel; +#else + if (intensity <= 0.0) { + return texel; + } + + const float INTENSITY = 0.30; + const float BRIGHTBOOST = 0.30; + +#if CRT_RASTER_MODE == 1 + vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel; + vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel; + + vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0); + float mask = 1.0 - abs(coords.y); + + vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); + return mix(texel, rasterizationColor, intensity); +#elif CRT_RASTER_MODE == 2 + vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel; + vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel; + + vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0); + coords = coords * coords; + float mask = 1.0 - coords.x - coords.y; + + vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); + return mix(texel, rasterizationColor, intensity); +#elif CRT_RASTER_MODE == 3 + const float SUBPIXELS = 3.0; + vec3 offsets = vec3(3.141592654) * vec3(0.5, 0.5 - 2.0 / 3.0, 0.5 - 4.0 / 3.0); + + vec2 omega = vec2(3.141592654) * vec2(2.0) * virtualRes; + vec2 angle = screenCoords * omega; + vec3 xfactors = (SUBPIXELS + sin(angle.x + offsets)) / (SUBPIXELS + 1.0); + + vec3 result = texel * xfactors; + vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * result)) * result; + vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * result)) * result; + + vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0); + float mask = 1.0 - abs(coords.y); + + vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask); + return mix(texel, rasterizationColor, intensity); +#else + return texel; +#endif +#endif +} + +float randomPass(vec2 coords){ + return fract(smoothstep(-120.0, 0.0, coords.y - (virtualResolution.y + 120.0) * fract(time * 0.15))); +} + +vec3 convertWithChroma(vec3 inColor) { +#if CRT_CHROMA == 1 + float grey = rgb2grey(inColor); + float denom = max(grey, 0.0001); + vec3 foregroundColor = mix(fontColor.rgb, inColor * fontColor.rgb / denom, chromaColor); + return mix(backgroundColor.rgb, foregroundColor, grey); +#else + return mix(backgroundColor.rgb, fontColor.rgb, rgb2grey(inColor)); +#endif +} + +void main() { + vec2 cc = vec2(0.5) - qt_TexCoord0; + float distance = length(cc); + + vec2 staticCoords = distortCoordinates(qt_TexCoord0); + vec2 coords = qt_TexCoord0; + + float dst = sin((coords.y + time) * vDistortionFreq); + coords.x += dst * vDistortionScale; + + vec4 noiseTexel = texture(noiseSource, scaleNoiseSize * coords + vec2(fract(time / 0.051), fract(time / 0.237))); + + vec2 txt_coords = coords + (noiseTexel.ba - vec2(0.5)) * jitterDisplacement * jitter; + + float color = 0.0001; + color += noiseTexel.a * staticNoise * (1.0 - distance * 1.3); + color += randomPass(coords * virtualResolution) * glowingLine; + +#if CRT_DISPLAY_FRAME == 1 + vec4 frameColor = texture(frameSource, qt_TexCoord0); + color *= (1.0 - frameColor.a); +#endif + + vec3 txt_color = texture(screenBuffer, txt_coords).rgb; + float bloomScale = 1.0 + max(bloom, 0.0); + txt_color *= bloomScale; + +#if CRT_BURN_IN == 1 + vec4 txt_blur = texture(burnInSource, staticCoords); + float blurDecay = clamp((time - burnInLastUpdate) * burnInTime, 0.0, 1.0); + vec3 burnInColor = 0.65 * (txt_blur.rgb - vec3(blurDecay)) * (1.0 - txt_blur.a); + txt_color = max(txt_color, burnInColor); +#endif + + txt_color += vec3(color); + txt_color = applyRasterization(staticCoords, txt_color, virtualResolution, rasterizationIntensity); + + vec3 finalColor = convertWithChroma(txt_color); + float brightness = mix(1.0, vBrightness, step(0.0, flickering)); + finalColor *= brightness; + +#if CRT_DISPLAY_FRAME == 1 + finalColor = mix(finalColor, frameColor.rgb, frameColor.a); +#endif + + fragColor = vec4(finalColor, qt_Opacity); +} diff --git a/app/shaders/terminal_dynamic.vert b/app/shaders/terminal_dynamic.vert new file mode 100644 index 0000000..c81be91 --- /dev/null +++ b/app/shaders/terminal_dynamic.vert @@ -0,0 +1,52 @@ +#version 440 + +layout(location = 0) in vec4 qt_Vertex; +layout(location = 1) in vec2 qt_MultiTexCoord0; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float time; + vec4 fontColor; + vec4 backgroundColor; + vec2 virtualResolution; + float rasterizationIntensity; + float burnInLastUpdate; + float burnInTime; + float burnIn; + float staticNoise; + float screenCurvature; + float glowingLine; + float chromaColor; + vec2 jitterDisplacement; + float jitter; + float horizontalSync; + float horizontalSyncStrength; + float flickering; + vec2 scaleNoiseSize; + float frameShininess; + float frameSize; + float bloom; +}; + +layout(binding = 0) uniform sampler2D noiseSource; + +layout(location = 0) out vec2 qt_TexCoord0; +layout(location = 1) out float vBrightness; +layout(location = 2) out float vDistortionScale; +layout(location = 3) out float vDistortionFreq; + +void main() { + qt_TexCoord0 = qt_MultiTexCoord0; + + vec2 coords = vec2(fract(time / 2.048), fract(time / 1048.576)); + vec4 initialNoiseTexel = texture(noiseSource, coords); + + vBrightness = 1.0 + (initialNoiseTexel.g - 0.5) * flickering; + + float randval = horizontalSyncStrength - initialNoiseTexel.r; + vDistortionScale = step(0.0, randval) * randval * horizontalSyncStrength * horizontalSync; + vDistortionFreq = mix(4.0, 40.0, initialNoiseTexel.g) * step(0.0, horizontalSync); + + gl_Position = qt_Matrix * qt_Vertex; +} diff --git a/app/shaders/terminal_dynamic.vert.qsb b/app/shaders/terminal_dynamic.vert.qsb new file mode 100644 index 0000000..4699278 Binary files /dev/null and b/app/shaders/terminal_dynamic.vert.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn0_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn0_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..33087a7 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn0_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn0_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn0_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..9b29f41 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn0_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn0_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn0_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..a3441d5 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn0_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn0_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn0_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..eb8abed Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn0_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn1_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn1_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..971f1fe Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn1_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn1_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn1_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..9560a2f Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn1_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn1_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn1_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..a932023 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn1_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster0_burn1_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster0_burn1_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..c0f9734 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster0_burn1_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn0_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn0_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..a65e0d5 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn0_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn0_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn0_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..c4dc4e9 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn0_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn0_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn0_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..174ec5f Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn0_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn0_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn0_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..aab56a9 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn0_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn1_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn1_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..0d2c9d2 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn1_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn1_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn1_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..34e1b48 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn1_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn1_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn1_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..29ca7d2 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn1_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster1_burn1_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster1_burn1_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..1d265c9 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster1_burn1_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn0_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn0_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..aafbd81 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn0_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn0_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn0_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..4efa151 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn0_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn0_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn0_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..d930caa Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn0_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn0_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn0_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..745b25a Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn0_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn1_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn1_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..71c6472 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn1_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn1_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn1_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..bd94062 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn1_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn1_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn1_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..5a37938 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn1_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster2_burn1_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster2_burn1_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..401f8ba Binary files /dev/null and b/app/shaders/terminal_dynamic_raster2_burn1_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn0_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn0_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..e51beb0 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn0_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn0_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn0_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..51c8d1e Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn0_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn0_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn0_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..1ca060e Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn0_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn0_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn0_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..ee90e68 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn0_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn1_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn1_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..50d89d7 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn1_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn1_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn1_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..ee42174 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn1_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn1_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn1_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..fd00682 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn1_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster3_burn1_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster3_burn1_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..63d2e50 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster3_burn1_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn0_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn0_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..33087a7 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn0_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn0_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn0_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..9b29f41 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn0_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn0_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn0_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..a3441d5 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn0_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn0_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn0_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..eb8abed Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn0_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn1_frame0_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn1_frame0_chroma0.frag.qsb new file mode 100644 index 0000000..971f1fe Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn1_frame0_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn1_frame0_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn1_frame0_chroma1.frag.qsb new file mode 100644 index 0000000..9560a2f Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn1_frame0_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn1_frame1_chroma0.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn1_frame1_chroma0.frag.qsb new file mode 100644 index 0000000..a932023 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn1_frame1_chroma0.frag.qsb differ diff --git a/app/shaders/terminal_dynamic_raster4_burn1_frame1_chroma1.frag.qsb b/app/shaders/terminal_dynamic_raster4_burn1_frame1_chroma1.frag.qsb new file mode 100644 index 0000000..c0f9734 Binary files /dev/null and b/app/shaders/terminal_dynamic_raster4_burn1_frame1_chroma1.frag.qsb differ diff --git a/app/shaders/terminal_frame.frag b/app/shaders/terminal_frame.frag new file mode 100644 index 0000000..8f7b9bd --- /dev/null +++ b/app/shaders/terminal_frame.frag @@ -0,0 +1,79 @@ +#version 440 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float screenCurvature; + vec4 frameColor; + float frameSize; + float screenRadius; + vec2 viewportSize; + float ambientLight; + float frameShininess; +}; + +float min2(vec2 v) { return min(v.x, v.y); } +float prod2(vec2 v) { return v.x * v.y; } +float rand2(vec2 v) { return fract(sin(dot(v, vec2(12.9898, 78.233))) * 43758.5453); } + +vec2 distortCoordinates(vec2 coords){ + vec2 paddedCoords = coords * (vec2(1.0) + frameSize * 2.0) - frameSize; + vec2 cc = (paddedCoords - vec2(0.5)); + float dist = dot(cc, cc) * screenCurvature; + return (paddedCoords + cc * (1.0 + dist) * dist); +} + +float roundedRectSdfPixels(vec2 p, vec2 topLeft, vec2 bottomRight, float radiusPixels) { + vec2 sizePixels = (bottomRight - topLeft) * viewportSize; + vec2 centerPixels = (topLeft + bottomRight) * 0.5 * viewportSize; + vec2 localPixels = p * viewportSize - centerPixels; + vec2 halfSize = sizePixels * 0.5 - vec2(radiusPixels); + vec2 d = abs(localPixels) - halfSize; + return length(max(d, vec2(0.0))) + min(max(d.x, d.y), 0.0) - radiusPixels; +} + +void main() { + vec2 staticCoords = qt_TexCoord0; + vec2 coords = distortCoordinates(staticCoords); + + float screenRadiusPixels = screenRadius; + float edgeSoftPixels = 1.0; + + float seamWidth = max(screenRadiusPixels, 0.5) / min2(viewportSize); + + float e = min( + smoothstep(-seamWidth, seamWidth, coords.x - coords.y), + smoothstep(-seamWidth, seamWidth, coords.x - (1.0 - coords.y)) + ); + float s = min( + smoothstep(-seamWidth, seamWidth, coords.y - coords.x), + smoothstep(-seamWidth, seamWidth, coords.x - (1.0 - coords.y)) + ); + float w = min( + smoothstep(-seamWidth, seamWidth, coords.y - coords.x), + smoothstep(-seamWidth, seamWidth, (1.0 - coords.x) - coords.y) + ); + float n = min( + smoothstep(-seamWidth, seamWidth, coords.x - coords.y), + smoothstep(-seamWidth, seamWidth, (1.0 - coords.x) - coords.y) + ); + + float distPixels = roundedRectSdfPixels(coords, vec2(0.0), vec2(1.0), screenRadiusPixels); + float frameShadow = (e * 0.66 + w * 0.66 + n * 0.33 + s); + frameShadow *= smoothstep(0.0, edgeSoftPixels * 5.0, distPixels); + + float frameAlpha = 1.0 - frameShininess * 0.4; + + float inScreen = smoothstep(0.0, edgeSoftPixels, -distPixels); + float alpha = mix(frameAlpha, mix(0.0, 0.3, ambientLight), inScreen); + float glass = clamp(ambientLight * pow(prod2(coords * (1.0 - coords.yx)) * 25.0, 0.5) * inScreen, 0.0, 1.0); + vec3 frameTint = frameColor.rgb * frameShadow; + float noise = rand2(staticCoords * viewportSize) - 0.5; + frameTint = clamp(frameTint + vec3(noise * 0.04), 0.0, 1.0); + vec3 color = mix(frameTint, vec3(glass), inScreen); + + fragColor = vec4(color, alpha) * qt_Opacity; +} diff --git a/app/shaders/terminal_frame.frag.qsb b/app/shaders/terminal_frame.frag.qsb new file mode 100644 index 0000000..76e1b12 Binary files /dev/null and b/app/shaders/terminal_frame.frag.qsb differ diff --git a/app/shaders/terminal_frame.vert b/app/shaders/terminal_frame.vert new file mode 100644 index 0000000..deeedee --- /dev/null +++ b/app/shaders/terminal_frame.vert @@ -0,0 +1,23 @@ +#version 440 + +layout(location = 0) in vec4 qt_Vertex; +layout(location = 1) in vec2 qt_MultiTexCoord0; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float screenCurvature; + vec4 frameColor; + float frameSize; + float screenRadius; + vec2 viewportSize; + float ambientLight; + float frameShininess; +}; + +layout(location = 0) out vec2 qt_TexCoord0; + +void main() { + qt_TexCoord0 = qt_MultiTexCoord0; + gl_Position = qt_Matrix * qt_Vertex; +} diff --git a/app/shaders/terminal_frame.vert.qsb b/app/shaders/terminal_frame.vert.qsb new file mode 100644 index 0000000..7be88ca Binary files /dev/null and b/app/shaders/terminal_frame.vert.qsb differ diff --git a/app/shaders/terminal_static.frag b/app/shaders/terminal_static.frag new file mode 100644 index 0000000..7be4542 --- /dev/null +++ b/app/shaders/terminal_static.frag @@ -0,0 +1,98 @@ +#version 440 + +#ifndef CRT_RGB_SHIFT +#define CRT_RGB_SHIFT 1 +#endif +#ifndef CRT_BLOOM +#define CRT_BLOOM 1 +#endif +#ifndef CRT_FRAME_SHININESS +#define CRT_FRAME_SHININESS 1 +#endif +#ifndef CRT_CURVATURE +#define CRT_CURVATURE 1 +#endif + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float screenCurvature; + float rgbShift; + float frameShininess; + float frameSize; + float screen_brightness; + float bloom; +}; + +layout(binding = 1) uniform sampler2D source; +layout(binding = 2) uniform sampler2D bloomSource; + +float min2(vec2 v) { return min(v.x, v.y); } +float max2(vec2 v) { return max(v.x, v.y); } +float rand2(vec2 v) { return fract(sin(dot(v, vec2(12.9898, 78.233))) * 43758.5453); } +vec2 distortCoordinates(vec2 coords){ + vec2 paddedCoords = coords * (vec2(1.0) + frameSize * 2.0) - frameSize; + vec2 cc = (paddedCoords - vec2(0.5)); + float dist = dot(cc, cc) * screenCurvature; + return (paddedCoords + cc * (1.0 + dist) * dist); +} + +void main() { + vec2 cc = vec2(0.5) - qt_TexCoord0; + + float shownDraw = 1.0; + float isReflection = 0.0; + float isScreen = 1.0; + + vec2 txt_coords = qt_TexCoord0; +#if CRT_CURVATURE == 1 + vec2 curvatureCoords = distortCoordinates(qt_TexCoord0); + shownDraw = max2(step(vec2(0.0), curvatureCoords) - step(vec2(1.0), curvatureCoords)); + isScreen = min2(step(vec2(0.0), curvatureCoords) - step(vec2(1.0), curvatureCoords)); + isReflection = shownDraw - isScreen; + txt_coords = curvatureCoords * (-1.0 + 2.0 * step(vec2(0.0), curvatureCoords) - 2.0 * step(vec2(1.0), curvatureCoords)); +#endif + + vec3 txt_color = texture(source, txt_coords).rgb; + +#if CRT_RGB_SHIFT == 1 + vec2 displacement = vec2(rgbShift, 0.0); + vec3 rightColor = texture(source, txt_coords + displacement).rgb; + vec3 leftColor = texture(source, txt_coords - displacement).rgb; + txt_color.r = leftColor.r * 0.10 + rightColor.r * 0.30 + txt_color.r * 0.60; + txt_color.g = leftColor.g * 0.20 + rightColor.g * 0.20 + txt_color.g * 0.60; + txt_color.b = leftColor.b * 0.30 + rightColor.b * 0.10 + txt_color.b * 0.60; +#endif + + vec3 finalColor = txt_color * shownDraw; + + vec3 bloomColor = txt_color; + float bloomAlpha = 0.0; +#if CRT_BLOOM == 1 || CRT_FRAME_SHININESS == 1 + vec4 bloomFullColor = texture(bloomSource, txt_coords); + bloomColor = bloomFullColor.rgb; + bloomAlpha = bloomFullColor.a; +#endif + +#if CRT_BLOOM == 1 + vec3 bloomOnScreen = bloomColor * isScreen; + finalColor += clamp(bloomOnScreen * bloom * bloomAlpha, 0.0, 0.5); + float bloomScale = 1.0 + max(bloom, 0.0); + finalColor /= bloomScale; +#endif + +#if CRT_FRAME_SHININESS == 1 + vec3 reflectionColor = mix(bloomColor * bloomAlpha * 2.0, finalColor, frameShininess * 0.5); + finalColor = mix(finalColor, reflectionColor, isReflection); +#endif + + finalColor *= screen_brightness; + + float noise = rand2(qt_TexCoord0) - 0.5; + finalColor = clamp(finalColor + vec3(noise * 0.025), 0.0, 1.0); + + fragColor = vec4(finalColor, qt_Opacity); +} diff --git a/app/shaders/terminal_static.vert b/app/shaders/terminal_static.vert new file mode 100644 index 0000000..a27981c --- /dev/null +++ b/app/shaders/terminal_static.vert @@ -0,0 +1,22 @@ +#version 440 + +layout(location = 0) in vec4 qt_Vertex; +layout(location = 1) in vec2 qt_MultiTexCoord0; + +layout(std140, binding = 0) uniform ubuf { + mat4 qt_Matrix; + float qt_Opacity; + float screenCurvature; + float rgbShift; + float frameShininess; + float frameSize; + float screen_brightness; + float bloom; +}; + +layout(location = 0) out vec2 qt_TexCoord0; + +void main() { + qt_TexCoord0 = qt_MultiTexCoord0; + gl_Position = qt_Matrix * qt_Vertex; +} diff --git a/app/shaders/terminal_static.vert.qsb b/app/shaders/terminal_static.vert.qsb new file mode 100644 index 0000000..bc601fa Binary files /dev/null and b/app/shaders/terminal_static.vert.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..bf740ea Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..1f5a0b6 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..6dc84ca Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..4c7884c Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..ee5f9e8 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..a4187c2 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..9d275ba Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..e56309f Binary files /dev/null and b/app/shaders/terminal_static_rgb0_bloom1_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0.frag.qsb new file mode 100644 index 0000000..47f35df Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..afaa6c3 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..6bba6e7 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1.frag.qsb new file mode 100644 index 0000000..05c1064 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..c96ddb8 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..70c4c8c Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0.frag.qsb new file mode 100644 index 0000000..8fc19e2 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..0a9a173 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..c89bca4 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1.frag.qsb new file mode 100644 index 0000000..130ef25 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..6f82259 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..192a16c Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma0_bloom1_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0.frag.qsb new file mode 100644 index 0000000..27121ef Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..afaa6c3 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..6bba6e7 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1.frag.qsb new file mode 100644 index 0000000..e87838f Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..c96ddb8 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..70c4c8c Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0.frag.qsb new file mode 100644 index 0000000..3a32da6 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..0a9a173 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..c89bca4 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1.frag.qsb new file mode 100644 index 0000000..d6cee96 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..6f82259 Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..192a16c Binary files /dev/null and b/app/shaders/terminal_static_rgb0_chroma1_bloom1_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..f2f75ed Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..8bfd16d Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..c38bf2c Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..4226723 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..473964a Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..d65b9cb Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..7379ef8 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..950e7ec Binary files /dev/null and b/app/shaders/terminal_static_rgb1_bloom1_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0.frag.qsb new file mode 100644 index 0000000..e650cab Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..d22b6f7 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..11ac6ac Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1.frag.qsb new file mode 100644 index 0000000..98dabd8 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..8deb869 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..7121cab Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0.frag.qsb new file mode 100644 index 0000000..60c689a Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..cfc0a2f Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..5c55c85 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1.frag.qsb new file mode 100644 index 0000000..eaa0658 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..c243160 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..cf5c193 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma0_bloom1_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0.frag.qsb new file mode 100644 index 0000000..9e39cf3 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0_shine0.frag.qsb new file mode 100644 index 0000000..d22b6f7 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0_shine1.frag.qsb new file mode 100644 index 0000000..11ac6ac Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1.frag.qsb new file mode 100644 index 0000000..cdebc26 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1_shine0.frag.qsb new file mode 100644 index 0000000..8deb869 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1_shine1.frag.qsb new file mode 100644 index 0000000..7121cab Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom0_curve1_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0.frag.qsb new file mode 100644 index 0000000..65290f0 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0_shine0.frag.qsb new file mode 100644 index 0000000..cfc0a2f Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0_shine1.frag.qsb new file mode 100644 index 0000000..5c55c85 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve0_shine1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1.frag.qsb new file mode 100644 index 0000000..cb2ef28 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1_shine0.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1_shine0.frag.qsb new file mode 100644 index 0000000..c243160 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1_shine0.frag.qsb differ diff --git a/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1_shine1.frag.qsb b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1_shine1.frag.qsb new file mode 100644 index 0000000..cf5c193 Binary files /dev/null and b/app/shaders/terminal_static_rgb1_chroma1_bloom1_curve1_shine1.frag.qsb differ diff --git a/cool-retro-term.desktop b/cool-retro-term.desktop index 8c0d278..e9af133 100644 --- a/cool-retro-term.desktop +++ b/cool-retro-term.desktop @@ -9,3 +9,8 @@ StartupNotify=true Terminal=false Type=Application Keywords=shell;prompt;command;commandline; +Actions=NewWindow; + +[Desktop Action NewWindow] +Name=New Window +Exec=cool-retro-term diff --git a/qmltermwidget b/qmltermwidget index 6322802..ed85066 160000 --- a/qmltermwidget +++ b/qmltermwidget @@ -1 +1 @@ -Subproject commit 63228027e1f97c24abb907550b22ee91836929c5 +Subproject commit ed85066d14723303177cab663257b7b67107db62 diff --git a/scripts/build-appimage.sh b/scripts/build-appimage.sh new file mode 100755 index 0000000..96b59a9 --- /dev/null +++ b/scripts/build-appimage.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + +REPO_ROOT="$(readlink -f "$(dirname "$(dirname "$0")")")" +OLD_CWD="$(readlink -f .)" +BUILD_DIR="$REPO_ROOT/build/appimage" +TOOLS_DIR="$BUILD_DIR/tools" +VERSION="$(git -C "$REPO_ROOT" describe --tags --always --dirty=-dirty 2>/dev/null || true)" +if [ -z "$VERSION" ]; then + VERSION="unknown" +fi + +if ! command -v qmake >/dev/null; then + echo "qmake not found in PATH." >&2 + exit 1 +fi +QTDIR="$(qmake -query QT_INSTALL_PREFIX)" +QT_INSTALL_QML="$(qmake -query QT_INSTALL_QML)" + +APPDIR="$BUILD_DIR/AppDir" + +mkdir -p "$BUILD_DIR" +rm -rf "$APPDIR" +pushd "$BUILD_DIR" + +qmake "$REPO_ROOT/cool-retro-term.pro" +make -j"$(nproc)" + +# Install targets from subprojects (the top-level install only installs the desktop file). +make -C app install INSTALL_ROOT="$APPDIR" +make -C qmltermwidget install INSTALL_ROOT="$APPDIR" +make install INSTALL_ROOT="$APPDIR" + +popd + +# Relocate QMLTermWidget into the standard AppDir QML import path. +QML_ROOT="$APPDIR$QT_INSTALL_QML" +if [ -d "$QML_ROOT" ]; then + mkdir -p "$APPDIR/usr/qml" + rsync -a "$QML_ROOT/" "$APPDIR/usr/qml/" + rm -rf "$QML_ROOT" + QML_PARENT="$(dirname "$QML_ROOT")" + while [ "$QML_PARENT" != "$APPDIR" ] && rmdir "$QML_PARENT" 2>/dev/null; do + QML_PARENT="$(dirname "$QML_PARENT")" + done +fi + + +# Build AppImage using linuxdeploy and linuxdeploy-plugin-qt. +mkdir -p "$TOOLS_DIR" +LINUXDEPLOY="$TOOLS_DIR/linuxdeploy-x86_64.AppImage" +LINUXDEPLOY_QT="$TOOLS_DIR/linuxdeploy-plugin-qt-x86_64.AppImage" +if [ ! -x "$LINUXDEPLOY" ]; then + wget -c -O "$LINUXDEPLOY" https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x "$LINUXDEPLOY" +fi +if [ ! -x "$LINUXDEPLOY_QT" ]; then + wget -c -O "$LINUXDEPLOY_QT" https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage + chmod +x "$LINUXDEPLOY_QT" +fi + +export QML_SOURCES_PATHS="$REPO_ROOT/app" + +pushd "$BUILD_DIR" + +export EXTRA_PLATFORM_PLUGINS="libqwayland.so;" +export EXTRA_QT_MODULES="sql;waylandcompositor;waylandclient" +export DEPLOY_PLATFORM_THEMES=true +export LINUXDEPLOY_EXCLUDED_LIBRARIES="libmysqlclient.so;libqsqlmimer.so;libqsqlmysql.so;libqsqlodbc.so;libqsqlpsql.so;libqsqloci.so;libqsqlibase.so" + +"$LINUXDEPLOY" \ + --appdir "$APPDIR" \ + -e "$APPDIR/usr/bin/cool-retro-term" \ + -i "$REPO_ROOT/app/icons/256x256/cool-retro-term.png" \ + -d "$REPO_ROOT/cool-retro-term.desktop" \ + --plugin qt \ + --output appimage + +APPIMAGE_PATH="$(ls -1 ./*.AppImage | head -n 1)" +APPIMAGE_OUT="cool-retro-term-${VERSION}.AppImage" +mv "$APPIMAGE_PATH" "$OLD_CWD/$APPIMAGE_OUT" +popd diff --git a/scripts/build-dmg.sh b/scripts/build-dmg.sh new file mode 100755 index 0000000..d1bab1b --- /dev/null +++ b/scripts/build-dmg.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" +OLD_CWD="$(pwd -P)" +BUILD_DIR="$REPO_ROOT/build/dmg" +APP="cool-retro-term.app" +QML_DIR="$REPO_ROOT/app/qml" +JOBS="${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || echo 4)}" +VERSION="$(git -C "$REPO_ROOT" describe --tags --always --dirty=-dirty 2>/dev/null || true)" +if [ -z "$VERSION" ]; then + VERSION="unknown" +fi + +if ! command -v qmake >/dev/null; then + echo "qmake not found in PATH." >&2 + exit 1 +fi +QT_DIR="${QT_DIR:-$(qmake -query QT_INSTALL_PREFIX)}" +QT_BIN="${QT_DIR%/}/bin" + +mkdir -p "$BUILD_DIR" +rm -f "$BUILD_DIR/${APP%.app}.dmg" +pushd "$BUILD_DIR" + +"$QT_BIN/qmake" CONFIG+=release "$REPO_ROOT/cool-retro-term.pro" +make -j"$JOBS" + +PLUGIN_DST="$APP/Contents/PlugIns/qmltermwidget" +rm -rf "$PLUGIN_DST" +mkdir -p "$APP/Contents/PlugIns" +cp -R qmltermwidget/QMLTermWidget "$PLUGIN_DST" + +export QML_IMPORT_PATH="$PWD/$APP/Contents/PlugIns" +"$QT_BIN/macdeployqt" "$APP" -qmldir="$QML_DIR" -dmg + +rm -f "$APP/Contents/PlugIns/sqldrivers/"libqsql{odbc,psql,mimer}.dylib 2>/dev/null || true +DMG_OUT="${APP%.app}-${VERSION}.dmg" +mv "$BUILD_DIR/${APP%.app}.dmg" "$OLD_CWD/$DMG_OUT" +popd diff --git a/scripts/list_glyph_counts.py b/scripts/list_glyph_counts.py new file mode 100644 index 0000000..8d1b851 --- /dev/null +++ b/scripts/list_glyph_counts.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +""" +Print glyph counts for all font files under app/qml/fonts. +Requires fontTools (already available in this environment). +""" +from pathlib import Path +from fontTools.ttLib import TTFont + + +def count_glyphs(font_path: Path) -> int: + """Return the number of glyphs in the font.""" + with TTFont(str(font_path), lazy=False, fontNumber=0) as font: + return len(font.getGlyphOrder()) + + +def main() -> None: + fonts_root = Path(__file__).resolve().parents[1] / "app" / "qml" / "fonts" + font_files = sorted( + p for p in fonts_root.rglob("*") if p.suffix.lower() in {".ttf", ".otf", ".otb"} + ) + + if not font_files: + print(f"No font files found under {fonts_root}") + return + + for font_path in font_files: + rel = font_path.relative_to(fonts_root.parent.parent) + try: + count = count_glyphs(font_path) + print(f"{rel}: {count} glyphs") + except Exception as exc: # noqa: BLE001 + print(f"{rel}: error reading font ({exc})") + + +if __name__ == "__main__": + main()