diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d170ed4c..e4da7f34 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -284,7 +284,7 @@ jobs:
- name: Build Linux
run: |
- node build_tgfx -DTGFX_USE_SWIFTSHADER=ON
+ node build_tgfx -s ./linux Hello2D -o ./out/release/linux -a x64
- name: Save Third-Party Cache
if: ${{ (github.event_name == 'push') && (steps.third-party-cache.outputs.cache-hit != 'true') }}
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 5fe263c2..e20dc0fc 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,7 +15,6 @@
-
\ No newline at end of file
diff --git a/README.md b/README.md
index f04515bb..79e424f4 100644
--- a/README.md
+++ b/README.md
@@ -268,6 +268,27 @@ pack the generated `.wasm` file into the final web program. This is because comm
usually ignore the `.wasm` file. Moreover, remember to upload the `.wasm` file to a server, enabling
users to access it from the network.
+### Linux
+
+When running Linux, the system usually lacks GPU hardware support. Therefore, we utilize the
+[**SwiftShader**](https://github.com/google/swiftshader) library to emulate the GPU rendering
+environment. Since SwiftShader relies on certain X11 header files, it is necessary to install the
+following packages before building the demo project:
+
+```
+yum install libX11-devel --nogpg
+```
+
+Next, execute the following commands in the linux/ directory:
+
+```
+cmake -B ./build -DCMAKE_BUILD_TYPE=Release
+cmake --build ./build -- -j 12
+```
+
+You will get the demo executable file in the build directory. You also have the option of opening
+the `linux/` directory in CLion and building the demo project directly in the IDE.
+
### Windows
To start, open the `win/` directory in CLion. Next, open the `File->Setting` panel and navigate to
diff --git a/codeformat.sh b/codeformat.sh
index 4f0c683d..65eb25d2 100755
--- a/codeformat.sh
+++ b/codeformat.sh
@@ -1,4 +1,6 @@
#!/usr/bin/env bash
+cd $(dirname $0)
+
if [[ $(uname) == 'Darwin' ]]; then
MAC_REQUIRED_TOOLS="python3"
for TOOL in ${MAC_REQUIRED_TOOLS[@]}; do
@@ -26,24 +28,24 @@ echo "----begin to scan code format----"
find include -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
find src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
find drawers -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find test -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find qt -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find ios -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find mac -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find linux -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find win -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find web -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
-find android -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find test/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find qt/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find ios/Hello2D -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find mac/Hello2D -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find linux/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find win/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find web/demo/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
+find android/app/src -name "*.cpp" -print -o -name "*.c" -print -o -name "*.h" -print -o -name "*.mm" -print -o -name "*.m" -print | xargs clang-format -i
git diff
result=`git diff`
if [[ $result =~ "diff" ]]
then
- echo "----Failed to pass coding specification----"
+ echo "----Failed to pass the code format check----"
exit 1
else
- echo "----Pass coding specification----"
+ echo "----Complete the code format check-----"
fi
-echo "----Complete the scan code format-----"
+
diff --git a/linux/.idea/fileTemplates/includes/TGFX File Header.h b/linux/.idea/fileTemplates/includes/TGFX File Header.h
new file mode 100644
index 00000000..9a045aca
--- /dev/null
+++ b/linux/.idea/fileTemplates/includes/TGFX File Header.h
@@ -0,0 +1,17 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making tgfx available.
+//
+// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// https://opensource.org/licenses/BSD-3-Clause
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/linux/.idea/fileTemplates/internal/C Header File.h b/linux/.idea/fileTemplates/internal/C Header File.h
new file mode 100644
index 00000000..d7f0678b
--- /dev/null
+++ b/linux/.idea/fileTemplates/internal/C Header File.h
@@ -0,0 +1,7 @@
+#parse("TGFX File Header.h")
+
+#pragma once
+
+namespace tgfx {
+
+} // namespace tgfx
diff --git a/linux/.idea/fileTemplates/internal/C Source File.c b/linux/.idea/fileTemplates/internal/C Source File.c
new file mode 100644
index 00000000..1df3e1b3
--- /dev/null
+++ b/linux/.idea/fileTemplates/internal/C Source File.c
@@ -0,0 +1,8 @@
+#parse("TGFX File Header.h")
+#if (${HEADER_FILENAME})
+#[[#include]]# "${HEADER_FILENAME}"
+#end
+
+namespace tgfx {
+
+} // namespace tgfx
\ No newline at end of file
diff --git a/linux/.idea/fileTemplates/internal/C++ Class Header.h b/linux/.idea/fileTemplates/internal/C++ Class Header.h
new file mode 100644
index 00000000..e1c28ff0
--- /dev/null
+++ b/linux/.idea/fileTemplates/internal/C++ Class Header.h
@@ -0,0 +1,9 @@
+#parse("TGFX File Header.h")
+
+#pragma once
+
+namespace tgfx {
+class ${NAME} {
+ public:
+};
+} // namespace tgfx
diff --git a/linux/.idea/fileTemplates/internal/C++ Class.cc b/linux/.idea/fileTemplates/internal/C++ Class.cc
new file mode 100644
index 00000000..6df4f00d
--- /dev/null
+++ b/linux/.idea/fileTemplates/internal/C++ Class.cc
@@ -0,0 +1,7 @@
+#parse("TGFX File Header.h")
+
+#[[#include]]# "${HEADER_FILENAME}"
+
+namespace tgfx {
+
+} // namespace tgfx
diff --git a/linux/.idea/misc.xml b/linux/.idea/misc.xml
new file mode 100644
index 00000000..79b3c948
--- /dev/null
+++ b/linux/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt
new file mode 100644
index 00000000..87cf48d2
--- /dev/null
+++ b/linux/CMakeLists.txt
@@ -0,0 +1,54 @@
+cmake_minimum_required(VERSION 3.13)
+project(Hello2D)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+if (NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Release")
+endif ()
+
+if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR $CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
+ set(ARCH x64)
+elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
+ set(ARCH arm64)
+else ()
+ set(ARCH x86)
+endif ()
+
+file(GLOB SWIFTSHADER_LIBS ../vendor/swiftshader/mac/${ARCH}/*.${CMAKE_SHARED_LIBRARY_SUFFIX})
+list(APPEND HELLO_2D_LIBS ${SWIFTSHADER_LIBS})
+list(APPEND HELLO_2D_INCLUDES ../vendor/swiftshader/include)
+
+if (APPLE)
+ find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices REQUIRED)
+ list(APPEND HELLO_2D_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
+ find_library(QUARTZ_CORE QuartzCore REQUIRED)
+ list(APPEND HELLO_2D_LIBS ${QUARTZ_CORE})
+ find_library(COCOA Cocoa REQUIRED)
+ list(APPEND HELLO_2D_LIBS ${COCOA})
+ find_library(FOUNDATION Foundation REQUIRED)
+ list(APPEND HELLO_2D_LIBS ${FOUNDATION})
+ find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)
+ list(APPEND HELLO_2D_LIBS ${ICONV_LIBRARIES})
+ find_library(CORE_MEDIA CoreMedia)
+ list(APPEND HELLO_2D_LIBS ${CORE_MEDIA})
+else ()
+ find_package(Threads)
+ list(APPEND HELLO_2D_LIBS ${CMAKE_THREAD_LIBS_INIT})
+ list(APPEND HELLO_2D_LIBS dl)
+ list(APPEND HELLO_2D_COMPILE_OPTIONS -fPIC -pthread)
+endif ()
+
+set(TGFX_BUILD_DRAWERS ON)
+set(TGFX_USE_SWIFTSHADER ON)
+set(TGFX_USE_FREETYPE ON)
+
+set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ ./tgfx)
+
+file(GLOB_RECURSE HELLO_2D_SOURCE_FILES src/*.*)
+add_executable(Hello2D ${HELLO_2D_SOURCE_FILES})
+target_include_directories(Hello2D PRIVATE ${HELLO_2D_INCLUDES} src)
+target_link_libraries(Hello2D tgfx-drawers tgfx ${HELLO_2D_LIBS})
+
diff --git a/linux/src/main.cpp b/linux/src/main.cpp
new file mode 100644
index 00000000..1627db9c
--- /dev/null
+++ b/linux/src/main.cpp
@@ -0,0 +1,87 @@
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Tencent is pleased to support the open source community by making tgfx available.
+//
+// Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
+//
+// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// https://opensource.org/licenses/BSD-3-Clause
+//
+// unless required by applicable law or agreed to in writing, software distributed under the
+// license is distributed on an "as is" basis, without warranties or conditions of any kind,
+// either express or implied. see the license for the specific language governing permissions
+// and limitations under the license.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+#include "drawers/Drawer.h"
+#include "tgfx/gpu/Surface.h"
+#include "tgfx/opengl/GLDevice.h"
+#include "tgfx/platform/Print.h"
+
+static std::string GetRootPath() {
+ std::filesystem::path filePath = __FILE__;
+ auto dir = filePath.parent_path().string();
+ return std::filesystem::path(dir + "/../..").lexically_normal();
+}
+
+static void SaveFile(std::shared_ptr data, const std::string& output) {
+ std::filesystem::path path = output;
+ std::filesystem::create_directories(path.parent_path());
+ std::ofstream out(path);
+ out.write(reinterpret_cast(data->data()),
+ static_cast(data->size()));
+ out.close();
+}
+
+int main() {
+ auto rootPath = GetRootPath();
+ drawers::AppHost appHost(720, 720, 2.0f);
+ auto image = tgfx::Image::MakeFromFile(rootPath + "resources/assets/bridge.jpg");
+ appHost.addImage("bridge", std::move(image));
+ auto typeface = tgfx::Typeface::MakeFromPath(rootPath + "resources/font/NotoSansSC-Regular.otf");
+ appHost.addTypeface("default", std::move(typeface));
+ typeface = tgfx::Typeface::MakeFromPath(rootPath + "resources/font/NotoColorEmoji.ttf");
+ appHost.addTypeface("emoji", std::move(typeface));
+
+ auto device = tgfx::GLDevice::Make();
+ if (device == nullptr) {
+ tgfx::PrintError("Failed to create the Device!");
+ return -1;
+ }
+ auto context = device->lockContext();
+ if (context == nullptr) {
+ tgfx::PrintError("Failed to lock the Context!");
+ return -1;
+ }
+ auto surface = tgfx::Surface::Make(context, appHost.width(), appHost.height());
+ auto canvas = surface->getCanvas();
+ auto drawerNames = drawers::Drawer::Names();
+ for (auto& name : drawerNames) {
+ auto drawer = drawers::Drawer::GetByName(name);
+ canvas->clear();
+ drawer->draw(canvas, &appHost);
+ tgfx::Bitmap bitmap = {};
+ bitmap.allocPixels(surface->width(), surface->height());
+ auto pixels = bitmap.lockPixels();
+ auto success = surface->readPixels(bitmap.info(), pixels);
+ bitmap.unlockPixels();
+ if (!success) {
+ tgfx::PrintError("Failed to readPixels!");
+ return -1;
+ }
+ auto data = bitmap.encode();
+ if (data == nullptr) {
+ tgfx::PrintError("Failed to encode bitmap!");
+ return -1;
+ }
+ SaveFile(data, "out/" + name + ".png");
+ }
+ device->unlock();
+ tgfx::PrintLog("All images have been saved to the 'out/' directory");
+ return 0;
+}