Repository: kyamagu/skia-python (language: python)

Issue:
deprecation of `distutils`upstream for python >= 3.12
Been getting this warning when I do local builds (`python setup.py ...`) for a while now:

```
skia-python/setup.py:8: DeprecationWarning: 

  `numpy.distutils` is deprecated since NumPy 1.23.0, as a result
  of the deprecation of `distutils` itself. It will be removed for
  Python >= 3.12. For older Python versions it will remain present.
  It is recommended to use `setuptools < 60.0` for those Python versions.
  For more details, see:
    https://numpy.org/devdocs/reference/distutils_status_migration.html 


  from numpy.distutils.ccompiler import CCompiler_compile
/usr/lib/python3.12/site-packages/setuptools/__init__.py:84: _DeprecatedInstaller: setuptools.installer and fetch_build_eggs are deprecated.
!!

        ********************************************************************************
        Requirements should be satisfied by a PEP 517 installer.
        If you are using pip, you can try `pip install --use-pep517`.
        ********************************************************************************

!!
  dist.fetch_build_eggs(dist.setup_requires)
WARNING: The wheel package is not available.
```

Nothing urgent yet, but possibly needs some work for python 3.13.


Discussion / hints:
Perhaps it's a good time to migrate the build configuration to `python -m build` with the `pyproject.toml` configuration.
https://setuptools.pypa.io/en/latest/userguide/ext_modules.html

As far as I remember, the use of numpy distutils is to speed up the wheel compilation. Maybe not needed.
Okay, that makes sense - I was wondering why it is `try: ... except: pass` doing nothing for not found. In that case it is just cosmetic, so I'd suggest adding a python version check to by-pass those few lines, to suppress the warning. I can add that at some point in time.
At this point, I would completely remove the `numpy.distutils` hack. [It seems pip supports parallel jobs as of now.](https://stackoverflow.com/questions/26669244/how-to-install-compile-pip-requirements-in-parallel-make-j-equivalent/57014278#57014278)
I removed the numpy section and it looks fine, but there is actually a 2nd deprecatioin after that (it is in above, just overlooked):

```
/usr/lib/python3.12/site-packages/setuptools/__init__.py:84: _DeprecatedInstaller: setuptools.installer and fetch_build_eggs are deprecated.
```
@HinTak Can you try `python -m build --format wheel`? Directly calling `python setup.py build` is deprecated.
Okay - I'll give it a try. Despite the deprecation warning about 3.12, it is still working on 3.12 at the moment...
The first time I tried `python -m build --wheel` (it is `--wheel`, not `--format wheel`), I got "No such module build". Obviously I have never built python package that way before, despite about a decade of misc python usage :-).

It seems both of these deprecation messages came from `python setup.py ...` . Switching to `python -m build ...`, both of them disappeared. But it is a lot slower. The stackoverflow url you refers to says "Sometimes pip uses make to build dependencies" so defining MAKEFLAGS works. That's not the case here. Switching to `-m build ...` loses not only parallel build for me, but also seems to disable ccache (probably because of using virtualenv). So it is a lot slow for me for both fresh build and incremental build.

Since both came from `python setup.py ...`, I am okay to just close this (as it is my personal preference...) - I'll just continue this way as long as it works for me, ignore the warnings, until it does not. The parallel build setting could do better though. `-m build --wheel` is not using multi-CPUs. (Skia itself is - ninja auto-detect number of CPUs, I think).
Sure, you can ignore the warning for a moment

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f104578c..3c44f8a2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -25,7 +25,7 @@ jobs:
           key: linux-aarch64-skia-${{ github.sha }}-3rd-party
       - name: Pre-fetch skia deps
         if: ${{ steps.cache-skia.outputs.cache-hit != 'true' }}
-        run: git config --global core.compression 0 && cd skia && patch -p1 -i ../patch/skia-m130-minimize-download.patch && python tools/git-sync-deps && patch -p1 -R -i ../patch/skia-m130-minimize-download.patch
+        run: git config --global core.compression 0 && cd skia && patch -p1 -i ../patch/skia-m131-minimize-download.patch && python tools/git-sync-deps && patch -p1 -R -i ../patch/skia-m131-minimize-download.patch
       - name: Set up QEMU
         uses: docker/setup-qemu-action@v3
       - name: Build skia 3rd-Party
@@ -73,29 +73,89 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        os: [ubuntu-22.04, windows-2022, macos-12]
+        os: [ubuntu-22.04, windows-2022, macos-13]
         arch: [auto64]
-        cp: ["cp3{8,9,10,11,12}"]
+        cp: ["cp3{10,11,12,13}"]
         include:
-          - os: macos-12
+          - os: macos-13
             arch: arm64
-            cp: "cp3{8,9,10,11,12}"
+            cp: "cp3{10,11,12,13}"
           # aarch64 is emulated and takes longer, build one wheel per job
           - os: ubuntu-22.04
             arch: aarch64
-            cp: cp38
+            cp: cp310
           - os: ubuntu-22.04
             arch: aarch64
-            cp: cp39
+            cp: cp311
           - os: ubuntu-22.04
             arch: aarch64
-            cp: cp310
+            cp: cp312
           - os: ubuntu-22.04
             arch: aarch64
-            cp: cp311
+            cp: cp313
+
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          submodules: true
+
+      - uses: actions/cache/restore@v4
+        if: runner.os == 'Linux' && matrix.arch == 'aarch64'
+        with:
+          path: |
+            gn
+            skia
+          key: linux-aarch64-skia-${{ github.sha }}
+
+      - name: Set up QEMU
+        if: runner.os == 'Linux' && matrix.arch == 'aarch64'
+        uses: docker/setup-qemu-action@v3
+        with:
+          platforms: ${{ matrix.arch }}
+
+      - name: Build wheels
+        uses: pypa/cibuildwheel@v2.21.3
+        env:
+          CIBW_BUILD: "${{ matrix.cp }}-*"
+          CIBW_SKIP: "*musllinux*"
+          CIBW_ARCHS: ${{ matrix.arch }}
+          CIBW_ENVIRONMENT_MACOS: TARGET_ARCH=${{ matrix.arch }} MACOSX_DEPLOYMENT_TARGET=11.0
+          CIBW_BEFORE_ALL: bash scripts/build_${{ runner.os }}.sh
+          CIBW_BEFORE_BUILD: pip install pybind11 numpy
+          CIBW_TEST_REQUIRES: pytest pillow glfw
+          CIBW_TEST_REQUIRES_MACOS: pytest pillow pyopengl
+          CIBW_TEST_COMMAND: python -m pytest {project}/tests
+          CIBW_TEST_COMMAND_LINUX: >
+            xvfb-run -s "-screen 0 640x480x24" python -m pytest {project}/tests
+          CIBW_TEST_SKIP: "*-macosx_arm64"
+
+      - uses: actions/upload-artifact@v4
+        with:
+          name: wheel-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.cp }}
+          path: ./wheelhouse/*.whl
+
+  # identical to "build_wheels", except with the older pypa/cibuildwheel@v2.19.2
+  build_wheels_old:
+    name: Build wheels on ${{ matrix.os }} (${{ matrix.arch }}) for ${{ matrix.cp }}
+    needs: prebuild_linux_aarch64
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-22.04, windows-2022, macos-13]
+        arch: [auto64]
+        cp: ["cp3{8,9}"]
+        include:
+          - os: macos-13
+            arch: arm64
+            cp: "cp3{8,9}"
+          # aarch64 is emulated and takes longer, build one wheel per job
           - os: ubuntu-22.04
             arch: aarch64
-            cp: cp312
+            cp: cp38
+          - os: ubuntu-22.04
+            arch: aarch64
+            cp: cp39
 
     steps:
       - uses: actions/checkout@v4
@@ -139,7 +199,7 @@ jobs:
 
   build_docs:
     name: Build docs
-    needs: [build_wheels]
+    needs: [build_wheels, build_wheels_old]
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
@@ -169,7 +229,7 @@ jobs:
 
   publish:
     name: Upload packages to PyPI
-    needs: [build_wheels]
+    needs: [build_wheels, build_wheels_old]
     runs-on: ubuntu-latest
     if: github.event_name == 'release' && github.event.action == 'published'
     permissions:
diff --git a/README.md b/README.md
index 37b2bfa8..43388386 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ Binary package is available on PyPI:
 pip install skia-python
 ```
 
-Supported platforms: Python 3.8-3.12 (CPython) on
+Supported platforms: Python 3.8-3.13 (CPython) on
 
 - Linux x86_64, aarch64
 - macOS x86_64, arm64
diff --git a/docs/tutorial/canvas.rst b/docs/tutorial/canvas.rst
index 16eb1791..ff658761 100644
--- a/docs/tutorial/canvas.rst
+++ b/docs/tutorial/canvas.rst
@@ -91,10 +91,11 @@ The following example uses glfw package to create an OpenGL context. Install
         glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
         glfw.window_hint(glfw.STENCIL_BITS, 8)
         # see https://www.glfw.org/faq#macos
-        glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
-        glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 2)
-        glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
-        glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
+        if sys.platform.startswith("darwin"):
+            glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
+            glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 2)
+            glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
+            glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
         window = glfw.create_window(640, 480, '', None, None)
         glfw.make_context_current(window)
         yield window
@@ -144,10 +145,11 @@ Here's a complete example:
             raise RuntimeError('glfw.init() failed')
         glfw.window_hint(glfw.STENCIL_BITS, 8)
         # see https://www.glfw.org/faq#macos
-        glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
-        glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 2)
-        glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
-        glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
+        if sys.platform.startswith("darwin"):
+            glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
+            glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 2)
+            glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
+            glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
         window = glfw.create_window(WIDTH, HEIGHT, '', None, None)
         glfw.make_context_current(window)
         yield window
diff --git a/patch/skia-m131-minimize-download.patch b/patch/skia-m131-minimize-download.patch
new file mode 100644
index 00000000..2d3642cc
--- /dev/null
+++ b/patch/skia-m131-minimize-download.patch
@@ -0,0 +1,70 @@
+diff --git a/DEPS b/DEPS
+index a30e242..3d8dd72 100644
+--- a/DEPS
++++ b/DEPS
+@@ -31,53 +31,18 @@ vars = {
+ #     ./tools/git-sync-deps
+ deps = {
+   "buildtools"                                   : "https://chromium.googlesource.com/chromium/src/buildtools.git@b138e6ce86ae843c42a1a08f37903207bebcca75",
+-  "third_party/externals/angle2"                 : "https://chromium.googlesource.com/angle/angle.git@78a694a1b82a01623226a418cf2f765c75e45c70",
+-  "third_party/externals/brotli"                 : "https://skia.googlesource.com/external/github.com/google/brotli.git@6d03dfbedda1615c4cba1211f8d81735575209c8",
+-  "third_party/externals/d3d12allocator"         : "https://skia.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git@169895d529dfce00390a20e69c2f516066fe7a3b",
+-  # Dawn requires jinja2 and markupsafe for the code generator, tint for SPIRV compilation, and abseil for string formatting.
+-  # When the Dawn revision is updated these should be updated from the Dawn DEPS as well.
+-  "third_party/externals/dawn"                   : "https://dawn.googlesource.com/dawn.git@f3c7cc5c580eb743829c78bb77df0c1e8f6a6ce3",
+-  "third_party/externals/jinja2"                 : "https://chromium.googlesource.com/chromium/src/third_party/jinja2@e2d024354e11cc6b041b0cff032d73f0c7e43a07",
+-  "third_party/externals/markupsafe"             : "https://chromium.googlesource.com/chromium/src/third_party/markupsafe@0bad08bb207bbfc1d6f3bbc82b9242b0c50e5794",
+-  "third_party/externals/abseil-cpp"             : "https://skia.googlesource.com/external/github.com/abseil/abseil-cpp.git@65a55c2ba891f6d2492477707f4a2e327a0b40dc",
+   "third_party/externals/dng_sdk"                : "https://android.googlesource.com/platform/external/dng_sdk.git@c8d0c9b1d16bfda56f15165d39e0ffa360a11123",
+-  "third_party/externals/egl-registry"           : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@b055c9b483e70ecd57b3cf7204db21f5a06f9ffe",
+-  "third_party/externals/emsdk"                  : "https://skia.googlesource.com/external/github.com/emscripten-core/emsdk.git@a896e3d066448b3530dbcaa48869fafefd738f57",
+   "third_party/externals/expat"                  : "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@624da0f593bb8d7e146b9f42b06d8e6c80d032a3",
+   "third_party/externals/freetype"               : "https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@83af801b552111e37d9466a887e1783a0fb5f196",
+   "third_party/externals/harfbuzz"               : "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@a070f9ebbe88dc71b248af9731dd49ec93f4e6e6",
+-  "third_party/externals/highway"                : "https://chromium.googlesource.com/external/github.com/google/highway.git@424360251cdcfc314cfc528f53c872ecd63af0f0",
+   "third_party/externals/icu"                    : "https://chromium.googlesource.com/chromium/deps/icu.git@364118a1d9da24bb5b770ac3d762ac144d6da5a4",
+-  "third_party/externals/icu4x"                  : "https://chromium.googlesource.com/external/github.com/unicode-org/icu4x.git@bcf4f7198d4dc5f3127e84a6ca657c88e7d07a13",
+-  "third_party/externals/imgui"                  : "https://skia.googlesource.com/external/github.com/ocornut/imgui.git@55d35d8387c15bf0cfd71861df67af8cfbda7456",
+-  "third_party/externals/libavif"                : "https://skia.googlesource.com/external/github.com/AOMediaCodec/libavif.git@55aab4ac0607ab651055d354d64c4615cf3d8000",
+-  "third_party/externals/libgav1"                : "https://chromium.googlesource.com/codecs/libgav1.git@5cf722e659014ebaf2f573a6dd935116d36eadf1",
+-  "third_party/externals/libgrapheme"            : "https://skia.googlesource.com/external/github.com/FRIGN/libgrapheme/@c0cab63c5300fa12284194fbef57aa2ed62a94c0",
+   "third_party/externals/libjpeg-turbo"          : "https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@ccfbe1c82a3b6dbe8647ceb36a3f9ee711fba3cf",
+-  "third_party/externals/libjxl"                 : "https://chromium.googlesource.com/external/gitlab.com/wg1/jpeg-xl.git@a205468bc5d3a353fb15dae2398a101dff52f2d3",
+   "third_party/externals/libpng"                 : "https://skia.googlesource.com/third_party/libpng.git@ed217e3e601d8e462f7fd1e04bed43ac42212429",
+   "third_party/externals/libwebp"                : "https://chromium.googlesource.com/webm/libwebp.git@845d5476a866141ba35ac133f856fa62f0b7445f",
+-  "third_party/externals/libyuv"                 : "https://chromium.googlesource.com/libyuv/libyuv.git@d248929c059ff7629a85333699717d7a677d8d96",
+-  "third_party/externals/microhttpd"             : "https://android.googlesource.com/platform/external/libmicrohttpd@748945ec6f1c67b7efc934ab0808e1d32f2fb98d",
+-  "third_party/externals/oboe"                   : "https://chromium.googlesource.com/external/github.com/google/oboe.git@b02a12d1dd821118763debec6b83d00a8a0ee419",
+-  "third_party/externals/opengl-registry"        : "https://skia.googlesource.com/external/github.com/KhronosGroup/OpenGL-Registry@14b80ebeab022b2c78f84a573f01028c96075553",
+-  "third_party/externals/partition_alloc"        : "https://chromium.googlesource.com/chromium/src/base/allocator/partition_allocator.git@ca4487e127c2e071da5d4a36a9f71fd7b65b1434",
+-  "third_party/externals/perfetto"               : "https://android.googlesource.com/platform/external/perfetto@93885509be1c9240bc55fa515ceb34811e54a394",
+   "third_party/externals/piex"                   : "https://android.googlesource.com/platform/external/piex.git@bb217acdca1cc0c16b704669dd6f91a1b509c406",
+-  "third_party/externals/swiftshader"            : "https://swiftshader.googlesource.com/SwiftShader@7a9a492a38b7c701f7c96a15a76046aed8f8c0c3",
+   "third_party/externals/vulkanmemoryallocator"  : "https://chromium.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@a6bfc237255a6bac1513f7c1ebde6d8aed6b5191",
+-  # vulkan-deps is a meta-repo containing several interdependent Khronos Vulkan repositories.
+-  # When the vulkan-deps revision is updated, those repos (spirv-*, vulkan-*) should be updated as well.
+   "third_party/externals/vulkan-deps"            : "https://chromium.googlesource.com/vulkan-deps@8f346c5caf5a624f42324ffb88167fc90992cab5",
+-  "third_party/externals/spirv-cross"            : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3",
+   "third_party/externals/spirv-headers"          : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@50bc4debdc3eec5045edbeb8ce164090e29b91f3",
+-  "third_party/externals/spirv-tools"            : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@42b315c15b1ff941b46bb3949c105e5386be8717",
+-  "third_party/externals/vello"                  : "https://skia.googlesource.com/external/github.com/linebender/vello.git@3ee3bea02164c5a816fe6c16ef4e3a810edb7620",
+-  "third_party/externals/vulkan-headers"         : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Headers@d91597a82f881d473887b560a03a7edf2720b72c",
+-  "third_party/externals/vulkan-tools"           : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Tools@eb9b6043be165f06c7ec78fadbb1ff773c5fc19c",
+-  "third_party/externals/vulkan-utility-libraries": "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@bfd85956e1b4c1c79842ce857fc7fb15adb8a573",
+-  "third_party/externals/unicodetools"           : "https://chromium.googlesource.com/external/github.com/unicode-org/unicodetools@66a3fa9dbdca3b67053a483d130564eabc5fe095",
+-  #"third_party/externals/v8"                     : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4",
+   "third_party/externals/wuffs"                  : "https://skia.googlesource.com/external/github.com/google/wuffs-mirror-release-c.git@e3f919ccfe3ef542cfc983a82146070258fb57f8",
+   "third_party/externals/zlib"                   : "https://chromium.googlesource.com/chromium/src/third_party/zlib@646b7f569718921d7d4b5b8e22572ff6c76f2596",
+ 
+diff --git a/bin/activate-emsdk b/bin/activate-emsdk
+index 687ca9f..7167d8d 100755
+--- a/bin/activate-emsdk
++++ b/bin/activate-emsdk
+@@ -17,6 +17,7 @@ EMSDK_PATH = os.path.join(EMSDK_ROOT, 'emsdk.py')
+ EMSDK_VERSION = '3.1.44'
+ 
+ def main():
++    return
+     if sysconfig.get_platform() in ['linux-aarch64', 'linux-arm64']:
+         # This platform cannot install emsdk at the provided version. See
+         # https://github.com/emscripten-core/emsdk/blob/main/emscripten-releases-tags.json#L5
diff --git a/scripts/build_Linux.sh b/scripts/build_Linux.sh
index 8fc6efca..123e749c 100644
--- a/scripts/build_Linux.sh
+++ b/scripts/build_Linux.sh
@@ -60,7 +60,7 @@ git clone https://gn.googlesource.com/gn && \
 
 # Build skia
 cd skia && \
-    patch -p1 < ../patch/skia-m130-minimize-download.patch && \
+    patch -p1 < ../patch/skia-m131-minimize-download.patch && \
     patch -p1 < ../patch/skia-m123-colrv1-freetype.diff && \
     python3 tools/git-sync-deps && \
     cp -f ../gn/out/gn bin/gn && \
diff --git a/scripts/build_Windows.sh b/scripts/build_Windows.sh
index ce694e46..f64409af 100644
--- a/scripts/build_Windows.sh
+++ b/scripts/build_Windows.sh
@@ -4,7 +4,7 @@ export PATH="${PWD}/depot_tools:$PATH"
 
 # Build skia
 cd skia && \
-    patch -p1 < ../patch/skia-m130-minimize-download.patch && \
+    patch -p1 < ../patch/skia-m131-minimize-download.patch && \
     patch -p1 < ../patch/skia-m123-colrv1-freetype.diff && \
     python tools/git-sync-deps && \
     bin/gn gen out/Release --args='
diff --git a/scripts/build_macOS.sh b/scripts/build_macOS.sh
index 666d1fdb..07c44900 100644
--- a/scripts/build_macOS.sh
+++ b/scripts/build_macOS.sh
@@ -22,7 +22,7 @@ function apply_patch {
 }
 
 cd skia && \
-    patch -p1 < ../patch/skia-m130-minimize-download.patch && \
+    patch -p1 < ../patch/skia-m131-minimize-download.patch && \
     patch -p1 < ../patch/skia-m123-colrv1-freetype.diff && \
     python3 tools/git-sync-deps && \
     bin/gn gen out/Release --args="
diff --git a/setup.py b/setup.py
index e4494234..ad7ede41 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@
     pass
 
 NAME = 'skia-python'
-__version__ = '130.0b10'
+__version__ = '131.0b10'
 
 SKIA_PATH = os.getenv('SKIA_PATH', 'skia')
 SKIA_OUT_PATH = os.getenv(
diff --git a/skia b/skia
index 0f81dc8b..f7f63e26 160000
--- a/skia
+++ b/skia
@@ -1,1 +1,1 @@
-Subproject commit 0f81dc8b2e43c060972a8d8d229b346694a674f8
+Subproject commit f7f63e2604e9d436f56daeaba55b103b578fc19e
diff --git a/src/skia/Document.cpp b/src/skia/Document.cpp
index 102cc10e..cdab79f7 100644
--- a/src/skia/Document.cpp
+++ b/src/skia/Document.cpp
@@ -216,8 +216,11 @@ py::class_<SkPDF::StructureElementNode>(pdf, "StructureElementNode",
     //     &SkPDF::StructureElementNode::fChildVector)
     .def_readwrite("fNodeId",
         &SkPDF::StructureElementNode::fNodeId)
+/* Removed in m131 */
+/*
     .def_readonly("fAdditionalNodeIds",
         &SkPDF::StructureElementNode::fAdditionalNodeIds)
+*/
     .def_readonly("fAttributes",
         &SkPDF::StructureElementNode::fAttributes)
     .def_readwrite("fAlt",
diff --git a/src/skia/GrContext.cpp b/src/skia/GrContext.cpp
index caaf7dd4..2c5e88fe 100644
--- a/src/skia/GrContext.cpp
+++ b/src/skia/GrContext.cpp
@@ -1,14 +1,14 @@
 #include "common.h"
 #include <include/core/SkTextureCompressionType.h>
-#include <include/gpu/GrBackendSemaphore.h>
-#include <include/gpu/GrBackendSurface.h>
-#include <include/gpu/GrContextThreadSafeProxy.h>
+#include <include/gpu/ganesh/GrBackendSemaphore.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
+#include <include/gpu/ganesh/GrContextThreadSafeProxy.h>
 #include <include/gpu/GpuTypes.h>
-#include <include/gpu/mock/GrMockTypes.h>
-#include <include/gpu/gl/GrGLInterface.h>
+#include <include/gpu/ganesh/mock/GrMockTypes.h>
+#include <include/gpu/ganesh/gl/GrGLInterface.h>
 #include <include/gpu/ganesh/gl/GrGLBackendSurface.h>
 #include <include/gpu/ganesh/gl/GrGLDirectContext.h>
-#include <include/gpu/vk/GrVkTypes.h>
+#include <include/gpu/ganesh/vk/GrVkTypes.h>
 #include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h>
 #include <include/gpu/ganesh/vk/GrVkBackendSurface.h>
 #include <include/gpu/ganesh/vk/GrVkDirectContext.h>
@@ -898,7 +898,7 @@ py::class_<GrDirectContext, sk_sp<GrDirectContext>, GrRecordingContext>(m, "GrDi
         )docstring",
         py::arg("info"))
     .def("flush", py::overload_cast<>(&GrDirectContext::flush))
-    .def("submit", &GrDirectContext::submit,
+    .def("submit", py::overload_cast<GrSyncCpu>(&GrDirectContext::submit),
         R"docstring(
         Submit outstanding work to the gpu from all previously un-submitted
         flushes. The return value of the submit will indicate whether or not the
diff --git a/src/skia/GrContext_gl.cpp b/src/skia/GrContext_gl.cpp
index 6024abea..b0413997 100644
--- a/src/skia/GrContext_gl.cpp
+++ b/src/skia/GrContext_gl.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
-#include <include/gpu/gl/GrGLTypes.h>
-#include <include/gpu/gl/GrGLInterface.h>
+#include <include/gpu/ganesh/gl/GrGLTypes.h>
+#include <include/gpu/ganesh/gl/GrGLInterface.h>
 
 void initGrContext_gl(py::module &m) {
 
diff --git a/src/skia/GrContext_mock.cpp b/src/skia/GrContext_mock.cpp
index 24d94a10..3b9f7307 100644
--- a/src/skia/GrContext_mock.cpp
+++ b/src/skia/GrContext_mock.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
-#include <include/gpu/mock/GrMockTypes.h>
-#include <include/gpu/GrBackendSurface.h>
+#include <include/gpu/ganesh/mock/GrMockTypes.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
 #include <include/core/SkTextureCompressionType.h>
 
 void initGrContext_mock(py::module &m) {
diff --git a/src/skia/GrContext_vk.cpp b/src/skia/GrContext_vk.cpp
index 7a0705bd..75bdaa21 100644
--- a/src/skia/GrContext_vk.cpp
+++ b/src/skia/GrContext_vk.cpp
@@ -1,6 +1,6 @@
 #include "common.h"
 #include <include/gpu/vk/VulkanBackendContext.h>
-#include <include/gpu/vk/GrVkTypes.h>
+#include <include/gpu/ganesh/vk/GrVkTypes.h>
 
 void initGrContext_vk(py::module &m) {
 
diff --git a/src/skia/Image.cpp b/src/skia/Image.cpp
index 13bb1c97..dbc2f1b2 100644
--- a/src/skia/Image.cpp
+++ b/src/skia/Image.cpp
@@ -1,7 +1,7 @@
 #include "common.h"
 #include <include/codec/SkEncodedImageFormat.h>
 #include <include/core/SkSamplingOptions.h>
-#include <include/gpu/GrBackendSurface.h>
+#include <include/gpu/ganesh/GrBackendSurface.h>
 #include <include/gpu/GpuTypes.h>
 #include <include/gpu/ganesh/SkImageGanesh.h>
 #include <include/encode/SkJpegEncoder.h>
diff --git a/src/skia/Shader.cpp b/src/skia/Shader.cpp
index e89f95b5..d1b37690 100644
--- a/src/skia/Shader.cpp
+++ b/src/skia/Shader.cpp
@@ -1,5 +1,4 @@
 #include "common.h"
-#include <include/effects/SkRuntimeEffect.h>
 #include <include/effects/SkGradientShader.h>
 #include <include/effects/SkPerlinNoiseShader.h>
 #include <include/effects/SkBlenders.h>
diff --git a/src/skia/Surface.cpp b/src/skia/Surface.cpp
index 7ecaf7e7..d4bbc026 100644
--- a/src/skia/Surface.cpp
+++ b/src/skia/Surface.cpp
@@ -3,7 +3,7 @@
 #include <include/gpu/ganesh/gl/GrGLBackendSurface.h>
 #include <include/private/chromium/GrSurfaceCharacterization.h>
 #include <include/gpu/GpuTypes.h>
-#include <include/gpu/GrTypes.h>
+#include <include/gpu/ganesh/GrTypes.h>
 #include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <include/gpu/MutableTextureState.h>
 #include <pybind11/operators.h>
diff --git a/src/skia/common.h b/src/skia/common.h
index d6f4d9d8..0cd21ab9 100644
--- a/src/skia/common.h
+++ b/src/skia/common.h
@@ -12,7 +12,7 @@
 #include <include/core/SkData.h>
 #include <include/core/SkDocument.h>
 #include <include/core/SkFont.h>
-#include <include/gpu/GrDirectContext.h>
+#include <include/gpu/ganesh/GrDirectContext.h>
 #include <include/core/SkImage.h>
 #include <include/core/SkImageFilter.h>
 #include <include/core/SkImageInfo.h>


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index a8b40518..0658d2ae 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -16,10 +16,11 @@ def glfw_context():
     glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
     glfw.window_hint(glfw.STENCIL_BITS, 8)
     # see https://www.glfw.org/faq#macos
-    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
-    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 2)
-    glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
-    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
+    if sys.platform.startswith("darwin"):
+        glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
+        glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 2)
+        glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
+        glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
     context = glfw.create_window(640, 480, '', None, None)
     glfw.make_context_current(context)
     logger.debug('glfw context created')
diff --git a/tests/test_font.py b/tests/test_font.py
index 2a220f98..bbecbd99 100644
--- a/tests/test_font.py
+++ b/tests/test_font.py
@@ -240,6 +240,17 @@ def svg_blob(svgface):
     blob = skia.TextBlob.MakeFromShapedText(text, font)
     return blob
 
+def test_svg_blob_1(svgface):
+    text = "abcdefgh"
+    font = skia.Font(svgface,109)
+    blob = skia.TextBlob.MakeFromText(text, font)
+    assert blob is not None
+
+def test_svg_blob_2(svgface):
+    text = "abcdefgh"
+    font = skia.Font(svgface,109)
+    blob = skia.TextBlob.MakeFromShapedText(text, font)
+    assert blob is not None
 
 # This test doesn't really test that the SVG table loads correctly -
 # Rather, it depends on the fact that, for this particular font,
@@ -418,6 +429,8 @@ def test_FontMgr_ref_unref(fontmgr):
 def font():
     return skia.Font(skia.Typeface(""))
 
+def test_font():
+    assert skia.Font(skia.Typeface("")) is not None
 
 @pytest.mark.parametrize('args', [
     tuple(),