1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::{ffi, Error, FtResult};
use std::slice;

/// An enumeration type used to describe the format of pixels in a given bitmap. Note that
/// additional formats may be added in the future.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PixelMode {
	/// This value is reserved.
	None,

	/// A monochrome bitmap, using 1 bit per pixel. Note that pixels are
	/// stored in most-significant order (MSB), which means that the left-most
	/// pixel in a byte has value 128.
	Mono,

	/// An 8-bit bitmap, generally used to represent anti-aliased glyph images.
	/// Each pixel is stored in one byte. Note that the number of `gray`
	/// levels is stored in the `num_grays` field of the FT_Bitmap structure
	/// (it generally is 256).
	Gray,

	/// A 2-bit per pixel bitmap, used to represent embedded anti-aliased
	/// bitmaps in font files according to the OpenType specification. We
	/// haven't found a single font using this format, however.
	Gray2,

	/// A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps in
	/// font files according to the OpenType specification. We haven't found a
	/// single font using this format, however.
	Gray4,

	/// An 8-bit bitmap, representing RGB or BGR decimated glyph images used
	/// for display on LCD displays; the bitmap is three times wider than the
	/// original glyph image. See also FT_RENDER_MODE_LCD.
	Lcd,

	/// An 8-bit bitmap, representing RGB or BGR decimated glyph images used for
	/// display on rotated LCD displays; the bitmap is three times taller than
	/// the original glyph image. See also FT_RENDER_MODE_LCD_V.
	LcdV,

	/// An image with four 8-bit channels per pixel, representing a color image
	/// (such as emoticons) with alpha channel. For each pixel, the format is
	/// BGRA, which means, the blue channel comes first in memory. The color
	/// channels are pre-multiplied and in the sRGB colorspace. For example,
	/// full red at half-translucent opacity will be represented as
	/// `00,00,80,80`, not `00,00,FF,80`. See also FT_LOAD_COLOR.
	Bgra,
}

#[allow(missing_copy_implementations)]
pub struct Bitmap {
	raw: *const ffi::FT_Bitmap,
}

impl Bitmap {
	pub unsafe fn from_raw(raw: *const ffi::FT_Bitmap) -> Self {
		Bitmap { raw }
	}

	/// A typeless pointer to the bitmap buffer. This value should be aligned
	/// on 32-bit boundaries in most cases.
	pub fn buffer(&self) -> &[u8] {
		unsafe {
			slice::from_raw_parts(
				(*self.raw).buffer,
				(self.pitch().abs() * self.rows()) as usize,
			)
		}
	}

	/// The number of pixels in bitmap row.
	pub fn width(&self) -> i32 {
		unsafe { (*self.raw).width }
	}

	/// The number of bitmap rows.
	pub fn rows(&self) -> i32 {
		unsafe { (*self.raw).rows }
	}

	pub fn raw(&self) -> &ffi::FT_Bitmap {
		unsafe { &*self.raw }
	}

	/// The pixel mode, i.e., how pixel bits are stored. See `PixelMode` for
	/// possible values.
	pub fn pixel_mode(&self) -> FtResult<PixelMode> {
		let pixel_mode = unsafe { (*self.raw).pixel_mode } as u32;

		Ok(match pixel_mode {
			ffi::FT_PIXEL_MODE_NONE => PixelMode::None,
			ffi::FT_PIXEL_MODE_MONO => PixelMode::Mono,
			ffi::FT_PIXEL_MODE_GRAY => PixelMode::Gray,
			ffi::FT_PIXEL_MODE_GRAY2 => PixelMode::Gray2,
			ffi::FT_PIXEL_MODE_GRAY4 => PixelMode::Gray4,
			ffi::FT_PIXEL_MODE_LCD => PixelMode::Lcd,
			ffi::FT_PIXEL_MODE_LCD_V => PixelMode::LcdV,
			ffi::FT_PIXEL_MODE_BGRA => PixelMode::Bgra,
			_ => return Err(Error::UnexpectedPixelMode),
		})
	}

	/// The pitch's absolute value is the number of bytes taken by one bitmap row, including
	/// padding. However, the pitch is positive when the bitmap has a ‘down’ flow, and negative
	/// when it has an ‘up’ flow. In all cases, the pitch is an offset to add to a bitmap pointer
	/// in order to go down one row.
	///
	/// Note that ‘padding’ means the alignment of a bitmap to a byte border, and FreeType
	/// functions normally align to the smallest possible integer value.
	/// For the B/W rasterizer, ‘pitch’ is always an even number.
	///
	/// To change the pitch of a bitmap (say, to make it a multiple of 4), use FT_Bitmap_Convert.
	/// Alternatively, you might use callback functions to directly render to the application's
	/// surface; see the file ‘example2.cpp’ in the tutorial for a demonstration.
	pub fn pitch(&self) -> i32 {
		unsafe { (*self.raw).pitch }
	}
}