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