Skip to content

Commit 1ae9cb0

Browse files
committed
fix: 1.1.x iOS crash and icon watermark not shown correctly
1 parent 10d71e1 commit 1ae9cb0

File tree

5 files changed

+245
-50
lines changed

5 files changed

+245
-50
lines changed

example/ios/Podfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ PODS:
331331
- glog
332332
- react-native-blob-util (0.19.6):
333333
- React-Core
334-
- react-native-image-marker (1.1.10):
334+
- react-native-image-marker (1.1.11):
335335
- React-Core
336336
- react-native-image-picker (5.7.0):
337337
- React-Core
@@ -583,7 +583,7 @@ EXTERNAL SOURCES:
583583
:path: "../node_modules/react-native/ReactCommon/yoga"
584584

585585
SPEC CHECKSUMS:
586-
boost: 57d2868c099736d80fcd648bf211b4431e51a558
586+
boost: 64032b9e9b938fda23325e68a3771f0fabf414dc
587587
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
588588
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
589589
FBLazyVector: c511d4cd0210f416cb5c289bd5ae6b36d909b048
@@ -617,7 +617,7 @@ SPEC CHECKSUMS:
617617
React-jsinspector: b6ed4cb3ffa27a041cd440300503dc512b761450
618618
React-logger: 186dd536128ae5924bc38ed70932c00aa740cd5b
619619
react-native-blob-util: d8fa1a7f726867907a8e43163fdd8b441d4489ea
620-
react-native-image-marker: 4414050c15944297bc24b3a37a1070d951fb57a2
620+
react-native-image-marker: d58c3e046b75e3302fd4f365cd7c32051badfef2
621621
react-native-image-picker: 3269f75c251cdcd61ab51b911dd30d6fff8c6169
622622
React-perflogger: e706562ab7eb8eb590aa83a224d26fa13963d7f2
623623
React-RCTActionSheet: 57d4bd98122f557479a3359ad5dad8e109e20c5a
@@ -638,4 +638,4 @@ SPEC CHECKSUMS:
638638

639639
PODFILE CHECKSUM: 4420d5a35a7e9d1bc71140c63c7e29db0be4fdf7
640640

641-
COCOAPODS: 1.12.1
641+
COCOAPODS: 1.14.3

example/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"android": "react-native run-android",
77
"ios": "react-native run-ios",
88
"start": "react-native start",
9-
"pods": "pod-install --quiet"
9+
"pods": "pod-install",
10+
"postinstall": "patch-package"
1011
},
1112
"dependencies": {
1213
"@expo/react-native-action-sheet": "^4.0.1",
@@ -23,6 +24,8 @@
2324
"@babel/preset-env": "^7.20.0",
2425
"@babel/runtime": "^7.20.0",
2526
"babel-plugin-module-resolver": "^4.1.0",
26-
"metro-react-native-babel-preset": "0.73.10"
27+
"metro-react-native-babel-preset": "0.73.10",
28+
"patch-package": "^8.0.0",
29+
"postinstall-postinstall": "^2.1.0"
2730
}
2831
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
diff --git a/node_modules/react-native/sdks/hermes/hermes-engine.podspec b/node_modules/react-native/sdks/hermes/hermes-engine.podspec
2+
new file mode 100644
3+
index 0000000..b800547
4+
--- /dev/null
5+
+++ b/node_modules/react-native/sdks/hermes/hermes-engine.podspec
6+
@@ -0,0 +1,143 @@
7+
+# Copyright (c) Meta Platforms, Inc. and affiliates.
8+
+#
9+
+# This source code is licensed under the MIT license found in the
10+
+# LICENSE file in the root directory of this source tree.
11+
+
12+
+require "json"
13+
+require_relative "./hermes-utils.rb"
14+
+
15+
+react_native_path = File.join(__dir__, "..", "..")
16+
+
17+
+# Whether Hermes is built for Release or Debug is determined by the PRODUCTION envvar.
18+
+build_type = ENV['PRODUCTION'] == "1" ? :release : :debug
19+
+
20+
+# package.json
21+
+package = JSON.parse(File.read(File.join(react_native_path, "package.json")))
22+
+version = package['version']
23+
+
24+
+# sdks/.hermesversion
25+
+hermestag_file = File.join(react_native_path, "sdks", ".hermesversion")
26+
+isInCI = ENV['REACT_NATIVE_CI'] === 'true'
27+
+
28+
+source = {}
29+
+git = "https://github.com/facebook/hermes.git"
30+
+
31+
+isInMain = version.include?('1000.0.0')
32+
+isNightly = version.start_with?('0.0.0-')
33+
+
34+
+if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH')
35+
+ if !File.exist?(ENV['HERMES_ENGINE_TARBALL_PATH'])
36+
+ abort "[Hermes] HERMES_ENGINE_TARBALL_PATH is set, but points to a non-existing file: \"#{ENV['HERMES_ENGINE_TARBALL_PATH']}\"\nIf you don't want to use tarball, run `unset HERMES_ENGINE_TARBALL_PATH`"
37+
+ end
38+
+end
39+
+
40+
+if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH')
41+
+ Pod::UI.puts "[Hermes] Using pre-built Hermes binaries from local path: #{ENV['HERMES_ENGINE_TARBALL_PATH']}".yellow if Object.const_defined?("Pod::UI")
42+
+ source[:http] = "file://#{ENV['HERMES_ENGINE_TARBALL_PATH']}"
43+
+elsif isInMain
44+
+ Pod::UI.puts '[Hermes] Installing hermes-engine may take slightly longer, building Hermes compiler from source...'.yellow if Object.const_defined?("Pod::UI")
45+
+ source[:git] = git
46+
+ source[:commit] = `git ls-remote https://github.com/facebook/hermes main | cut -f 1`.strip
47+
+elsif isNightly
48+
+ Pod::UI.puts '[Hermes] Nightly version, download pre-built for Hermes'.yellow if Object.const_defined?("Pod::UI")
49+
+ destination_path = download_nightly_hermes(react_native_path, version)
50+
+ # set tarball as hermes engine
51+
+ source[:http] = "file://#{destination_path}"
52+
+elsif File.exist?(hermestag_file) && isInCI
53+
+ Pod::UI.puts '[Hermes] Detected that you are on a React Native release branch, building Hermes from source but fetched from tag...'.yellow if Object.const_defined?("Pod::UI")
54+
+ hermestag = File.read(hermestag_file).strip
55+
+ source[:git] = git
56+
+ source[:tag] = hermestag
57+
+else
58+
+ # Sample url from Maven:
59+
+ # https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.71.0/react-native-artifacts-0.71.0-hermes-ios-debug.tar.gz
60+
+ source[:http] = "https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/#{version}/react-native-artifacts-#{version}-hermes-ios-#{build_type.to_s}.tar.gz"
61+
+end
62+
+
63+
+Pod::Spec.new do |spec|
64+
+ spec.name = "hermes-engine"
65+
+ spec.version = version
66+
+ spec.summary = "Hermes is a small and lightweight JavaScript engine optimized for running React Native."
67+
+ spec.description = "Hermes is a JavaScript engine optimized for fast start-up of React Native apps. It features ahead-of-time static optimization and compact bytecode."
68+
+ spec.homepage = "https://hermesengine.dev"
69+
+ spec.license = package['license']
70+
+ spec.author = "Facebook"
71+
+ spec.source = source
72+
+ spec.platforms = { :osx => "10.13", :ios => "12.4" }
73+
+
74+
+ spec.preserve_paths = '**/*.*'
75+
+ spec.source_files = ''
76+
+
77+
+ spec.xcconfig = {
78+
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
79+
+ "CLANG_CXX_LIBRARY" => "compiler-default"
80+
+ }.merge!(build_type == :debug ? { "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1" } : {})
81+
+
82+
+ if source[:http] then
83+
+
84+
+ spec.subspec 'Pre-built' do |ss|
85+
+ ss.preserve_paths = ["destroot/bin/*"].concat(build_type == :debug ? ["**/*.{h,c,cpp}"] : [])
86+
+ ss.source_files = "destroot/include/**/*.h"
87+
+ ss.exclude_files = ["destroot/include/jsi/jsi/JSIDynamic.{h,cpp}", "destroot/include/jsi/jsi/jsilib-*.{h,cpp}"]
88+
+ ss.header_mappings_dir = "destroot/include"
89+
+ ss.ios.vendored_frameworks = "destroot/Library/Frameworks/universal/hermes.xcframework"
90+
+ ss.osx.vendored_frameworks = "destroot/Library/Frameworks/macosx/hermes.framework"
91+
+ end
92+
+
93+
+ elsif source[:git] then
94+
+
95+
+ spec.subspec 'Hermes' do |ss|
96+
+ ss.source_files = ''
97+
+ ss.public_header_files = 'API/hermes/*.h'
98+
+ ss.header_dir = 'hermes'
99+
+ end
100+
+
101+
+ spec.subspec 'JSI' do |ss|
102+
+ ss.source_files = ''
103+
+ ss.public_header_files = 'API/jsi/jsi/*.h'
104+
+ ss.header_dir = 'jsi'
105+
+ end
106+
+
107+
+ spec.subspec 'Public' do |ss|
108+
+ ss.source_files = ''
109+
+ ss.public_header_files = 'public/hermes/Public/*.h'
110+
+ ss.header_dir = 'hermes/Public'
111+
+ end
112+
+
113+
+ hermesc_path = ""
114+
+
115+
+ if ENV.has_key?('HERMES_OVERRIDE_HERMESC_PATH') && File.exist?(ENV['HERMES_OVERRIDE_HERMESC_PATH']) then
116+
+ hermesc_path = ENV['HERMES_OVERRIDE_HERMESC_PATH']
117+
+ else
118+
+ # Keep hermesc_path synchronized with .gitignore entry.
119+
+ ENV['REACT_NATIVE_PATH'] = react_native_path
120+
+ hermesc_path = "${REACT_NATIVE_PATH}/sdks/hermes-engine/build_host_hermesc"
121+
+ # NOTE: Prepare command is not run if the pod is not downloaded.
122+
+ spec.prepare_command = ". #{react_native_path}/sdks/hermes-engine/utils/build-hermesc-xcode.sh #{hermesc_path}"
123+
+ end
124+
+
125+
+ spec.user_target_xcconfig = {
126+
+ 'FRAMEWORK_SEARCH_PATHS' => '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/iphoneos" ' +
127+
+ '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/iphonesimulator" ' +
128+
+ '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/macosx" ' +
129+
+ '"$(PODS_ROOT)/hermes-engine/destroot/Library/Frameworks/catalyst"',
130+
+ 'OTHER_LDFLAGS' => '-framework "hermes"',
131+
+ 'HERMES_CLI_PATH' => "#{hermesc_path}/bin/hermesc"
132+
+ }
133+
+
134+
+ spec.script_phases = [
135+
+ {
136+
+ :name => 'Build Hermes',
137+
+ :script => <<-EOS
138+
+ . ${PODS_ROOT}/../.xcode.env
139+
+ export CMAKE_BINARY=${CMAKE_BINARY:-#{%x(command -v cmake | tr -d '\n')}}
140+
+ . ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermes-xcode.sh #{version} #{hermesc_path}/ImportHermesc.cmake
141+
+ EOS
142+
+ },
143+
+ {
144+
+ :name => 'Copy Hermes Framework',
145+
+ :script => ". ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/copy-hermes-xcode.sh"
146+
+ }
147+
+ ]
148+
+ end
149+
+end
150+
diff --git a/node_modules/react-native/sdks/hermes/hermes-utils.rb b/node_modules/react-native/sdks/hermes/hermes-utils.rb
151+
new file mode 100644
152+
index 0000000..0842496
153+
--- /dev/null
154+
+++ b/node_modules/react-native/sdks/hermes/hermes-utils.rb
155+
@@ -0,0 +1,26 @@
156+
+# Copyright (c) Meta Platforms, Inc. and affiliates.
157+
+#
158+
+# This source code is licensed under the MIT license found in the
159+
+# LICENSE file in the root directory of this source tree.
160+
+
161+
+require 'net/http'
162+
+require 'rexml/document'
163+
+
164+
+# This function downloads the nightly prebuilt version of Hermes based on the passed version
165+
+# and save it in the node_module/react_native/sdks/downloads folder
166+
+# It then returns the path to the hermes tarball
167+
+#
168+
+# Parameters
169+
+# - react_native_path: the path to the React Native folder in node modules. It is used as root path to store the Hermes tarball
170+
+# - version: the version of React Native that requires the Hermes tarball
171+
+# Returns: the path to the downloaded Hermes tarball
172+
+def download_nightly_hermes(react_native_path, version)
173+
+ params = "r=snapshots\&g=com.facebook.react\&a=react-native-artifacts\&c=hermes-ios-debug\&e=tar.gz\&v=#{version}-SNAPSHOT"
174+
+ tarball_url = "http://oss.sonatype.org/service/local/artifact/maven/redirect\?#{params}"
175+
+
176+
+ destination_folder = "#{react_native_path}/sdks/downloads"
177+
+ destination_path = "#{destination_folder}/hermes-ios.tar.gz"
178+
+
179+
+ `mkdir -p "#{destination_folder}" && curl "#{tarball_url}" -Lo "#{destination_path}"`
180+
+ return destination_path
181+
+end
182+
diff --git a/node_modules/react-native/third-party-podspecs/boost.podspec b/node_modules/react-native/third-party-podspecs/boost.podspec
183+
index 3d9331c..b1e2c6a 100644
184+
--- a/node_modules/react-native/third-party-podspecs/boost.podspec
185+
+++ b/node_modules/react-native/third-party-podspecs/boost.podspec
186+
@@ -10,7 +10,7 @@ Pod::Spec.new do |spec|
187+
spec.homepage = 'http://www.boost.org'
188+
spec.summary = 'Boost provides free peer-reviewed portable C++ source libraries.'
189+
spec.authors = 'Rene Rivera'
190+
- spec.source = { :http => 'https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2',
191+
+ spec.source = { :http => 'https://sourceforge.net/projects/boost/files/boost/1.76.0/boost_1_76_0.tar.bz2',
192+
:sha256 => 'f0397ba6e982c4450f27bf32a2a83292aba035b827a5623a14636ea583318c41' }
193+
194+
# Pinning to the same version as React.podspec.

ios/RCTImageMarker/ImageMarker.swift

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public final class ImageMarker: NSObject, RCTBridgeModule {
116116
}
117117
}
118118

119-
func markerImgWithText(_ image: UIImage, _ opts: MarkTextOptions) -> UIImage? {
119+
func markImgWithText(_ image: UIImage, _ opts: MarkTextOptions) -> UIImage? {
120120

121121
var bg = image;
122122
let w = bg.size.width
@@ -271,9 +271,9 @@ public final class ImageMarker: NSObject, RCTBridgeModule {
271271
return aimg
272272
}
273273

274-
func markeImage(with image: UIImage, waterImages: [UIImage], options: MarkImageOptions) -> UIImage? {
275-
276-
var bg = image;
274+
func markImage(with image: UIImage, waterImages: [UIImage], options: MarkImageOptions) -> UIImage? {
275+
276+
let bg = image;
277277
let w = bg.size.width
278278
let h = bg.size.height
279279
UIGraphicsBeginImageContextWithOptions(bg.size, false, options.backgroundImage.scale)
@@ -323,39 +323,41 @@ public final class ImageMarker: NSObject, RCTBridgeModule {
323323
case .topLeft:
324324
rect = CGRect(origin: CGPoint(x: 20, y: 20), size: size)
325325
case .topCenter:
326-
rect = CGRect(origin: CGPoint(x: (w - size.width) / 2, y: 20), size: size)
326+
rect = CGRect(origin: CGPoint(x: (w - ww) / 2, y: 20), size: size)
327327
case .topRight:
328-
rect = CGRect(origin: CGPoint(x: w - size.width - 20, y: 20), size: size)
328+
rect = CGRect(origin: CGPoint(x: w - ww - 20, y: 20), size: size)
329329
case .bottomLeft:
330-
rect = CGRect(origin: CGPoint(x: 20, y: h - size.height - 20), size: size)
330+
rect = CGRect(origin: CGPoint(x: 20, y: h - wh - 20), size: size)
331331
case .bottomCenter:
332-
rect = CGRect(origin: CGPoint(x: (w - size.width) / 2, y: h - size.height - 20), size: size)
332+
rect = CGRect(origin: CGPoint(x: (w - ww) / 2, y: h - wh - 20), size: size)
333333
case .bottomRight:
334-
rect = CGRect(origin: CGPoint(x: w - size.width - 20, y: h - size.height - 20), size: size)
334+
rect = CGRect(origin: CGPoint(x: w - ww - 20, y: h - wh - 20), size: size)
335335
case .center:
336-
rect = CGRect(origin: CGPoint(x: (w - size.width) / 2, y: (h - size.height) / 2), size: size)
336+
rect = CGRect(origin: CGPoint(x: (w - ww) / 2, y: (h - wh) / 2), size: size)
337337
default:
338338
rect = CGRect(origin: CGPoint(x: 20, y: 20), size: size)
339339
}
340340
} else {
341-
rect = CGRect(x: Utils.parseSpreadValue(v: watermarkOptions.X, relativeTo: w) ?? 20, y: Utils.parseSpreadValue(v: watermarkOptions.Y, relativeTo: h) ?? 20, width: CGFloat(ww), height: CGFloat(wh))
341+
rect = CGRect(x: Utils.parseSpreadValue(v: watermarkOptions.X, relativeTo: w) ?? 20, y: Utils.parseSpreadValue(v: watermarkOptions.Y, relativeTo: h) ?? 20, width: diagonal, height: diagonal)
342342
}
343343

344344
UIGraphicsBeginImageContextWithOptions(CGSize(width: diagonal, height: diagonal), false, 1)
345345
let markerContext = UIGraphicsGetCurrentContext()
346346
markerContext?.saveGState()
347-
347+
348348
if watermarkOptions.imageOption.alpha != 1.0 {
349349
markerContext?.beginTransparencyLayer(auxiliaryInfo: nil)
350350
markerContext?.setAlpha(watermarkOptions.imageOption.alpha)
351351
markerContext?.setBlendMode(.multiply)
352352
let markerImage = markerImg.rotatedImageWithTransform(watermarkOptions.imageOption.rotate)
353-
markerContext?.draw(markerImage.cgImage!, in: CGRect(origin: .zero, size: CGSize(width: diagonal, height: diagonal)))
353+
let originPoint = CGPoint(x: 0, y: rect.height - markerImage.size.height)
354+
markerContext?.draw(markerImage.cgImage!, in: CGRect(origin: originPoint, size: CGSize(width: markerImage.size.width, height: markerImage.size.height)))
354355
markerContext?.endTransparencyLayer()
355356

356357
} else {
357358
let markerImage = markerImg.rotatedImageWithTransform(watermarkOptions.imageOption.rotate)
358-
markerContext?.draw(markerImage.cgImage!, in: CGRect(origin: .zero, size: CGSize(width: diagonal, height: diagonal)))
359+
let originPoint = CGPoint(x: 0, y: rect.height - markerImage.size.height)
360+
markerContext?.draw(markerImage.cgImage!, in: CGRect(origin: originPoint, size: CGSize(width: markerImage.size.width, height: markerImage.size.height)))
359361
}
360362
markerContext?.restoreGState()
361363

@@ -388,12 +390,12 @@ public final class ImageMarker: NSObject, RCTBridgeModule {
388390
Task(priority: .userInitiated) {
389391
do {
390392
let images = try await loadImages(with: [(markOpts?.backgroundImage)!])
391-
let scaledImage = self.markerImgWithText(images[0], markOpts!)
393+
let scaledImage = self.markImgWithText(images[0], markOpts!)
392394
let res = self.saveImageForMarker(scaledImage!, with: markOpts!)
393395
resolver(res)
394-
print("Loaded images:", images)
396+
print("Loaded images: \(images)")
395397
} catch {
396-
print("Failed to load images:", error)
398+
print("Failed to load images, error: \(error).")
397399
}
398400
}
399401
}
@@ -408,12 +410,12 @@ public final class ImageMarker: NSObject, RCTBridgeModule {
408410
do {
409411
let waterImages = markOpts?.watermarkImages.map { $0.imageOption }
410412
var images = try await loadImages(with: [(markOpts?.backgroundImage)!] + waterImages!)
411-
let scaledImage = self.markeImage(with: images.remove(at: 0), waterImages: images, options: markOpts!)
413+
let scaledImage = self.markImage(with: images.remove(at: 0), waterImages: images, options: markOpts!)
412414
let res = self.saveImageForMarker(scaledImage!, with: markOpts!)
413415
resolver(res)
414-
print("Loaded images:", images)
416+
print("Loaded images: \(images), waterImages: \(String(describing: waterImages))")
415417
} catch {
416-
print("Failed to load images:", error)
418+
print("Failed to load images, error: \(error).")
417419
}
418420
}
419421
}

0 commit comments

Comments
 (0)