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
//! The Windows "Graphics Device Interface" (GDI).
//!
//! It mostly lets you do 2D drawing in a Window.

use super::*;

use winapi::um::wingdi::{
  GetDeviceCaps, StretchDIBits, BITMAPINFO, BLACKNESS, CAPTUREBLT, DIB_PAL_COLORS,
  DIB_RGB_COLORS, DSTINVERT, MERGECOPY, MERGEPAINT, NOMIRRORBITMAP, NOTSRCCOPY,
  NOTSRCERASE, PATCOPY, PATINVERT, PATPAINT, SRCAND, SRCCOPY, SRCERASE, SRCINVERT,
  SRCPAINT, WHITENESS,
};

/// See [`GetDeviceCaps`](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getdevicecaps)
#[inline]
pub unsafe fn get_device_caps(hdc: HDC, index: i32) -> i32 {
  GetDeviceCaps(hdc, index)
}

/// Describes the color scheme of some Device Independent Bits.
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DibColors {
  /// Paletted colors
  Pal = DIB_PAL_COLORS,
  /// RGB colors
  RGB = DIB_RGB_COLORS,
}

/// Common raster operations, See the parameters of
/// [`BitBlt`](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-bitblt#parameters)
#[repr(u32)]
#[derive(Debug, Clone, Copy)]
pub enum RasterOp {
  /// Fill dest with index 0 in the physical palette (defaults to black)
  Blackness = BLACKNESS,
  /// Includes windows layered on top of your window in the image
  CaptureBlt = CAPTUREBLT,
  /// Invert the destination rectangle
  DstInvert = DSTINVERT,
  /// Merge the source and brush with AND
  MergeCopy = MERGECOPY,
  /// Merge inverted source with dest using OR
  MergePaint = MERGEPAINT,
  /// Prevents the bitmap from being mirrored
  NoMirrorBitmap = NOMIRRORBITMAP,
  /// Copies inverted source to destination
  NotSrcCopy = NOTSRCCOPY,
  /// Combines source and dest with OR, the inverts
  NotSrcErase = NOTSRCERASE,
  /// Copies the brush into the dest
  PatCopy = PATCOPY,
  /// XOR brush with dest
  PatInvert = PATINVERT,
  /// Combine brush with inverted source with OR, then OR with dest
  PatPaint = PATPAINT,
  /// Source AND dest
  SrcAnd = SRCAND,
  /// Copies the source to the destination
  SrcCopy = SRCCOPY,
  /// Source AND inverted dest
  SrcErase = SRCERASE,
  /// Source XOR dest
  SrcInvert = SRCINVERT,
  /// Source OR dest
  SrcPaint = SRCPAINT,
  /// Fill dest with index 1 of physical palette (default to white)
  Whiteness = WHITENESS,
}
impl Default for RasterOp {
  fn default() -> Self {
    RasterOp::SrcCopy
  }
}

/// Use with [`stretch_di_bits`](stretch_di_bits)
#[derive(Debug, Clone, Copy)]
pub struct StretchDIBitsArgs {
  /// Destination device context handle
  pub hdc: HDC,
  /// From upper left origin, logical units
  pub dest: PointSizeRect,
  /// From upper left origin, logical units
  pub src: PointSizeRect,
  /// Image data
  pub bits: *const c_void,
  /// Image format information
  pub bitmap_info: *const BITMAPINFO,
  /// Describes `bmiColors` in the `bitmap_info`
  pub usage: DibColors,
  /// How to rasterize the data.
  pub raster_op: RasterOp,
}

/// See [`StretchDIBits`](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-stretchdibits)
#[inline]
pub unsafe fn stretch_di_bits(args: StretchDIBitsArgs) -> Option<i32> {
  let result = StretchDIBits(
    args.hdc,
    args.dest.x,
    args.dest.y,
    args.dest.width,
    args.dest.height,
    args.src.x,
    args.src.y,
    args.src.width,
    args.src.height,
    args.bits as *const _,
    args.bitmap_info,
    args.usage as u32,
    args.raster_op as u32,
  );
  if result >= 0 {
    Some(result)
  } else {
    None
  }
}