Skip to content

Commit 7abf3e4

Browse files
authored
ndk/bitmap: Provide detailed implementation for AndroidBitmapInfoFlags (#424)
As per the TODO, wrap this flags type with some helpers that fish out the two bit-representations for the `IS_HARDWARE` flag and `ALPHA` value. Also add missing documentation and aliases across the `bitmap` module.
1 parent 8e3e8ff commit 7abf3e4

File tree

2 files changed

+111
-8
lines changed

2 files changed

+111
-8
lines changed

ndk/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- looper: Add `remove_fd()` to unregister events/callbacks for a file descriptor. (#416)
2525
- **Breaking:** Use `BorrowedFd` and `OwnedFd` to clarify possible ownership transitions. (#417)
2626
- **Breaking:** Upgrade to [`ndk-sys 0.5.0`](../ndk-sys/CHANGELOG.md#050-beta0-2023-08-15). (#420)
27+
- **Breaking:** bitmap: Provide detailed implementation for `AndroidBitmapInfoFlags`. (#424)
2728
- hardware_buffer: Add `id()` to retrieve a system-wide unique identifier for a `HardwareBuffer`. (#428)
2829

2930
# 0.7.0 (2022-07-24)

ndk/src/bitmap.rs

Lines changed: 110 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ use std::mem::MaybeUninit;
1414
use crate::hardware_buffer::HardwareBufferRef;
1515

1616
#[repr(i32)]
17-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
17+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1818
pub enum BitmapError {
1919
Unknown,
20+
#[doc(alias = "ANDROID_BITMAP_RESULT_ALLOCATION_FAILED")]
2021
AllocationFailed = ffi::ANDROID_BITMAP_RESULT_ALLOCATION_FAILED,
22+
#[doc(alias = "ANDROID_BITMAP_RESULT_BAD_PARAMETER")]
2123
BadParameter = ffi::ANDROID_BITMAP_RESULT_BAD_PARAMETER,
24+
#[doc(alias = "ANDROID_BITMAP_RESULT_JNI_EXCEPTION")]
2225
JniException = ffi::ANDROID_BITMAP_RESULT_JNI_EXCEPTION,
2326
}
2427

@@ -43,16 +46,23 @@ fn construct<T>(with_ptr: impl FnOnce(*mut T) -> i32) -> BitmapResult<T> {
4346
}
4447

4548
#[repr(u32)]
46-
#[derive(Copy, Clone, Debug, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
49+
#[derive(Clone, Copy, Debug, PartialEq, Eq, IntoPrimitive, TryFromPrimitive)]
4750
#[allow(non_camel_case_types)]
4851
pub enum BitmapFormat {
52+
#[doc(alias = "ANDROID_BITMAP_FORMAT_NONE")]
4953
NONE = ffi::AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_NONE.0,
54+
#[doc(alias = "ANDROID_BITMAP_FORMAT_RGBA_8888")]
5055
RGBA_8888 = ffi::AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGBA_8888.0,
56+
#[doc(alias = "ANDROID_BITMAP_FORMAT_RGB_565")]
5157
RGB_565 = ffi::AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGB_565.0,
5258
#[deprecated = "Deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead."]
59+
#[doc(alias = "ANDROID_BITMAP_FORMAT_RGBA_4444")]
5360
RGBA_4444 = ffi::AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGBA_4444.0,
61+
#[doc(alias = "ANDROID_BITMAP_FORMAT_A_8")]
5462
A_8 = ffi::AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_A_8.0,
63+
#[doc(alias = "ANDROID_BITMAP_FORMAT_RGBA_F16")]
5564
RGBA_F16 = ffi::AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGBA_F16.0,
65+
#[doc(alias = "ANDROID_BITMAP_FORMAT_RGBA_1010102")]
5666
RGBA_1010102 = ffi::AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGBA_1010102.0,
5767
}
5868

@@ -77,26 +87,42 @@ impl AndroidBitmap {
7787
Self { env, inner: bitmap }
7888
}
7989

90+
/// Fills out and returns the [`AndroidBitmapInfo`] struct for the given Java bitmap object.
91+
#[doc(alias = "AndroidBitmap_getInfo")]
8092
pub fn get_info(&self) -> BitmapResult<AndroidBitmapInfo> {
8193
let inner =
8294
construct(|res| unsafe { ffi::AndroidBitmap_getInfo(self.env, self.inner, res) })?;
8395

8496
Ok(AndroidBitmapInfo { inner })
8597
}
8698

99+
/// Attempt to lock the pixel address.
100+
///
101+
/// Locking will ensure that the memory for the pixels will not move until the
102+
/// [`AndroidBitmap::unlock_pixels()`] call, and ensure that, if the pixels had been previously
103+
/// purged, they will have been restored.
104+
///
105+
/// If this call succeeds, it must be balanced by a call to [`AndroidBitmap::unlock_pixels()`],
106+
/// after which time the address of the pixels should no longer be used.
107+
#[doc(alias = "AndroidBitmap_lockPixels")]
87108
pub fn lock_pixels(&self) -> BitmapResult<*mut std::os::raw::c_void> {
88109
construct(|res| unsafe { ffi::AndroidBitmap_lockPixels(self.env, self.inner, res) })
89110
}
90111

112+
/// Call this to balance a successful call to [`AndroidBitmap::lock_pixels()`].
113+
#[doc(alias = "AndroidBitmap_unlockPixels")]
91114
pub fn unlock_pixels(&self) -> BitmapResult<()> {
92115
let status = unsafe { ffi::AndroidBitmap_unlockPixels(self.env, self.inner) };
93116
BitmapError::from_status(status)
94117
}
95118

96-
/// Retrieve the native object associated with a `HARDWARE` [`AndroidBitmap`].
119+
/// Retrieve the native object associated with an [`ffi::ANDROID_BITMAP_FLAGS_IS_HARDWARE`]
120+
/// [`AndroidBitmap`] (requires [`AndroidBitmapInfoFlags::is_hardware()`] on
121+
/// [`AndroidBitmapInfo::flags()`] to return [`true`]).
97122
///
98123
/// Client must not modify it while an [`AndroidBitmap`] is wrapping it.
99124
#[cfg(feature = "api-level-30")]
125+
#[doc(alias = "AndroidBitmap_getHardwareBuffer")]
100126
pub fn get_hardware_buffer(&self) -> BitmapResult<HardwareBufferRef> {
101127
unsafe {
102128
let result =
@@ -111,27 +137,102 @@ impl AndroidBitmap {
111137
}
112138
}
113139

140+
/// Possible values for [`ffi::ANDROID_BITMAP_FLAGS_ALPHA_MASK`] within [`AndroidBitmapInfoFlags`]
141+
#[cfg(feature = "api-level-30")]
142+
#[derive(Clone, Copy, Debug)]
143+
pub enum AndroidBitmapInfoFlagsAlpha {
144+
/// Pixel components are premultiplied by alpha.
145+
#[doc(alias = "ANDROID_BITMAP_FLAGS_ALPHA_PREMUL")]
146+
Premultiplied,
147+
/// Pixels are opaque.
148+
#[doc(alias = "ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE")]
149+
Opaque,
150+
/// Pixel components are independent of alpha.
151+
#[doc(alias = "ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL")]
152+
Unpremultiplied,
153+
}
154+
155+
/// Bitfield containing information about the bitmap.
156+
#[cfg(feature = "api-level-30")]
157+
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
158+
#[repr(transparent)]
159+
pub struct AndroidBitmapInfoFlags(u32);
160+
161+
#[cfg(feature = "api-level-30")]
162+
impl std::fmt::Debug for AndroidBitmapInfoFlags {
163+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164+
write!(
165+
f,
166+
"AndroidBitmapInfoFlags({:#x}, alpha: {:?}, is_hardware: {})",
167+
self.0,
168+
self.alpha(),
169+
self.is_hardware()
170+
)
171+
}
172+
}
173+
174+
#[cfg(feature = "api-level-30")]
175+
impl AndroidBitmapInfoFlags {
176+
/// Returns the alpha value contained in the [`ffi::ANDROID_BITMAP_FLAGS_ALPHA_MASK`] bit range
177+
#[doc(alias = "ANDROID_BITMAP_FLAGS_ALPHA_MASK")]
178+
pub fn alpha(self) -> AndroidBitmapInfoFlagsAlpha {
179+
// Note that ffi::ANDROID_BITMAP_FLAGS_ALPHA_SHIFT is 0 and hence irrelevant.
180+
match self.0 & ffi::ANDROID_BITMAP_FLAGS_ALPHA_MASK {
181+
ffi::ANDROID_BITMAP_FLAGS_ALPHA_PREMUL => AndroidBitmapInfoFlagsAlpha::Premultiplied,
182+
ffi::ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE => AndroidBitmapInfoFlagsAlpha::Opaque,
183+
ffi::ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL => {
184+
AndroidBitmapInfoFlagsAlpha::Unpremultiplied
185+
}
186+
3 => todo!("ALPHA_MASK value 3"),
187+
_ => unreachable!(),
188+
}
189+
}
190+
191+
/// Returns [`true`] when [`ffi::ANDROID_BITMAP_FLAGS_IS_HARDWARE`] is set, meaning this
192+
/// [`AndroidBitmap`] uses "HARDWARE Config" and its [`HardwareBufferRef`] can be retrieved via
193+
/// [`AndroidBitmap::get_hardware_buffer()`].
194+
#[doc(alias = "ANDROID_BITMAP_FLAGS_IS_HARDWARE")]
195+
pub fn is_hardware(self) -> bool {
196+
// This constant is defined in a separate anonymous enum which bindgen treats as i32.
197+
(self.0 & ffi::ANDROID_BITMAP_FLAGS_IS_HARDWARE as u32) != 0
198+
}
199+
}
200+
114201
/// A native [`AndroidBitmapInfo`]
115202
///
116203
/// [`AndroidBitmapInfo`]: https://developer.android.com/ndk/reference/struct/android-bitmap-info#struct_android_bitmap_info
117-
#[derive(Copy, Clone, Debug)]
204+
#[derive(Clone, Copy)]
118205
pub struct AndroidBitmapInfo {
119206
inner: ffi::AndroidBitmapInfo,
120207
}
121208

122-
// TODO: flesh out when API 30 is released
123-
#[cfg(feature = "api-level-30")]
124-
pub type AndroidBitmapInfoFlags = u32;
209+
impl std::fmt::Debug for AndroidBitmapInfo {
210+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
211+
let mut f = f.debug_struct("AndroidBitmapInfo");
212+
f.field("width", &self.width())
213+
.field("height", &self.height())
214+
.field("stride", &self.stride())
215+
.field("format", &self.try_format());
216+
217+
#[cfg(feature = "api-level-30")]
218+
f.field("flags", &self.flags());
219+
220+
f.finish()
221+
}
222+
}
125223

126224
impl AndroidBitmapInfo {
225+
/// The bitmap width in pixels.
127226
pub fn width(&self) -> u32 {
128227
self.inner.width
129228
}
130229

230+
/// The bitmap height in pixels.
131231
pub fn height(&self) -> u32 {
132232
self.inner.height
133233
}
134234

235+
/// The number of byte per row.
135236
pub fn stride(&self) -> u32 {
136237
self.inner.stride
137238
}
@@ -155,8 +256,9 @@ impl AndroidBitmapInfo {
155256
format.try_into()
156257
}
157258

259+
/// Bitfield containing information about the bitmap.
158260
#[cfg(feature = "api-level-30")]
159261
pub fn flags(&self) -> AndroidBitmapInfoFlags {
160-
self.inner.flags
262+
AndroidBitmapInfoFlags(self.inner.flags)
161263
}
162264
}

0 commit comments

Comments
 (0)