diff --git a/.github/workflows/tagged-release.yml b/.github/workflows/tagged-release.yml index 68d3955a..2b17bf6d 100644 --- a/.github/workflows/tagged-release.yml +++ b/.github/workflows/tagged-release.yml @@ -11,7 +11,7 @@ env: jobs: create-release: name: Create Release - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Create Release id: create_release @@ -33,11 +33,11 @@ jobs: release-linux: name: Release Linux - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 needs: ["create-release"] steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Build resvg run: cargo build --release @@ -57,6 +57,10 @@ jobs: cp resvg-linux-x86_64.tar.gz ../../bin/ cp usvg-linux-x86_64.tar.gz ../../bin/ + - name: Build C API + working-directory: crates/c-api + run: cargo build --release + - name: Get version id: get_version uses: battila7/get-version-action@v2 @@ -88,14 +92,13 @@ jobs: release-windows: name: Release Windows - runs-on: windows-2019 + runs-on: windows-2022 needs: ["create-release"] steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Toolchain is stable-x86_64-pc-windows-msvc by default. No need to change it. - - name: Build resvg env: RUSTFLAGS: -Ctarget-feature=+crt-static # make sure it's static @@ -150,11 +153,11 @@ jobs: release-macos: name: Release macOS - runs-on: macos-13 + runs-on: macos-15 needs: ["create-release"] steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Some weird CI glitch. Make sure we have the latest Rust. - name: Install latest stable toolchain diff --git a/.github/workflows/viewsvg-release.yml b/.github/workflows/viewsvg-release.yml new file mode 100644 index 00000000..42ecdf5f --- /dev/null +++ b/.github/workflows/viewsvg-release.yml @@ -0,0 +1,350 @@ +name: "ViewSVG Release" + +on: + workflow_dispatch: + inputs: + release_tag: + description: 'Release tag to append binaries to (e.g. v0.30.0, leave empty for latest)' + required: false + type: string + default: '' + +env: + CARGO_TERM_COLOR: always + +jobs: + prepare-release: + name: Prepare Release Info + runs-on: ubuntu-24.04 + outputs: + upload_url: ${{ steps.get_release.outputs.upload_url }} + release_tag: ${{ steps.determine_tag.outputs.release_tag }} + release_id: ${{ steps.get_release.outputs.release_id }} + steps: + - name: Determine release tag + id: determine_tag + run: | + if [[ -z "${{ github.event.inputs.release_tag }}" ]]; then + LATEST_RELEASE=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name) + echo "Using latest release: ${LATEST_RELEASE}" + echo "release_tag=${LATEST_RELEASE}" >> $GITHUB_OUTPUT + else + echo "Using specified release: ${{ github.event.inputs.release_tag }}" + echo "release_tag=${{ github.event.inputs.release_tag }}" >> $GITHUB_OUTPUT + fi + + - name: Get release + id: get_release + run: | + RELEASE_TAG="${{ steps.determine_tag.outputs.release_tag }}" + RELEASE_INFO=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/tags/${RELEASE_TAG}) + UPLOAD_URL=$(echo $RELEASE_INFO | jq -r .upload_url) + RELEASE_ID=$(echo $RELEASE_INFO | jq -r .id) + + if [[ "$UPLOAD_URL" == "null" ]]; then + echo "::error::Could not find release with tag ${RELEASE_TAG}" + exit 1 + fi + + echo "Found release URL: ${UPLOAD_URL}" + echo "upload_url=${UPLOAD_URL}" >> $GITHUB_OUTPUT + echo "release_id=${RELEASE_ID}" >> $GITHUB_OUTPUT + + viewsvg-linux: + name: Build ViewSVG for Linux + runs-on: ubuntu-24.04 + needs: ["prepare-release"] + outputs: + success: ${{ steps.build_success.outputs.success }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare-release.outputs.release_tag }} + + - name: Build C API + working-directory: crates/c-api + run: cargo build --release + + - name: Install Qt + uses: jurplel/install-qt-action@v4.2.1 + with: + version: '6.8.3' + + - name: Build viewsvg + working-directory: tools/viewsvg + run: | + qmake6 + make + + # Create AppDir structure + mkdir -p AppDir/usr/bin + mkdir -p AppDir/usr/lib + mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps + + # Copy viewsvg binary + cp viewsvg AppDir/usr/bin/ + + # Copy libresvg.so and set correct permissions + cp ../../target/release/libresvg.so AppDir/usr/lib/ + chmod +x AppDir/usr/lib/libresvg.so + + # Create a simple SVG icon as fallback + cat > AppDir/usr/share/icons/hicolor/256x256/apps/viewsvg.svg << EOF + + + SVG + + EOF + + - name: Create AppImage + working-directory: tools/viewsvg + run: | + # Install linuxdeploy and Qt plugin + wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-plugin-qt-x86_64.AppImage + + # Create .desktop file with icon reference + mkdir -p AppDir/usr/share/applications + cat > AppDir/usr/share/applications/viewsvg.desktop << EOF + [Desktop Entry] + Type=Application + Name=ViewSVG + Comment=Simple SVG viewer + Exec=viewsvg + Icon=viewsvg + Categories=Graphics;Viewer; + EOF + + # Add library path to environment + export LD_LIBRARY_PATH=AppDir/usr/lib:$LD_LIBRARY_PATH + + # Create AppImage with library path + export OUTPUT=viewsvg-x86_64.AppImage + ./linuxdeploy-x86_64.AppImage --appdir=AppDir --plugin=qt --output=appimage + + # Compress AppImage + 7z a -tzip -mx9 viewsvg-linux-x86_64.zip viewsvg-x86_64.AppImage + + - name: Collect viewsvg binary + run: | + mkdir -p bin + cp tools/viewsvg/viewsvg-linux-x86_64.zip bin/ + + - name: Check for existing asset and remove if found + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + RELEASE_ID="${{ needs.prepare-release.outputs.release_id }}" + ASSET_NAME="viewsvg-linux-x86_64.zip" + + # Get list of assets + ASSETS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + "https://api.github.com/repos/${{ github.repository }}/releases/${RELEASE_ID}/assets") + + # Find asset ID for the given name if it exists + ASSET_ID=$(echo "$ASSETS" | jq -r ".[] | select(.name == \"$ASSET_NAME\") | .id") + + if [[ ! -z "$ASSET_ID" ]]; then + echo "Found existing asset with ID: $ASSET_ID, removing it..." + curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \ + "https://api.github.com/repos/${{ github.repository }}/releases/assets/$ASSET_ID" + else + echo "No existing asset found with name: $ASSET_NAME" + fi + + - name: Upload Linux binary to release + uses: shogo82148/actions-upload-release-asset@v1 + with: + upload_url: ${{ needs.prepare-release.outputs.upload_url }} + asset_path: bin/viewsvg-linux-x86_64.zip + asset_name: viewsvg-linux-x86_64.zip + asset_content_type: application/zip + + - name: Set success output + id: build_success + run: echo "success=true" >> $GITHUB_OUTPUT + + viewsvg-windows: + name: Build ViewSVG for Windows + runs-on: windows-2022 + needs: ["prepare-release"] + outputs: + success: ${{ steps.build_success.outputs.success }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare-release.outputs.release_tag }} + + - name: Build C API + working-directory: crates/c-api + run: cargo build --release + + - name: Install Qt + uses: jurplel/install-qt-action@v4.2.1 + with: + version: '6.8.3' + + - name: Prepare Developer Command Prompt for MSVC + uses: ilammy/msvc-dev-cmd@v1 + + - name: Build viewsvg + working-directory: tools/viewsvg + run: | + qmake6 + nmake + mkdir viewsvg-bin + cp release/viewsvg.exe viewsvg-bin/viewsvg.exe + windeployqt --no-translations viewsvg-bin/viewsvg.exe + cd viewsvg-bin + 7z a -tzip -mx9 viewsvg-win64.zip * + + - name: Collect + run: | + mkdir bin + cp tools/viewsvg/viewsvg-bin/viewsvg-win64.zip bin/ + + - name: Check for existing asset and remove if found + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + RELEASE_ID="${{ needs.prepare-release.outputs.release_id }}" + ASSET_NAME="viewsvg-win64.zip" + + # Get list of assets + ASSETS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/${{ github.repository }}/releases/${RELEASE_ID}/assets") + + # Find asset ID for the given name if it exists + ASSET_ID=$(echo "$ASSETS" | jq -r ".[] | select(.name == \"$ASSET_NAME\") | .id") + + if [[ ! -z "$ASSET_ID" ]]; then + echo "Found existing asset with ID: $ASSET_ID, removing it..." + curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/${{ github.repository }}/releases/assets/$ASSET_ID" + else + echo "No existing asset found with name: $ASSET_NAME" + fi + + - name: Upload Windows binary to release + uses: shogo82148/actions-upload-release-asset@v1 + with: + upload_url: ${{ needs.prepare-release.outputs.upload_url }} + asset_path: bin/viewsvg-win64.zip + asset_name: viewsvg-win64.zip + asset_content_type: application/zip + + - name: Set success output + id: build_success + shell: bash + run: echo "success=true" >> $GITHUB_OUTPUT + + viewsvg-macos: + name: Build ViewSVG for macOS + runs-on: macos-15 + needs: ["prepare-release"] + outputs: + success: ${{ steps.build_success.outputs.success }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.prepare-release.outputs.release_tag }} + + - name: Install latest stable toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Build C API + working-directory: crates/c-api + run: cargo build --release + + - name: Install Qt + uses: jurplel/install-qt-action@v4.2.1 + with: + version: '6.8.3' + + - name: Build viewsvg + working-directory: tools/viewsvg + run: | + qmake6 + make + macdeployqt viewsvg.app + rm -r viewsvg.app/Contents/Plugins/iconengines + rm -r viewsvg.app/Contents/Plugins/imageformats + 7z a -tzip -mx9 viewsvg-macos-x86_64.zip viewsvg.app + + - name: Collect + run: | + mkdir bin + cp tools/viewsvg/viewsvg-macos-x86_64.zip bin/ + + - name: Check for existing asset and remove if found + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + RELEASE_ID="${{ needs.prepare-release.outputs.release_id }}" + ASSET_NAME="viewsvg-macos-x86_64.zip" + + # Get list of assets + ASSETS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/${{ github.repository }}/releases/${RELEASE_ID}/assets") + + # Find asset ID for the given name if it exists + ASSET_ID=$(echo "$ASSETS" | jq -r ".[] | select(.name == \"$ASSET_NAME\") | .id") + + if [[ ! -z "$ASSET_ID" ]]; then + echo "Found existing asset with ID: $ASSET_ID, removing it..." + curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/${{ github.repository }}/releases/assets/$ASSET_ID" + else + echo "No existing asset found with name: $ASSET_NAME" + fi + + - name: Upload macOS binary to release + uses: shogo82148/actions-upload-release-asset@v1 + with: + upload_url: ${{ needs.prepare-release.outputs.upload_url }} + asset_path: bin/viewsvg-macos-x86_64.zip + asset_name: viewsvg-macos-x86_64.zip + asset_content_type: application/zip + + - name: Set success output + id: build_success + run: echo "success=true" >> $GITHUB_OUTPUT + + update-release: + name: Update Release Description + runs-on: ubuntu-24.04 + needs: ["prepare-release", "viewsvg-linux", "viewsvg-windows", "viewsvg-macos"] + if: | + always() && ( + needs.viewsvg-linux.result == 'success' && needs.viewsvg-linux.outputs.success == 'true' || + needs.viewsvg-windows.result == 'success' && needs.viewsvg-windows.outputs.success == 'true' || + needs.viewsvg-macos.result == 'success' && needs.viewsvg-macos.outputs.success == 'true' + ) + steps: + - name: Update release description + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + RELEASE_ID="${{ needs.prepare-release.outputs.release_id }}" + RELEASE_INFO=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/${{ github.repository }}/releases/${RELEASE_ID}") + CURRENT_BODY=$(echo $RELEASE_INFO | jq -r .body) + + # Check if the line already exists in the body + if [[ "$CURRENT_BODY" != *'`viewsvg` is a simple application that showcases resvg capabilities'* ]]; then + # Create new body with line at beginning + NEW_LINE='- `viewsvg` is a simple application that showcases resvg capabilities' + NEW_BODY=$(echo -e "$NEW_LINE\n$CURRENT_BODY") + + # Update the release body + curl -s -X PATCH \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + -d "{\"body\": $(echo "$NEW_BODY" | jq -s -R .)}" \ + "https://api.github.com/repos/${{ github.repository }}/releases/${RELEASE_ID}" + + echo "Release description updated successfully." + else + echo "The viewsvg line already exists in the release description. No update needed." + fi diff --git a/tools/viewsvg/.gitignore b/tools/viewsvg/.gitignore index 75c107bc..57014542 100644 --- a/tools/viewsvg/.gitignore +++ b/tools/viewsvg/.gitignore @@ -1 +1,7 @@ *.pro.user +*.o +moc_* +viewsvg +.* +ui_*.h +Makefile diff --git a/tools/viewsvg/main.cpp b/tools/viewsvg/main.cpp index 042e4a96..aa36634f 100644 --- a/tools/viewsvg/main.cpp +++ b/tools/viewsvg/main.cpp @@ -7,8 +7,6 @@ int main(int argc, char *argv[]) { - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QApplication a(argc, argv); MainWindow w; diff --git a/tools/viewsvg/svgview.cpp b/tools/viewsvg/svgview.cpp index 965f0071..b1027692 100644 --- a/tools/viewsvg/svgview.cpp +++ b/tools/viewsvg/svgview.cpp @@ -302,7 +302,7 @@ void SvgView::requestUpdate() m_timer.start(100, this); // Run method in the m_worker thread scope. - QTimer::singleShot(1, m_worker, [=](){ + QTimer::singleShot(1, m_worker, [this, s](){ m_worker->render(s); }); } diff --git a/tools/viewsvg/viewsvg.pro b/tools/viewsvg/viewsvg.pro index 9aed32cc..7bc3bae5 100644 --- a/tools/viewsvg/viewsvg.pro +++ b/tools/viewsvg/viewsvg.pro @@ -2,7 +2,7 @@ QT += core gui widgets TARGET = viewsvg TEMPLATE = app -CONFIG += c++11 +CONFIG += c++20 SOURCES += \ main.cpp \