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::slice;
6 use std::cell::UnsafeCell;
7 use std::mem::{zeroed, size_of};
8 
9 use comptr::ComPtr;
10 use winapi;
11 use gdi32;
12 use super::{FontFace, RenderingParams};
13 
14 #[derive(Debug)]
15 pub struct BitmapRenderTarget {
16     native: UnsafeCell<ComPtr<winapi::IDWriteBitmapRenderTarget>>,
17 }
18 
19 impl BitmapRenderTarget {
take(native: ComPtr<winapi::IDWriteBitmapRenderTarget>) -> BitmapRenderTarget20     pub fn take(native: ComPtr<winapi::IDWriteBitmapRenderTarget>) -> BitmapRenderTarget {
21         BitmapRenderTarget {
22             native: UnsafeCell::new(native),
23         }
24     }
25 
as_ptr(&self) -> *mut winapi::IDWriteBitmapRenderTarget26     pub unsafe fn as_ptr(&self) -> *mut winapi::IDWriteBitmapRenderTarget {
27         (*self.native.get()).as_ptr()
28     }
29 
30     // 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)31     pub fn set_pixels_per_dip(&self, ppd: f32) {
32         unsafe {
33             (*self.native.get()).SetPixelsPerDip(ppd);
34         }
35     }
36 
get_memory_dc(&self) -> winapi::HDC37     pub fn get_memory_dc(&self) -> winapi::HDC {
38         unsafe {
39             (*self.native.get()).GetMemoryDC()
40         }
41     }
42 
draw_glyph_run(&self, baseline_origin_x: f32, baseline_origin_y: f32, measuring_mode: winapi::DWRITE_MEASURING_MODE, font_face: &FontFace, em_size: f32, glyph_indices: &[u16], glyph_advances: &[f32], glyph_offsets: &[winapi::DWRITE_GLYPH_OFFSET], rendering_params: &RenderingParams, color: &(f32, f32, f32)) -> winapi::RECT43     pub fn draw_glyph_run(&self,
44                           baseline_origin_x: f32,
45                           baseline_origin_y: f32,
46                           measuring_mode: winapi::DWRITE_MEASURING_MODE,
47                           font_face: &FontFace,
48                           em_size: f32,
49                           glyph_indices: &[u16],
50                           glyph_advances: &[f32],
51                           glyph_offsets: &[winapi::DWRITE_GLYPH_OFFSET],
52                           rendering_params: &RenderingParams,
53                           color: &(f32, f32, f32))
54         -> winapi::RECT
55     {
56         unsafe {
57             assert!(glyph_indices.len() == glyph_advances.len());
58             assert!(glyph_indices.len() == glyph_offsets.len());
59 
60             let r = (color.0 * 255.0) as u8;
61             let g = (color.1 * 255.0) as u8;
62             let b = (color.2 * 255.0) as u8;
63 
64             let mut glyph_run: winapi::DWRITE_GLYPH_RUN = zeroed();
65             glyph_run.fontFace = font_face.as_ptr();
66             glyph_run.fontEmSize = em_size;
67             glyph_run.glyphCount = glyph_indices.len() as u32;
68             glyph_run.glyphIndices = glyph_indices.as_ptr();
69             glyph_run.glyphAdvances = glyph_advances.as_ptr();
70             glyph_run.glyphOffsets = glyph_offsets.as_ptr();
71             glyph_run.isSideways = 0;
72             glyph_run.bidiLevel = 0;
73 
74             let mut rect: winapi::RECT = zeroed();
75             let hr = (*self.native.get()).DrawGlyphRun(baseline_origin_x,
76                                                        baseline_origin_y,
77                                                        measuring_mode,
78                                                        &glyph_run,
79                                                        rendering_params.as_ptr(),
80                                                        winapi::RGB(r,g,b),
81                                                        &mut rect);
82             assert!(hr == 0);
83             rect
84         }
85     }
86 
87     // This function expects to have glyphs rendered in WHITE,
88     // and pulls out a u8 vector of width*height*4 size with
89     // the coverage value (we pull out R) broadcast to the alpha
90     // channel, with the color white.  That is, it performs:
91     // RGBX -> xxxR, where xxx = 0xff
get_opaque_values_as_mask(&self) -> Vec<u8>92     pub fn get_opaque_values_as_mask(&self) -> Vec<u8> {
93         // Now grossness to pull out the pixels
94         unsafe {
95             let memory_dc = self.get_memory_dc();
96             let mut bitmap: winapi::BITMAP = zeroed();
97             let ret = gdi32::GetObjectW(gdi32::GetCurrentObject(memory_dc, winapi::OBJ_BITMAP),
98                                         size_of::<winapi::BITMAP>() as i32,
99                                         &mut bitmap as *mut _ as *mut winapi::c_void);
100             assert!(ret == size_of::<winapi::BITMAP>() as i32);
101             assert!(bitmap.bmBitsPixel == 32);
102 
103             let width = bitmap.bmWidth as usize;
104             let stride = bitmap.bmWidthBytes as usize;
105             let height = bitmap.bmHeight as usize;
106 
107             let mut out_bytes: Vec<u8> = vec![0; width * height * 4];
108             let mut out_u32 = slice::from_raw_parts_mut(out_bytes.as_mut_ptr() as *mut u32,
109                                                         width * height);
110 
111             for row in 0..height {
112                 let in_offset = (row * stride) as isize;
113                 let in_u32 = slice::from_raw_parts(bitmap.bmBits.offset(in_offset) as *const u32,
114                                                    width);
115                 for col in 0..width {
116                     let r = in_u32[col] & 0xff;
117                     out_u32[width*row + col] = (r << 24) | (0x00ffffffu32);
118                 }
119             }
120 
121             out_bytes
122         }
123     }
124 }
125