1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use std::cell::UnsafeCell;
6 use std::mem::{size_of, zeroed};
7 use std::slice;
8 use winapi::ctypes::c_void;
9 use winapi::shared::windef::{HDC, RECT};
10 use winapi::um::dcommon::DWRITE_MEASURING_MODE;
11 use winapi::um::dwrite::IDWriteBitmapRenderTarget;
12 use winapi::um::dwrite::{DWRITE_GLYPH_OFFSET, DWRITE_GLYPH_RUN};
13 use winapi::um::wingdi::{GetCurrentObject, GetObjectW, BITMAP, OBJ_BITMAP, RGB};
14 use wio::com::ComPtr;
15 
16 use super::{FontFace, RenderingParams};
17 
18 pub struct BitmapRenderTarget {
19     native: UnsafeCell<ComPtr<IDWriteBitmapRenderTarget>>,
20 }
21 
22 impl BitmapRenderTarget {
take(native: ComPtr<IDWriteBitmapRenderTarget>) -> BitmapRenderTarget23     pub fn take(native: ComPtr<IDWriteBitmapRenderTarget>) -> BitmapRenderTarget {
24         BitmapRenderTarget {
25             native: UnsafeCell::new(native),
26         }
27     }
28 
as_ptr(&self) -> *mut IDWriteBitmapRenderTarget29     pub unsafe fn as_ptr(&self) -> *mut IDWriteBitmapRenderTarget {
30         (*self.native.get()).as_raw()
31     }
32 
33     // A dip is 1/96th of an inch, so this value is the number of pixels per inch divided by 96.
set_pixels_per_dip(&self, ppd: f32)34     pub fn set_pixels_per_dip(&self, ppd: f32) {
35         unsafe {
36             (*self.native.get()).SetPixelsPerDip(ppd);
37         }
38     }
39 
get_memory_dc(&self) -> HDC40     pub fn get_memory_dc(&self) -> HDC {
41         unsafe { (*self.native.get()).GetMemoryDC() }
42     }
43 
draw_glyph_run( &self, baseline_origin_x: f32, baseline_origin_y: f32, measuring_mode: DWRITE_MEASURING_MODE, font_face: &FontFace, em_size: f32, glyph_indices: &[u16], glyph_advances: &[f32], glyph_offsets: &[DWRITE_GLYPH_OFFSET], rendering_params: &RenderingParams, color: &(f32, f32, f32), ) -> RECT44     pub fn draw_glyph_run(
45         &self,
46         baseline_origin_x: f32,
47         baseline_origin_y: f32,
48         measuring_mode: DWRITE_MEASURING_MODE,
49         font_face: &FontFace,
50         em_size: f32,
51         glyph_indices: &[u16],
52         glyph_advances: &[f32],
53         glyph_offsets: &[DWRITE_GLYPH_OFFSET],
54         rendering_params: &RenderingParams,
55         color: &(f32, f32, f32),
56     ) -> RECT {
57         unsafe {
58             assert!(glyph_indices.len() == glyph_advances.len());
59             assert!(glyph_indices.len() == glyph_offsets.len());
60 
61             let r = (color.0 * 255.0) as u8;
62             let g = (color.1 * 255.0) as u8;
63             let b = (color.2 * 255.0) as u8;
64 
65             let mut glyph_run: DWRITE_GLYPH_RUN = zeroed();
66             glyph_run.fontFace = font_face.as_ptr();
67             glyph_run.fontEmSize = em_size;
68             glyph_run.glyphCount = glyph_indices.len() as u32;
69             glyph_run.glyphIndices = glyph_indices.as_ptr();
70             glyph_run.glyphAdvances = glyph_advances.as_ptr();
71             glyph_run.glyphOffsets = glyph_offsets.as_ptr();
72             glyph_run.isSideways = 0;
73             glyph_run.bidiLevel = 0;
74 
75             let mut rect: RECT = zeroed();
76             let hr = (*self.native.get()).DrawGlyphRun(
77                 baseline_origin_x,
78                 baseline_origin_y,
79                 measuring_mode,
80                 &glyph_run,
81                 rendering_params.as_ptr(),
82                 RGB(r, g, b),
83                 &mut rect,
84             );
85             assert!(hr == 0);
86             rect
87         }
88     }
89 
90     // This function expects to have glyphs rendered in WHITE,
91     // and pulls out a u8 vector of width*height*4 size with
92     // the coverage value (we pull out R) broadcast to the alpha
93     // channel, with the color white.  That is, it performs:
94     // RGBX -> xxxR, where xxx = 0xff
get_opaque_values_as_mask(&self) -> Vec<u8>95     pub fn get_opaque_values_as_mask(&self) -> Vec<u8> {
96         // Now grossness to pull out the pixels
97         unsafe {
98             let memory_dc = self.get_memory_dc();
99             let mut bitmap: BITMAP = zeroed();
100             let ret = GetObjectW(
101                 GetCurrentObject(memory_dc, OBJ_BITMAP),
102                 size_of::<BITMAP>() as i32,
103                 &mut bitmap as *mut _ as *mut c_void,
104             );
105             assert!(ret == size_of::<BITMAP>() as i32);
106             assert!(bitmap.bmBitsPixel == 32);
107 
108             let width = bitmap.bmWidth as usize;
109             let stride = bitmap.bmWidthBytes as usize;
110             let height = bitmap.bmHeight as usize;
111 
112             let mut out_bytes: Vec<u8> = vec![0; width * height * 4];
113             let out_u32 =
114                 slice::from_raw_parts_mut(out_bytes.as_mut_ptr() as *mut u32, width * height);
115 
116             for row in 0..height {
117                 let in_offset = (row * stride) as isize;
118                 let in_u32 =
119                     slice::from_raw_parts(bitmap.bmBits.offset(in_offset) as *const u32, width);
120                 for col in 0..width {
121                     let r = in_u32[col] & 0xff;
122                     out_u32[width * row + col] = (r << 24) | (0x00ffffffu32);
123                 }
124             }
125 
126             out_bytes
127         }
128     }
129 }
130