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

Issue:
Missing `getBlendMode` on `skia.Paint` objects
There is a `setBlendMode` method on `Paint` objects, but no corresponding `getBlendMode`. Also, the `BlendMode` parameter to `skia.Paint` is not documented

**To Reproduce**
```
>>> skia.__version__
'119.0b4'
>>> skia.Paint().getBlendMode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'skia.Paint' object has no attribute 'getBlendMode'. Did you mean: 'setBlendMode'?
```
To see the documentation issues, search "blendmode" on this page: https://kyamagu.github.io/skia-python/reference/skia.Paint.html
Note that the `BlendMode` argument to the `skia.Paint` constructor works, but is not documented.

**Expected behavior**
Like in previous releases of `skia-python`, the `getBlendMode` function should exist and be documented.

**Desktop:**
 - OS: macOS 14.3.1
 - Python: 3.12
 - skia-python version: 119.0b4



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index fe6122f5..8bb7644d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,10 +13,10 @@ jobs:
     name: Build skia bundled 3rd-party on linux/aarch64
     runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           submodules: true
-      - uses: actions/cache@v3
+      - uses: actions/cache@v4
         id: cache-skia
         with:
           path: |
@@ -24,9 +24,9 @@ jobs:
             skia
           key: linux-aarch64-skia-${{ github.sha }}-3rd-party
       - name: Pre-fetch skia deps
-        run: git config --global core.compression 0 && cd skia && patch -p1 -i ../patch/skia-m121-minimize-download.patch && python tools/git-sync-deps && patch -p1 -R -i ../patch/skia-m121-minimize-download.patch
+        run: git config --global core.compression 0 && cd skia && patch -p1 -i ../patch/skia-m123-minimize-download.patch && python tools/git-sync-deps && patch -p1 -R -i ../patch/skia-m123-minimize-download.patch
       - name: Set up QEMU
-        uses: docker/setup-qemu-action@v2
+        uses: docker/setup-qemu-action@v3
       - name: Build skia 3rd-Party
         # Taken from https://github.com/pypa/cibuildwheel/blob/v2.16.2/cibuildwheel/resources/pinned_docker_images.cfg
         uses: docker://quay.io/pypa/manylinux2014_aarch64:2023-10-03-72cdc42
@@ -41,24 +41,24 @@ jobs:
     needs: prebuild_linux_aarch64_3rd_party
     runs-on: ubuntu-22.04
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           submodules: true
-      - uses: actions/cache@v3
+      - uses: actions/cache@v4
         id: cache-skia
         with:
           path: |
             gn
             skia
           key: linux-aarch64-skia-${{ github.sha }}
-      - uses: actions/cache/restore@v3
+      - uses: actions/cache/restore@v4
         with:
           path: |
             gn
             skia
           key: linux-aarch64-skia-${{ github.sha }}-3rd-party
       - name: Set up QEMU
-        uses: docker/setup-qemu-action@v2
+        uses: docker/setup-qemu-action@v3
       - name: Build Skia Proper
         uses: docker://quay.io/pypa/manylinux2014_aarch64:2023-10-03-72cdc42
         with:
@@ -100,11 +100,11 @@ jobs:
             cp: cp312
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
         with:
           submodules: true
 
-      - uses: actions/cache/restore@v3
+      - uses: actions/cache/restore@v4
         if: runner.os == 'Linux' && matrix.arch == 'aarch64'
         with:
           path: |
@@ -114,12 +114,12 @@ jobs:
 
       - name: Set up QEMU
         if: runner.os == 'Linux' && matrix.arch == 'aarch64'
-        uses: docker/setup-qemu-action@v2
+        uses: docker/setup-qemu-action@v3
         with:
           platforms: ${{ matrix.arch }}
 
       - name: Build wheels
-        uses: pypa/cibuildwheel@v2.16.2
+        uses: pypa/cibuildwheel@v2.16.5
         env:
           CIBW_BUILD: "${{ matrix.cp }}-*"
           CIBW_SKIP: "*musllinux*"
@@ -144,7 +144,7 @@ jobs:
     needs: [build_wheels]
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - uses: actions/setup-python@v4
         name: Install Python
diff --git a/patch/skia-m122-colrv1-freetype.diff b/patch/skia-m122-colrv1-freetype.diff
new file mode 100644
index 00000000..a6232503
--- /dev/null
+++ b/patch/skia-m122-colrv1-freetype.diff
@@ -0,0 +1,119 @@
+diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
+index 7e096a6..46fe7a0 100644
+--- a/src/ports/SkFontHost_FreeType.cpp
++++ b/src/ports/SkFontHost_FreeType.cpp
+@@ -33,7 +33,6 @@
+ #include "src/core/SkMask.h"
+ #include "src/core/SkMaskGamma.h"
+ #include "src/core/SkScalerContext.h"
+-#include "src/ports/SkFontHost_FreeType_common.h"
+ #include "src/ports/SkTypeface_FreeType.h"
+ #include "src/sfnt/SkOTUtils.h"
+ #include "src/sfnt/SkSFNTHeader.h"
+@@ -52,6 +51,7 @@
+ #ifdef FT_COLOR_H  // 2.10.0
+ #   include <freetype/ftcolor.h>
+ #endif
++#include "src/ports/SkFontHost_FreeType_common.h"
+ #include <freetype/freetype.h>
+ #include <freetype/ftlcdfil.h>
+ #include <freetype/ftmodapi.h>
+diff --git a/src/ports/SkFontHost_FreeType_common.cpp b/src/ports/SkFontHost_FreeType_common.cpp
+index 14b2adb..f041583 100644
+--- a/src/ports/SkFontHost_FreeType_common.cpp
++++ b/src/ports/SkFontHost_FreeType_common.cpp
+@@ -6,7 +6,6 @@
+  * found in the LICENSE file.
+  */
+ 
+-#include "src/ports/SkFontHost_FreeType_common.h"
+ 
+ #include "include/core/SkBitmap.h"
+ #include "include/core/SkCanvas.h"
+@@ -32,6 +31,7 @@
+ #ifdef FT_COLOR_H
+ #   include <freetype/ftcolor.h>
+ #endif
++#include "src/ports/SkFontHost_FreeType_common.h"
+ #include <freetype/ftimage.h>
+ #include <freetype/ftoutln.h>
+ #include <freetype/ftsizes.h>
+@@ -1574,6 +1574,41 @@ bool SkScalerContext_FreeType_Base::drawCOLRv1Glyph(FT_Face face,
+     SkASSERTF(haveLayers, "Could not get COLRv1 layers from '%s'.", face->family_name);
+     return haveLayers;
+ }
++/*
++ * This content is mostly just
++ *       SkTypeface_FreeType::FaceRec::setupPalette()
++ +     + SkScalerContext_FreeType_Base::drawCOLRv1Glyph()
++ +*/
++bool SkScalerContext_FreeType_Base::skia_colrv1_start_glyph(SkCanvas* canvas,
++                                    FT_Face face,
++                                    uint16_t glyphId,
++                                    FT_UShort palette_index,
++                                    FT_Color_Root_Transform rootTransform
++                                    ) {
++    uint32_t fForegroundColor{SK_ColorBLACK};
++    FT_Palette_Data paletteData;
++    FT_Palette_Data_Get(face, &paletteData);
++
++    FT_Color* ftPalette = nullptr;
++    FT_Palette_Select(face, palette_index, &ftPalette);
++    std::unique_ptr<SkColor[]> ptr_palette(new SkColor[paletteData.num_palette_entries]);
++    for (int i = 0; i < paletteData.num_palette_entries; ++i) {
++      ptr_palette[i] = SkColorSetARGB(ftPalette[i].alpha,
++                                  ftPalette[i].red,
++                                  ftPalette[i].green,
++                                  ftPalette[i].blue);
++    }
++    SkSpan<SkColor> palette(ptr_palette.get(), paletteData.num_palette_entries);
++
++    VisitedSet activePaints;
++    bool haveLayers =  colrv1_start_glyph(canvas, palette,
++                                          fForegroundColor, // FT_Palette_Get_Foreground_Color?
++                                          face, glyphId,
++                                          FT_COLOR_INCLUDE_ROOT_TRANSFORM,
++                                          &activePaints);
++    SkASSERTF(haveLayers, "Could not get COLRv1 layers from '%s'.", face->family_name);
++    return haveLayers;
++}
+ #endif  // TT_SUPPORT_COLRV1
+ 
+ #ifdef FT_COLOR_H
+diff --git a/src/ports/SkFontHost_FreeType_common.h b/src/ports/SkFontHost_FreeType_common.h
+index d649784..1100b0e 100644
+--- a/src/ports/SkFontHost_FreeType_common.h
++++ b/src/ports/SkFontHost_FreeType_common.h
+@@ -19,6 +19,7 @@
+ typedef struct FT_FaceRec_* FT_Face;
+ typedef struct FT_StreamRec_* FT_Stream;
+ typedef signed long FT_Pos;
++typedef unsigned short  FT_UShort; /* freetype/fttypes.h */
+ 
+ 
+ #ifdef SK_DEBUG
+@@ -31,7 +32,15 @@ const char* SkTraceFtrGetError(int);
+ #endif
+ 
+ 
+-class SkScalerContext_FreeType_Base : public SkScalerContext {
++class SK_SPI SkScalerContext_FreeType_Base : public SkScalerContext {
++public:
++    static bool computeColrV1GlyphBoundingBox(FT_Face, SkGlyphID, SkRect* bounds);
++    static bool skia_colrv1_start_glyph(SkCanvas* canvas,
++                                        FT_Face face,
++                                        uint16_t glyphId,
++                                        FT_UShort palette_index,
++                                        FT_Color_Root_Transform rootTransform
++                                        );
+ protected:
+     // See http://freetype.sourceforge.net/freetype2/docs/reference/ft2-bitmap_handling.html#FT_Bitmap_Embolden
+     // This value was chosen by eyeballing the result in Firefox and trying to match it.
+@@ -57,7 +66,6 @@ protected:
+      *  configure size, matrix and load glyphs as needed after using this function to restore the
+      *  state of FT_Face.
+      */
+-    static bool computeColrV1GlyphBoundingBox(FT_Face, SkGlyphID, SkRect* bounds);
+ 
+     struct ScalerContextBits {
+         static const constexpr uint32_t COLRv0 = 1;
diff --git a/patch/skia-m122-minimize-download.patch b/patch/skia-m122-minimize-download.patch
new file mode 100644
index 00000000..9b207a33
--- /dev/null
+++ b/patch/skia-m122-minimize-download.patch
@@ -0,0 +1,70 @@
+diff --git a/DEPS b/DEPS
+index bd7ed9d..8180821 100644
+--- a/DEPS
++++ b/DEPS
+@@ -23,53 +23,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@c6fbf93decbac74cd14c6ca3d600d4ed91d1179d",
+-  "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@5b45794c2c24c3fa40dc480af92c5284a95423ef",
+-  "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@334aca32051ef6ede2711487acf45d959e9bdffc",
+   "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@441f98d02deafd9b090aea568282b28f66a50e36",
+   "third_party/externals/freetype"               : "https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@45903920b984540bb629bc89f4c010159c23a89a",
+   "third_party/externals/harfbuzz"               : "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@4cfc6d8e173e800df086d7be078da2e8c5cfca19",
+-  "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@a0718d4f121727e30b8d52c7a189ebf5ab52421f",
+-  "third_party/externals/icu4x"                  : "https://chromium.googlesource.com/external/github.com/unicode-org/icu4x.git@4f81635489681ecf7707623177123cb78d6a66a0",
+-  "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@ed683925e4897a84b3bffc5c1414c85b97a129a3",
+-  "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@386707c6d19b974ca2e3db7f5c61873813c6fe44",
+   "third_party/externals/libwebp"                : "https://chromium.googlesource.com/webm/libwebp.git@2af26267cdfcb63a88e5c74a85927a12d6ca1d76",
+-  "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/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/sfntly"                 : "https://chromium.googlesource.com/external/github.com/googlei18n/sfntly.git@b55ff303ea2f9e26702b514cf6a3196a2e3e2974",
+-  "third_party/externals/swiftshader"            : "https://swiftshader.googlesource.com/SwiftShader@328e794f0c8bddc81c834ccc89c9652902f643cb",
+   "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@4307b0183c9e16bc920ef0bceaa9e9d630c352c3",
+-  "third_party/externals/spirv-cross"            : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@b82536766d1b81631b126d1ddbe49baf42929bd3",
+-  "third_party/externals/spirv-headers"          : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@7b0309708da5126b89e4ce6f19835f36dc912f2f",
+-  "third_party/externals/spirv-tools"            : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@3e6bdd0f99655b1bc6a54aa73e5bfaaa4252198b",
+-  "third_party/externals/vello"                  : "https://skia.googlesource.com/external/github.com/linebender/vello.git@ee3a076b291d206c361431cc841407adf265c692",
+   "third_party/externals/vulkan-headers"         : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Headers@217e93c664ec6704ec2d8c36fa116c1a4a1e2d40",
+-  "third_party/externals/vulkan-tools"           : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Tools@7c6d640a5ca3ab73c1f42d22312f672b54babfaf",
+-  "third_party/externals/vulkan-utility-libraries": "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@4cfc176e3242b4dbdfd3f6c5680c5d8f2cb7db45",
+-  "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@c876c8f87101c5a75f6014b0f832499afeb65b73",
+ 
+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/patch/skia-m123-colrv1-freetype.diff b/patch/skia-m123-colrv1-freetype.diff
new file mode 100644
index 00000000..6d051d3b
--- /dev/null
+++ b/patch/skia-m123-colrv1-freetype.diff
@@ -0,0 +1,109 @@
+diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
+index 0b81565..9163883 100644
+--- a/src/ports/SkFontHost_FreeType.cpp
++++ b/src/ports/SkFontHost_FreeType.cpp
+@@ -33,7 +33,6 @@
+ #include "src/core/SkMask.h"
+ #include "src/core/SkMaskGamma.h"
+ #include "src/core/SkScalerContext.h"
+-#include "src/ports/SkFontHost_FreeType_common.h"
+ #include "src/ports/SkTypeface_FreeType.h"
+ #include "src/sfnt/SkOTUtils.h"
+ #include "src/sfnt/SkSFNTHeader.h"
+@@ -52,6 +51,7 @@
+ #ifdef FT_COLOR_H  // 2.10.0
+ #   include <freetype/ftcolor.h>
+ #endif
++#include "src/ports/SkFontHost_FreeType_common.h"
+ #include <freetype/freetype.h>
+ #include <freetype/ftlcdfil.h>
+ #include <freetype/ftmodapi.h>
+diff --git a/src/ports/SkFontHost_FreeType_common.cpp b/src/ports/SkFontHost_FreeType_common.cpp
+index 050a127..8b98adc 100644
+--- a/src/ports/SkFontHost_FreeType_common.cpp
++++ b/src/ports/SkFontHost_FreeType_common.cpp
+@@ -6,7 +6,6 @@
+  * found in the LICENSE file.
+  */
+ 
+-#include "src/ports/SkFontHost_FreeType_common.h"
+ 
+ #include "include/core/SkBitmap.h"
+ #include "include/core/SkCanvas.h"
+@@ -32,6 +31,7 @@
+ #ifdef FT_COLOR_H
+ #   include <freetype/ftcolor.h>
+ #endif
++#include "src/ports/SkFontHost_FreeType_common.h"
+ #include <freetype/ftimage.h>
+ #include <freetype/ftoutln.h>
+ #include <freetype/ftsizes.h>
+@@ -1577,6 +1577,41 @@ bool SkScalerContextFTUtils::drawCOLRv1Glyph(FT_Face face, const SkGlyph& glyph,
+     SkASSERTF(haveLayers, "Could not get COLRv1 layers from '%s'.", face->family_name);
+     return haveLayers;
+ }
++/*
++ * This content is mostly just
++ *       SkTypeface_FreeType::FaceRec::setupPalette()
++ +     + SkScalerContext_FreeType_Base::drawCOLRv1Glyph()
++ +*/
++bool SkScalerContextFTUtils::skia_colrv1_start_glyph(SkCanvas* canvas,
++                                    FT_Face face,
++                                    uint16_t glyphId,
++                                    FT_UShort palette_index,
++                                    FT_Color_Root_Transform rootTransform
++                                    ) {
++    uint32_t fForegroundColor{SK_ColorBLACK};
++    FT_Palette_Data paletteData;
++    FT_Palette_Data_Get(face, &paletteData);
++
++    FT_Color* ftPalette = nullptr;
++    FT_Palette_Select(face, palette_index, &ftPalette);
++    std::unique_ptr<SkColor[]> ptr_palette(new SkColor[paletteData.num_palette_entries]);
++    for (int i = 0; i < paletteData.num_palette_entries; ++i) {
++      ptr_palette[i] = SkColorSetARGB(ftPalette[i].alpha,
++                                  ftPalette[i].red,
++                                  ftPalette[i].green,
++                                  ftPalette[i].blue);
++    }
++    SkSpan<SkColor> palette(ptr_palette.get(), paletteData.num_palette_entries);
++
++    VisitedSet activePaints;
++    bool haveLayers =  colrv1_start_glyph(canvas, palette,
++                                          fForegroundColor, // FT_Palette_Get_Foreground_Color?
++                                          face, glyphId,
++                                          FT_COLOR_INCLUDE_ROOT_TRANSFORM,
++                                          &activePaints);
++    SkASSERTF(haveLayers, "Could not get COLRv1 layers from '%s'.", face->family_name);
++    return haveLayers;
++}
+ #endif  // TT_SUPPORT_COLRV1
+ 
+ #ifdef FT_COLOR_H
+diff --git a/src/ports/SkFontHost_FreeType_common.h b/src/ports/SkFontHost_FreeType_common.h
+index 444811e..d88433c 100644
+--- a/src/ports/SkFontHost_FreeType_common.h
++++ b/src/ports/SkFontHost_FreeType_common.h
+@@ -20,6 +20,7 @@ class SkCanvas;
+ // These are forward declared to avoid pimpl but also hide the FreeType implementation.
+ typedef struct FT_FaceRec_* FT_Face;
+ typedef signed long FT_Pos;
++typedef unsigned short  FT_UShort; /* freetype/fttypes.h */
+ 
+ 
+ #ifdef SK_DEBUG
+@@ -31,7 +32,13 @@ const char* SkTraceFtrGetError(int);
+ #define SK_TRACEFTR(ERR, ...) do { sk_ignore_unused_variable(ERR); } while (false)
+ #endif
+ 
+-struct SkScalerContextFTUtils {
++struct SK_SPI SkScalerContextFTUtils {
++    static bool skia_colrv1_start_glyph(SkCanvas* canvas,
++                                        FT_Face face,
++                                        uint16_t glyphId,
++                                        FT_UShort palette_index,
++                                        FT_Color_Root_Transform rootTransform
++                                        );
+     SkColor                 fForegroundColor;
+     SkScalerContext::Flags  fFlags;
+ 
diff --git a/patch/skia-m123-minimize-download.patch b/patch/skia-m123-minimize-download.patch
new file mode 100644
index 00000000..dec3706b
--- /dev/null
+++ b/patch/skia-m123-minimize-download.patch
@@ -0,0 +1,70 @@
+diff --git a/DEPS b/DEPS
+index fa09db3..7277713 100644
+--- a/DEPS
++++ b/DEPS
+@@ -23,53 +23,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@e04b7c7392d9d05907db6d453c8b8e577d306a7e",
+-  "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@d3e0bd4770cc8115d1342a8dc051a36e50e8bd26",
+-  "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@334aca32051ef6ede2711487acf45d959e9bdffc",
+   "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@441f98d02deafd9b090aea568282b28f66a50e36",
+   "third_party/externals/freetype"               : "https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@47574f7ea445c8bb751da0fa716424c9c29a6807",
+   "third_party/externals/harfbuzz"               : "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@4cfc6d8e173e800df086d7be078da2e8c5cfca19",
+-  "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@a0718d4f121727e30b8d52c7a189ebf5ab52421f",
+-  "third_party/externals/icu4x"                  : "https://chromium.googlesource.com/external/github.com/unicode-org/icu4x.git@4f81635489681ecf7707623177123cb78d6a66a0",
+-  "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@ed683925e4897a84b3bffc5c1414c85b97a129a3",
+-  "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@144b348e072a78e8130ed0acc452c9f039a67bf2",
+   "third_party/externals/libwebp"                : "https://chromium.googlesource.com/webm/libwebp.git@2af26267cdfcb63a88e5c74a85927a12d6ca1d76",
+-  "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/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/sfntly"                 : "https://chromium.googlesource.com/external/github.com/googlei18n/sfntly.git@b55ff303ea2f9e26702b514cf6a3196a2e3e2974",
+-  "third_party/externals/swiftshader"            : "https://swiftshader.googlesource.com/SwiftShader@eb75201a4e0354a36d315dd01077092ec9aa2356",
+   "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@13783d616289ab4ff6cad96e570d04183b24f2e0",
+-  "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@05cc486580771e4fa7ddc89f5c9ee1e97382689a",
+-  "third_party/externals/spirv-tools"            : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@dc6676445be97ab19d8191fee019af62e2aaf774",
+-  "third_party/externals/vello"                  : "https://skia.googlesource.com/external/github.com/linebender/vello.git@e04b6028651dfd6b87067c0d27c1207c7f735a6d",
+   "third_party/externals/vulkan-headers"         : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Headers@31aa7f634b052d87ede4664053e85f3f4d1d50d3",
+-  "third_party/externals/vulkan-tools"           : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Tools@069bd14c0548556e130fc9e205adc918b7a01891",
+-  "third_party/externals/vulkan-utility-libraries": "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@1b8b60bf7f271a09eeda032d117d51a43ed506cd",
+-  "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 207df70a..548f76d6 100644
--- a/scripts/build_Linux.sh
+++ b/scripts/build_Linux.sh
@@ -60,8 +60,8 @@ git clone https://gn.googlesource.com/gn && \
 
 # Build skia
 cd skia && \
-    patch -p1 < ../patch/skia-m121-minimize-download.patch && \
-    patch -p1 < ../patch/skia-m121-colrv1-freetype.diff && \
+    patch -p1 < ../patch/skia-m123-minimize-download.patch && \
+    patch -p1 < ../patch/skia-m123-colrv1-freetype.diff && \
     python3 tools/git-sync-deps && \
     cp -f ../gn/out/gn bin/gn && \
     bin/gn gen out/Release --args="
diff --git a/scripts/build_Windows.sh b/scripts/build_Windows.sh
index b4808480..814a8bc9 100644
--- a/scripts/build_Windows.sh
+++ b/scripts/build_Windows.sh
@@ -4,8 +4,8 @@ export PATH="${PWD}/depot_tools:$PATH"
 
 # Build skia
 cd skia && \
-    patch -p1 < ../patch/skia-m121-minimize-download.patch && \
-    patch -p1 < ../patch/skia-m121-colrv1-freetype.diff && \
+    patch -p1 < ../patch/skia-m123-minimize-download.patch && \
+    patch -p1 < ../patch/skia-m123-colrv1-freetype.diff && \
     python tools/git-sync-deps && \
     bin/gn gen out/Release --args='
 is_official_build=true
diff --git a/scripts/build_macOS.sh b/scripts/build_macOS.sh
index 404f7b2c..afe18144 100644
--- a/scripts/build_macOS.sh
+++ b/scripts/build_macOS.sh
@@ -22,8 +22,8 @@ function apply_patch {
 }
 
 cd skia && \
-    patch -p1 < ../patch/skia-m121-minimize-download.patch && \
-    patch -p1 < ../patch/skia-m121-colrv1-freetype.diff && \
+    patch -p1 < ../patch/skia-m123-minimize-download.patch && \
+    patch -p1 < ../patch/skia-m123-colrv1-freetype.diff && \
     python3 tools/git-sync-deps && \
     bin/gn gen out/Release --args="
 is_official_build=true
diff --git a/setup.py b/setup.py
index 94796253..7e615a56 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@
     pass
 
 NAME = 'skia-python'
-__version__ = '121.0b6'
+__version__ = '123.0b6'
 
 SKIA_PATH = os.getenv('SKIA_PATH', 'skia')
 SKIA_OUT_PATH = os.getenv(
diff --git a/skia b/skia
index 589c4655..3d4e4590 160000
--- a/skia
+++ b/skia
@@ -1,1 +1,1 @@
-Subproject commit 589c46555055ec23bcc4634c209f7f543f6b424c
+Subproject commit 3d4e45907f9b239a54957001d619d2d4a6ca06b4
diff --git a/src/skia/Font.cpp b/src/skia/Font.cpp
index f281f210..dcbb9a50 100644
--- a/src/skia/Font.cpp
+++ b/src/skia/Font.cpp
@@ -10,6 +10,48 @@
 #include <src/ports/SkFontHost_FreeType_common.h>
 #endif
 
+#ifdef __APPLE__
+#include "include/ports/SkFontMgr_mac_ct.h"
+#endif
+
+#ifdef __linux__
+#include "include/ports/SkFontMgr_fontconfig.h"
+#endif
+
+#ifdef _WIN32
+#include "include/ports/SkTypeface_win.h"
+#endif
+
+#include <mutex>
+
+namespace {
+
+bool g_factory_called = false;
+
+}  // namespace
+
+static sk_sp<SkFontMgr> fontmgr_factory() {
+#if defined(__APPLE__)
+  return SkFontMgr_New_CoreText(nullptr);
+#elif defined(__linux__)
+  return SkFontMgr_New_FontConfig(nullptr);
+#elif defined(_WIN32)
+  return SkFontMgr_New_DirectWrite();
+#else
+  return SkFontMgr_New_Custom_Empty(); /* last resort: SkFontMgr::RefEmpty(); */
+#endif
+}
+
+sk_sp<SkFontMgr> SkFontMgr_RefDefault() {
+  static std::once_flag flag;
+  static sk_sp<SkFontMgr> mgr;
+  std::call_once(flag, [] {
+    mgr = fontmgr_factory();
+    g_factory_called = true;
+  });
+  return mgr;
+}
+
 using Axis = SkFontParameters::Variation::Axis;
 using Coordinate = SkFontArguments::VariationPosition::Coordinate;
 PYBIND11_MAKE_OPAQUE(std::vector<Coordinate>);
@@ -44,7 +86,7 @@ py::str SkFontMgr_getFamilyName(const SkFontMgr& fontmgr, int index) {
 sk_sp<SkTypeface> SkTypeface_MakeFromName(
     py::object familyName,
     const SkFontStyle* fontStyle) {
-    return SkTypeface::MakeFromName(
+    return SkFontMgr_RefDefault()->legacyMakeTypeface(
         (familyName.is_none()) ?
             nullptr : familyName.cast<std::string>().c_str(),
         (fontStyle) ? *fontStyle : SkFontStyle());
@@ -266,7 +308,7 @@ typeface
             warnings.attr("warn")(
                 "\"Default typeface\" is deprecated upstream. Please specify name/file/style choices.",
                 builtins.attr("DeprecationWarning"));
-            return SkFontMgr::RefDefault()->legacyMakeTypeface("", SkFontStyle());
+            return SkFontMgr_RefDefault()->legacyMakeTypeface("", SkFontStyle());
         }),
         R"docstring(
         Returns the default normal typeface.
@@ -571,7 +613,7 @@ typeface
             warnings.attr("warn")(
                 "\"Default typeface\" is deprecated upstream. Please specify name/file/style choices.",
                 builtins.attr("DeprecationWarning"));
-            return SkFontMgr::RefDefault()->legacyMakeTypeface("", SkFontStyle());
+            return SkFontMgr_RefDefault()->legacyMakeTypeface("", SkFontStyle());
         },
         R"docstring(
         Returns the default normal typeface, which is never nullptr.
@@ -595,7 +637,7 @@ typeface
         py::arg("familyName"), py::arg("fontStyle") = nullptr)
     .def_static("MakeFromFile",
         [] (const std::string& path, int index) {
-            return SkTypeface::MakeFromFile(&path[0], index);
+            return SkFontMgr_RefDefault()->makeFromFile(&path[0], index);
         },
         R"docstring(
         Return a new typeface given a file.
@@ -606,7 +648,10 @@ typeface
         py::arg("path"), py::arg("index") = 0)
     // .def_static("MakeFromStream", &SkTypeface::MakeFromStream,
     //     "Return a new typeface given a stream.")
-    .def_static("MakeFromData", &SkTypeface::MakeFromData,
+    .def_static("MakeFromData",
+        [] (sk_sp<SkData> data, int index) {
+            return SkFontMgr_RefDefault()->makeFromData(data, index);
+        },
         R"docstring(
         Return a new typeface given a :py:class:`Data`.
 
@@ -618,9 +663,9 @@ typeface
     // .def_static("MakeFromFontData", &SkTypeface::MakeFromFontData,
     //     "Return a new typeface given font data and configuration.")
     .def_static("MakeDeserialize",
-        [] (const sk_sp<SkData>& data) {
+        [] (const sk_sp<SkData>& data, sk_sp<SkFontMgr> lastResortMgr) {
             SkMemoryStream stream(data);
-            return SkTypeface::MakeDeserialize(&stream);
+            return SkTypeface::MakeDeserialize(&stream, lastResortMgr);
         },
         R"docstring(
         Given the data previously written by :py:meth:`serialize`, return a new
@@ -628,7 +673,7 @@ typeface
 
         If that font is not available, return nullptr.
         )docstring",
-        py::arg("dats"))
+        py::arg("dats"), py::arg("lastResortMgr"))
     ;
 
 // FontMgr
@@ -660,7 +705,7 @@ py::class_<SkFontMgr, sk_sp<SkFontMgr>, SkRefCnt>(m, "FontMgr",
         assert typeface is not None
 
     )docstring")
-    .def(py::init([] () { return SkFontMgr::RefDefault(); }))
+    .def(py::init([] () { return SkFontMgr_RefDefault(); }))
     .def_static("New_Custom_Empty", &SkFontMgr_New_Custom_Empty)
     .def("__getitem__", &SkFontMgr_getFamilyName, py::arg("index"))
     .def("__len__", &SkFontMgr::countFamilies)
@@ -765,7 +810,7 @@ py::class_<SkFontMgr, sk_sp<SkFontMgr>, SkRefCnt>(m, "FontMgr",
             return fontmgr.legacyMakeTypeface(familyName.c_str(), style);
         },
         py::arg("familyName"), py::arg("style"))
-    .def_static("RefDefault", &SkFontMgr::RefDefault,
+    .def_static("RefDefault", &SkFontMgr_RefDefault,
         R"docstring(
         Return the default fontmgr.
         )docstring")
@@ -814,7 +859,7 @@ font
             warnings.attr("warn")(
                 "\"Default font\" is deprecated upstream. Please specify name/file/style choices.",
                 builtins.attr("DeprecationWarning"));
-            return SkFont(SkFontMgr::RefDefault()->legacyMakeTypeface("", SkFontStyle()));
+            return SkFont(SkFontMgr_RefDefault()->legacyMakeTypeface("", SkFontStyle()));
         }),
         R"docstring(
         Constructs :py:class:`Font` with default values.
@@ -827,7 +872,7 @@ font
                 warnings.attr("warn")(
                     "\"Default font\" is deprecated upstream. Please specify name/file/style choices.",
                     builtins.attr("DeprecationWarning"));
-                return SkFont(SkFontMgr::RefDefault()->legacyMakeTypeface("", SkFontStyle()), size);
+                return SkFont(SkFontMgr_RefDefault()->legacyMakeTypeface("", SkFontStyle()), size);
             } else {
                 return SkFont(typeface.cast<sk_sp<SkTypeface>>(), size);
             }
@@ -849,7 +894,7 @@ font
                 warnings.attr("warn")(
                     "\"Default font\" is deprecated upstream. Please specify name/file/style choices.",
                     builtins.attr("DeprecationWarning"));
-                return SkFont(SkFontMgr::RefDefault()->legacyMakeTypeface("", SkFontStyle()));
+                return SkFont(SkFontMgr_RefDefault()->legacyMakeTypeface("", SkFontStyle()));
             } else {
                 return SkFont(typeface.cast<sk_sp<SkTypeface>>());
             }
@@ -870,7 +915,7 @@ font
                 warnings.attr("warn")(
                     "\"Default font\" is deprecated upstream. Please specify name/file/style choices.",
                     builtins.attr("DeprecationWarning"));
-                return SkFont(SkFontMgr::RefDefault()->legacyMakeTypeface("", SkFontStyle()),
+                return SkFont(SkFontMgr_RefDefault()->legacyMakeTypeface("", SkFontStyle()),
                                       size, scaleX, skewX);
             } else {
                 return SkFont(typeface.cast<sk_sp<SkTypeface>>(),
diff --git a/src/skia/Paint.cpp b/src/skia/Paint.cpp
index 88a68833..d40d1eb0 100644
--- a/src/skia/Paint.cpp
+++ b/src/skia/Paint.cpp
@@ -543,8 +543,10 @@ paint
             subsequent draw
         )docstring",
         py::arg("colorFilter"))
-/*
-    .def("getBlendMode", &SkPaint::getBlendMode,
+    .def("getBlendMode",
+        [] (SkPaint& paint) {
+            return paint.getBlendMode_or(SkBlendMode::kSrcOver);
+        },
         R"docstring(
         Returns :py:class:`BlendMode`.
 
@@ -552,7 +554,6 @@ paint
 
         :return: mode used to combine source color with destination color
         )docstring")
-*/
     .def("isSrcOver", &SkPaint::isSrcOver,
         R"docstring(
         Returns true if :py:class:`BlendMode` is :py:attr:`BlendMode.kSrcOver`,


Test patch:
diff --git a/tests/test_font.py b/tests/test_font.py
index 12d03501..368ac1bd 100644
--- a/tests/test_font.py
+++ b/tests/test_font.py
@@ -219,9 +219,9 @@ def test_Typeface_MakeFromData(typeface, args):
         skia.Typeface.MakeFromData(*args), (skia.Typeface, type(None)))
 
 
-def test_Typeface_MakeDeserialize(typeface):
+def test_Typeface_MakeDeserialize(typeface, fontmgr):
     assert isinstance(
-        skia.Typeface.MakeDeserialize(typeface.serialize()), skia.Typeface)
+        skia.Typeface.MakeDeserialize(typeface.serialize(), fontmgr), skia.Typeface)
 
 
 @pytest.fixture
diff --git a/tests/test_paint.py b/tests/test_paint.py
index 677420ea..36a58139 100644
--- a/tests/test_paint.py
+++ b/tests/test_paint.py
@@ -181,7 +181,6 @@ def test_Paint_setColorFilter(paint):
     paint.setColorFilter(skia.LumaColorFilter.Make())
 
 
-@pytest.mark.skip(reason='m116:REVISIT')
 def test_Paint_getBlendMode(paint):
     assert isinstance(paint.getBlendMode(), skia.BlendMode)