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