Skip to content

Commit

Permalink
fix: Pass preview orientation
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Jul 12, 2024
1 parent e75a027 commit 30764da
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 12 deletions.
16 changes: 8 additions & 8 deletions package/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1391,16 +1391,16 @@ PODS:
- ReactCommon/turbomodule/core
- Yoga
- SocketRocket (0.7.0)
- VisionCamera (4.4.2):
- VisionCamera/Core (= 4.4.2)
- VisionCamera/FrameProcessors (= 4.4.2)
- VisionCamera/React (= 4.4.2)
- VisionCamera/Core (4.4.2)
- VisionCamera/FrameProcessors (4.4.2):
- VisionCamera (4.4.3):
- VisionCamera/Core (= 4.4.3)
- VisionCamera/FrameProcessors (= 4.4.3)
- VisionCamera/React (= 4.4.3)
- VisionCamera/Core (4.4.3)
- VisionCamera/FrameProcessors (4.4.3):
- React
- React-callinvoker
- react-native-worklets-core
- VisionCamera/React (4.4.2):
- VisionCamera/React (4.4.3):
- React-Core
- VisionCamera/FrameProcessors
- Yoga (0.0.0)
Expand Down Expand Up @@ -1688,7 +1688,7 @@ SPEC CHECKSUMS:
RNStaticSafeAreaInsets: 055ddbf5e476321720457cdaeec0ff2ba40ec1b8
RNVectorIcons: 2a2f79274248390b80684ea3c4400bd374a15c90
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
VisionCamera: 0292805e99ae8d121c8ec5bb8a9554f6f1c36b82
VisionCamera: 7435f20f7ee7756a1e307e986195a97764da5142
Yoga: 2f71ecf38d934aecb366e686278102a51679c308

PODFILE CHECKSUM: 49584be049764895189f1f88ebc9769116621103
Expand Down
5 changes: 5 additions & 0 deletions package/src/Camera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,11 @@ export class Camera extends React.PureComponent<CameraProps, CameraState> {
this.rotationHelper.previewOrientation = previewOrientation
this.props.onPreviewOrientationChanged?.(previewOrientation)
this.maybeUpdateUIRotation()

if (isSkiaFrameProcessor(this.props.frameProcessor)) {
// If we have a Skia Frame Processor, we need to update it's orientation so it knows how to render.
this.props.frameProcessor.previewOrientation.value = previewOrientation
}
}

private maybeUpdateUIRotation(): void {
Expand Down
43 changes: 39 additions & 4 deletions package/src/skia/useSkiaFrameProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { WorkletsProxy } from '../dependencies/WorkletsProxy'
import { SkiaProxy } from '../dependencies/SkiaProxy'
import { withFrameRefCounting } from '../frame-processors/withFrameRefCounting'
import { VisionCameraProxy } from '../frame-processors/VisionCameraProxy'
import type { Orientation } from '../types/Orientation'

/**
* Represents a Camera Frame that can be directly drawn to using Skia.
Expand Down Expand Up @@ -46,19 +47,50 @@ type SurfaceCache = Record<
}
>

function getDegrees(orientation: Orientation): number {
'worklet'
switch (orientation) {
case 'portrait':
return 0
case 'landscape-left':
return 270
case 'portrait-upside-down':
return 180
case 'landscape-right':
return 90
}
}

function getOrientation(degrees: number): Orientation {
'worklet'
const clamped = degrees % 360
if (clamped >= 315 || clamped <= 45) return 'portrait'
else if (clamped >= 45 || clamped <= 135) return 'landscape-left'
else if (clamped >= 135 || clamped <= 225) return 'portrait-upside-down'
else if (clamped >= 225 || clamped <= 315) return 'landscape-right'
else throw new Error(`Invalid degrees! ${degrees}`)
}

function rotateBy(a: Orientation, b: Orientation): Orientation {
'worklet'
return getOrientation(getDegrees(a) + getDegrees(b))
}

/**
* Counter-rotates the {@linkcode canvas} by the {@linkcode frame}'s {@linkcode Frame.orientation orientation}
* to ensure the Frame will be drawn upright.
*/
function withRotatedFrame(frame: Frame, canvas: SkCanvas, func: () => void): void {
function withRotatedFrame(frame: Frame, canvas: SkCanvas, previewOrientation: Orientation, func: () => void): void {
'worklet'

// 1. save current translation matrix
canvas.save()

try {
// 2. properly rotate canvas so Frame is rendered up-right.
switch (frame.orientation) {
const orientation = rotateBy(frame.orientation, previewOrientation)
console.log(frame.orientation, previewOrientation, orientation)
switch (orientation) {
case 'portrait':
// do nothing
break
Expand Down Expand Up @@ -139,6 +171,7 @@ export function createSkiaFrameProcessor(
frameProcessor: (frame: DrawableFrame) => void,
surfaceHolder: ISharedValue<SurfaceCache>,
offscreenTextures: ISharedValue<SkImage[]>,
previewOrientation: ISharedValue<Orientation>,
): DrawableFrameProcessor {
const Skia = SkiaProxy.Skia
const Worklets = WorkletsProxy.Worklets
Expand Down Expand Up @@ -236,7 +269,7 @@ export function createSkiaFrameProcessor(
canvas.clear(black)

// 4. rotate the frame properly to make sure it's upright
withRotatedFrame(frame, canvas, () => {
withRotatedFrame(frame, canvas, previewOrientation.value, () => {
// 5. Run any user drawing operations
frameProcessor(drawableFrame)
})
Expand Down Expand Up @@ -264,6 +297,7 @@ export function createSkiaFrameProcessor(
}),
type: 'drawable-skia',
offscreenTextures: offscreenTextures,
previewOrientation: previewOrientation,
}
}

Expand Down Expand Up @@ -301,6 +335,7 @@ export function useSkiaFrameProcessor(
): DrawableFrameProcessor {
const surface = WorkletsProxy.useSharedValue<SurfaceCache>({})
const offscreenTextures = WorkletsProxy.useSharedValue<SkImage[]>([])
const previewOrientation = WorkletsProxy.useSharedValue<Orientation>('portrait')

useEffect(() => {
return () => {
Expand All @@ -322,7 +357,7 @@ export function useSkiaFrameProcessor(
}, [offscreenTextures, surface])

return useMemo(
() => createSkiaFrameProcessor(frameProcessor, surface, offscreenTextures),
() => createSkiaFrameProcessor(frameProcessor, surface, offscreenTextures, previewOrientation),
// eslint-disable-next-line react-hooks/exhaustive-deps
dependencies,
)
Expand Down

0 comments on commit 30764da

Please sign in to comment.