<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{FontInstanceKey, FontKey, FontRenderMode, GlyphDimensions};
use api::{NativeFontHandle, SubpixelDirection};
use api::{GlyphKey};
use internal_types::FastHashMap;

use freetype::freetype::{FT_Render_Mode, FT_Pixel_Mode, FT_BBox, FT_Outline_Translate};
use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter};
use freetype::freetype::{FT_Library, FT_Set_Char_Size, FT_Outline_Get_CBox};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6, FT_Glyph_Format};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
use freetype::freetype::{FT_Done_Face, FT_Error, FT_Int32, FT_Get_Char_Index};

use std::{mem, ptr, slice};

// This constant is not present in the freetype
// bindings due to bindgen not handling the way
// the macro is defined.
const FT_LOAD_TARGET_LIGHT: FT_Int32 = 1 << 16;

// Default to slight hinting, which is what most
// Linux distros use by default, and is a better
// default than no hinting.
// TODO(gw): Make this configurable.
const GLYPH_LOAD_FLAGS: FT_Int32 = FT_LOAD_TARGET_LIGHT;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: FastHashMap<FontKey, Face>,
    lcd_extra_pixels: i64,
}

// FreeType resources are safe to move between threads as long as they
// are not concurrently accessed. In our case, everything is hidden inside
// a given FontContext so it is safe to move the latter between threads.
unsafe impl Send for FontContext {}

pub struct RasterizedGlyph {
    pub top: f32,
    pub left: f32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

const SUCCESS: FT_Error = FT_Error(0);

impl FontContext {
    pub fn new() -> FontContext {
        let mut lib: FT_Library = ptr::null_mut();

        // Per Skia, using a filter adds one full pixel to each side.
        let mut lcd_extra_pixels = 1;

        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            assert!(result.succeeded(), "Unable to initialize FreeType library {:?}", result);

            // TODO(gw): Check result of this to determine if freetype build supports subpixel.
            let result = FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);

            if !result.succeeded() {
                println!("WARN: Initializing a FreeType library build without subpixel AA enabled!");
                lcd_extra_pixels = 0;
            }
        }

        FontContext {
            lib,
            faces: FastHashMap::default(),
            lcd_extra_pixels: lcd_extra_pixels,
        }
    }

    pub fn has_font(&self, font_key: &FontKey) -> bool {
        self.faces.contains_key(font_key)
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   index as FT_Long,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn delete_font(&mut self, font_key: &FontKey) {
        if let Some(face) = self.faces.remove(font_key) {
            let result = unsafe {
                FT_Done_Face(face.face)
            };
            assert!(result.succeeded());
        }
    }

    fn load_glyph(&self,
                  font: &FontInstanceKey,
                  glyph: &GlyphKey) -> Option<FT_GlyphSlot> {

        debug_assert!(self.faces.contains_key(&font.font_key));
        let face = self.faces.get(&font.font_key).unwrap();
        let char_size = font.size.to_f64_px() * 64.0 + 0.5;

        assert_eq!(SUCCESS, unsafe {
            FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0)
        });

        let result = unsafe {
            FT_Load_Glyph(face.face,
                          glyph.index as FT_UInt,
                          GLYPH_LOAD_FLAGS)
        };

        if result == SUCCESS {
            let slot = unsafe { (*face.face).glyph };
            assert!(slot != ptr::null_mut());

            // TODO(gw): We use the FT_Outline_* APIs to manage sub-pixel offsets.
            //           We will need a custom code path for bitmap fonts (which
            //           are very rare).
            match unsafe { (*slot).format } {
                FT_Glyph_Format::FT_GLYPH_FORMAT_OUTLINE => {
                    Some(slot)
                }
                _ => {
                    error!("TODO: Support bitmap fonts!");
                    None
                }
            }
        } else {
            error!("Unable to load glyph for {} of size {:?} from font {:?}, {:?}",
                glyph.index, font.size, font.font_key, result);
            None
        }
    }

    // Get the bounding box for a glyph, accounting for sub-pixel positioning.
    fn get_bounding_box(&self,
                        slot: FT_GlyphSlot,
                        font: &FontInstanceKey,
                        glyph: &GlyphKey) -> FT_BBox {
        let mut cbox: FT_BBox = unsafe { mem::uninitialized() };

        // Get the estimated bounding box from FT (control points).
        unsafe {
            FT_Outline_Get_CBox(&(*slot).outline, &mut cbox);
        }

        // Convert the subpixel offset to floats.
        let (dx, dy) = font.get_subpx_offset(glyph);

        // Apply extra pixel of padding for subpixel AA, due to the filter.
        let padding = match font.render_mode {
            FontRenderMode::Subpixel => self.lcd_extra_pixels * 64,
            FontRenderMode::Alpha | FontRenderMode::Mono => 0,
        };
        cbox.xMin -= padding;
        cbox.xMax += padding;

        // Offset the bounding box by subpixel positioning.
        // Convert to 26.6 fixed point format for FT.
        match font.subpx_dir {
            SubpixelDirection::None => {}
            SubpixelDirection::Horizontal => {
                let dx = (dx * 64.0 + 0.5) as FT_Long;
                cbox.xMin += dx;
                cbox.xMax += dx;
            }
            SubpixelDirection::Vertical => {
                let dy = (dy * 64.0 + 0.5) as FT_Long;
                cbox.yMin += dy;
                cbox.yMax += dy;
            }
        }

        // Outset the box to device pixel boundaries
        cbox.xMin &= !63;
        cbox.yMin &= !63;
        cbox.xMax = (cbox.xMax + 63) & !63;
        cbox.yMax = (cbox.yMax + 63) & !63;

        cbox
    }

    fn get_glyph_dimensions_impl(&self,
                                 slot: FT_GlyphSlot,
                                 font: &FontInstanceKey,
                                 glyph: &GlyphKey) -> Option<GlyphDimensions> {
        let metrics = unsafe { &(*slot).metrics };

        // If there's no advance, no need to consider this glyph
        // for layout.
        if metrics.horiAdvance == 0 {
            None
        } else {
            let cbox = self.get_bounding_box(slot, font, glyph);

            Some(GlyphDimensions {
                left: (cbox.xMin >> 6) as i32,
                top: (cbox.yMax >> 6) as i32,
                width: ((cbox.xMax - cbox.xMin) >> 6) as u32,
                height: ((cbox.yMax - cbox.yMin) >> 6) as u32,
                advance: metrics.horiAdvance as f32 / 64.0,
            })
        }
    }

    pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
        let face = self.faces
                       .get(&font_key)
                       .expect("Unknown font key!");
        unsafe {
            let idx = FT_Get_Char_Index(face.face, ch as _);
            if idx != 0 {
                Some(idx)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                font: &FontInstanceKey,
                                key: &GlyphKey) -> Option<GlyphDimensions> {
        let slot = self.load_glyph(font, key);
        slot.and_then(|slot| {
            self.get_glyph_dimensions_impl(slot, font, key)
        })
    }

    pub fn rasterize_glyph(&mut self,
                           font: &FontInstanceKey,
                           key: &GlyphKey)
                           -> Option<RasterizedGlyph> {

        let slot = match self.load_glyph(font, key) {
            Some(slot) => slot,
            None => return None,
        };

        let render_mode = match font.render_mode {
            FontRenderMode::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
            FontRenderMode::Alpha => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
            FontRenderMode::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
        };

        // Get dimensions of the glyph, to see if we need to rasterize it.
        let dimensions = match self.get_glyph_dimensions_impl(slot, font, key) {
            Some(val) => val,
            None => return None,
        };

        // For spaces and other non-printable characters, early out.
        if dimensions.width == 0 || dimensions.height == 0 {
            return None;
        }

        // Get the subpixel offsets in FT 26.6 format.
        let (dx, dy) = font.get_subpx_offset(key);
        let dx = (dx * 64.0 + 0.5) as FT_Long;
        let dy = (dy * 64.0 + 0.5) as FT_Long;

        // Move the outline curves to be at the origin, taking
        // into account the subpixel positioning.
        unsafe {
            let outline = &(*slot).outline;
            let mut cbox: FT_BBox = mem::uninitialized();
            FT_Outline_Get_CBox(outline, &mut cbox);
            FT_Outline_Translate(outline, dx - ((cbox.xMin + dx) & !63),
                                          dy - ((cbox.yMin + dy) & !63));
        }

        let result = unsafe { FT_Render_Glyph(slot, render_mode) };
        if result != SUCCESS {
            error!("Unable to rasterize {:?} with {:?}, {:?}", key, render_mode, result);
            return None;
        }

        let bitmap = unsafe { &(*slot).bitmap };
        let pixel_mode = unsafe { mem::transmute(bitmap.pixel_mode as u32) };
        info!("Rasterizing {:?} as {:?} with dimensions {:?}", key, render_mode, dimensions);

        let actual_width = match pixel_mode {
            FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                assert!(bitmap.width % 3 == 0);
                bitmap.width / 3
            },
            FT_Pixel_Mode::FT_PIXEL_MODE_MONO |
            FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                bitmap.width
            }
            _ => {
                panic!("Unexpected pixel mode!");
            }
        } as i32;

        let actual_height = bitmap.rows as i32;
        let top = unsafe { (*slot).bitmap_top };
        let left = unsafe { (*slot).bitmap_left };
        let mut final_buffer = vec![0; (actual_width * actual_height * 4) as usize];

        // Extract the final glyph from FT format into RGBA8 format, which is
        // what WR expects.
        for y in 0..actual_height {
            // Get pointer to the bytes for this row.
            let mut src = unsafe {
                bitmap.buffer.offset((y * bitmap.pitch) as isize)
            };

            for x in 0..actual_width {
                let value = match pixel_mode {
                    FT_Pixel_Mode::FT_PIXEL_MODE_MONO => {
                        let mask = 0x80 >> (x & 0x7);
                        let byte = unsafe { *src.offset((x >> 3) as isize) };
                        let alpha = if byte & mask != 0 { 0xff } else { 0 };
                        [0xff, 0xff, 0xff, alpha]
                    }
                    FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                        let alpha = unsafe { *src };
                        src = unsafe { src.offset(1) };
                        [0xff, 0xff, 0xff, alpha]
                    }
                    FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                        let t = unsafe { slice::from_raw_parts(src, 3) };
                        src = unsafe { src.offset(3) };
                        [t[2], t[1], t[0], 0xff]
                    }
                    _ => panic!("Unsupported {:?}", pixel_mode)
                };
                let i = 4 * (y * actual_width + x) as usize;
                let dest = &mut final_buffer[i..i+4];
                dest.clone_from_slice(&value);
            }
        }

        Some(RasterizedGlyph {
            left: (dimensions.left + left) as f32,
            top: (dimensions.top + top - actual_height) as f32,
            width: actual_width as u32,
            height: actual_height as u32,
            bytes: final_buffer,
        })
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<commit_msg>Auto merge of #1557 - glennw:fix-arm32, r=emilio<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{FontInstanceKey, FontKey, FontRenderMode, GlyphDimensions};
use api::{NativeFontHandle, SubpixelDirection};
use api::{GlyphKey};
use internal_types::FastHashMap;

use freetype::freetype::{FT_Render_Mode, FT_Pixel_Mode, FT_BBox, FT_Outline_Translate};
use freetype::freetype::{FT_Done_FreeType, FT_Library_SetLcdFilter, FT_Pos};
use freetype::freetype::{FT_Library, FT_Set_Char_Size, FT_Outline_Get_CBox};
use freetype::freetype::{FT_Face, FT_Long, FT_UInt, FT_F26Dot6, FT_Glyph_Format};
use freetype::freetype::{FT_Init_FreeType, FT_Load_Glyph, FT_Render_Glyph};
use freetype::freetype::{FT_New_Memory_Face, FT_GlyphSlot, FT_LcdFilter};
use freetype::freetype::{FT_Done_Face, FT_Error, FT_Int32, FT_Get_Char_Index};

use std::{mem, ptr, slice};

// This constant is not present in the freetype
// bindings due to bindgen not handling the way
// the macro is defined.
const FT_LOAD_TARGET_LIGHT: FT_Int32 = 1 << 16;

// Default to slight hinting, which is what most
// Linux distros use by default, and is a better
// default than no hinting.
// TODO(gw): Make this configurable.
const GLYPH_LOAD_FLAGS: FT_Int32 = FT_LOAD_TARGET_LIGHT;

struct Face {
    face: FT_Face,
}

pub struct FontContext {
    lib: FT_Library,
    faces: FastHashMap<FontKey, Face>,
    lcd_extra_pixels: i64,
}

// FreeType resources are safe to move between threads as long as they
// are not concurrently accessed. In our case, everything is hidden inside
// a given FontContext so it is safe to move the latter between threads.
unsafe impl Send for FontContext {}

pub struct RasterizedGlyph {
    pub top: f32,
    pub left: f32,
    pub width: u32,
    pub height: u32,
    pub bytes: Vec<u8>,
}

const SUCCESS: FT_Error = FT_Error(0);

impl FontContext {
    pub fn new() -> FontContext {
        let mut lib: FT_Library = ptr::null_mut();

        // Per Skia, using a filter adds one full pixel to each side.
        let mut lcd_extra_pixels = 1;

        unsafe {
            let result = FT_Init_FreeType(&mut lib);
            assert!(result.succeeded(), "Unable to initialize FreeType library {:?}", result);

            // TODO(gw): Check result of this to determine if freetype build supports subpixel.
            let result = FT_Library_SetLcdFilter(lib, FT_LcdFilter::FT_LCD_FILTER_DEFAULT);

            if !result.succeeded() {
                println!("WARN: Initializing a FreeType library build without subpixel AA enabled!");
                lcd_extra_pixels = 0;
            }
        }

        FontContext {
            lib,
            faces: FastHashMap::default(),
            lcd_extra_pixels: lcd_extra_pixels,
        }
    }

    pub fn has_font(&self, font_key: &FontKey) -> bool {
        self.faces.contains_key(font_key)
    }

    pub fn add_raw_font(&mut self, font_key: &FontKey, bytes: &[u8], index: u32) {
        if !self.faces.contains_key(&font_key) {
            let mut face: FT_Face = ptr::null_mut();
            let result = unsafe {
                FT_New_Memory_Face(self.lib,
                                   bytes.as_ptr(),
                                   bytes.len() as FT_Long,
                                   index as FT_Long,
                                   &mut face)
            };
            if result.succeeded() && !face.is_null() {
                self.faces.insert(*font_key, Face {
                    face,
                    //_bytes: bytes
                });
            } else {
                println!("WARN: webrender failed to load font {:?}", font_key);
            }
        }
    }

    pub fn add_native_font(&mut self, _font_key: &FontKey, _native_font_handle: NativeFontHandle) {
        panic!("TODO: Not supported on Linux");
    }

    pub fn delete_font(&mut self, font_key: &FontKey) {
        if let Some(face) = self.faces.remove(font_key) {
            let result = unsafe {
                FT_Done_Face(face.face)
            };
            assert!(result.succeeded());
        }
    }

    fn load_glyph(&self,
                  font: &FontInstanceKey,
                  glyph: &GlyphKey) -> Option<FT_GlyphSlot> {

        debug_assert!(self.faces.contains_key(&font.font_key));
        let face = self.faces.get(&font.font_key).unwrap();
        let char_size = font.size.to_f64_px() * 64.0 + 0.5;

        assert_eq!(SUCCESS, unsafe {
            FT_Set_Char_Size(face.face, char_size as FT_F26Dot6, 0, 0, 0)
        });

        let result = unsafe {
            FT_Load_Glyph(face.face,
                          glyph.index as FT_UInt,
                          GLYPH_LOAD_FLAGS)
        };

        if result == SUCCESS {
            let slot = unsafe { (*face.face).glyph };
            assert!(slot != ptr::null_mut());

            // TODO(gw): We use the FT_Outline_* APIs to manage sub-pixel offsets.
            //           We will need a custom code path for bitmap fonts (which
            //           are very rare).
            match unsafe { (*slot).format } {
                FT_Glyph_Format::FT_GLYPH_FORMAT_OUTLINE => {
                    Some(slot)
                }
                _ => {
                    error!("TODO: Support bitmap fonts!");
                    None
                }
            }
        } else {
            error!("Unable to load glyph for {} of size {:?} from font {:?}, {:?}",
                glyph.index, font.size, font.font_key, result);
            None
        }
    }

    // Get the bounding box for a glyph, accounting for sub-pixel positioning.
    fn get_bounding_box(&self,
                        slot: FT_GlyphSlot,
                        font: &FontInstanceKey,
                        glyph: &GlyphKey) -> FT_BBox {
        let mut cbox: FT_BBox = unsafe { mem::uninitialized() };

        // Get the estimated bounding box from FT (control points).
        unsafe {
            FT_Outline_Get_CBox(&(*slot).outline, &mut cbox);
        }

        // Convert the subpixel offset to floats.
        let (dx, dy) = font.get_subpx_offset(glyph);

        // Apply extra pixel of padding for subpixel AA, due to the filter.
        let padding = match font.render_mode {
            FontRenderMode::Subpixel => self.lcd_extra_pixels * 64,
            FontRenderMode::Alpha | FontRenderMode::Mono => 0,
        };
        cbox.xMin -= padding as FT_Pos;
        cbox.xMax += padding as FT_Pos;

        // Offset the bounding box by subpixel positioning.
        // Convert to 26.6 fixed point format for FT.
        match font.subpx_dir {
            SubpixelDirection::None => {}
            SubpixelDirection::Horizontal => {
                let dx = (dx * 64.0 + 0.5) as FT_Long;
                cbox.xMin += dx;
                cbox.xMax += dx;
            }
            SubpixelDirection::Vertical => {
                let dy = (dy * 64.0 + 0.5) as FT_Long;
                cbox.yMin += dy;
                cbox.yMax += dy;
            }
        }

        // Outset the box to device pixel boundaries
        cbox.xMin &= !63;
        cbox.yMin &= !63;
        cbox.xMax = (cbox.xMax + 63) & !63;
        cbox.yMax = (cbox.yMax + 63) & !63;

        cbox
    }

    fn get_glyph_dimensions_impl(&self,
                                 slot: FT_GlyphSlot,
                                 font: &FontInstanceKey,
                                 glyph: &GlyphKey) -> Option<GlyphDimensions> {
        let metrics = unsafe { &(*slot).metrics };

        // If there's no advance, no need to consider this glyph
        // for layout.
        if metrics.horiAdvance == 0 {
            None
        } else {
            let cbox = self.get_bounding_box(slot, font, glyph);

            Some(GlyphDimensions {
                left: (cbox.xMin >> 6) as i32,
                top: (cbox.yMax >> 6) as i32,
                width: ((cbox.xMax - cbox.xMin) >> 6) as u32,
                height: ((cbox.yMax - cbox.yMin) >> 6) as u32,
                advance: metrics.horiAdvance as f32 / 64.0,
            })
        }
    }

    pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
        let face = self.faces
                       .get(&font_key)
                       .expect("Unknown font key!");
        unsafe {
            let idx = FT_Get_Char_Index(face.face, ch as _);
            if idx != 0 {
                Some(idx)
            } else {
                None
            }
        }
    }

    pub fn get_glyph_dimensions(&mut self,
                                font: &FontInstanceKey,
                                key: &GlyphKey) -> Option<GlyphDimensions> {
        let slot = self.load_glyph(font, key);
        slot.and_then(|slot| {
            self.get_glyph_dimensions_impl(slot, font, key)
        })
    }

    pub fn rasterize_glyph(&mut self,
                           font: &FontInstanceKey,
                           key: &GlyphKey)
                           -> Option<RasterizedGlyph> {

        let slot = match self.load_glyph(font, key) {
            Some(slot) => slot,
            None => return None,
        };

        let render_mode = match font.render_mode {
            FontRenderMode::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
            FontRenderMode::Alpha => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
            FontRenderMode::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
        };

        // Get dimensions of the glyph, to see if we need to rasterize it.
        let dimensions = match self.get_glyph_dimensions_impl(slot, font, key) {
            Some(val) => val,
            None => return None,
        };

        // For spaces and other non-printable characters, early out.
        if dimensions.width == 0 || dimensions.height == 0 {
            return None;
        }

        // Get the subpixel offsets in FT 26.6 format.
        let (dx, dy) = font.get_subpx_offset(key);
        let dx = (dx * 64.0 + 0.5) as FT_Long;
        let dy = (dy * 64.0 + 0.5) as FT_Long;

        // Move the outline curves to be at the origin, taking
        // into account the subpixel positioning.
        unsafe {
            let outline = &(*slot).outline;
            let mut cbox: FT_BBox = mem::uninitialized();
            FT_Outline_Get_CBox(outline, &mut cbox);
            FT_Outline_Translate(outline, dx - ((cbox.xMin + dx) & !63),
                                          dy - ((cbox.yMin + dy) & !63));
        }

        let result = unsafe { FT_Render_Glyph(slot, render_mode) };
        if result != SUCCESS {
            error!("Unable to rasterize {:?} with {:?}, {:?}", key, render_mode, result);
            return None;
        }

        let bitmap = unsafe { &(*slot).bitmap };
        let pixel_mode = unsafe { mem::transmute(bitmap.pixel_mode as u32) };
        info!("Rasterizing {:?} as {:?} with dimensions {:?}", key, render_mode, dimensions);

        let actual_width = match pixel_mode {
            FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                assert!(bitmap.width % 3 == 0);
                bitmap.width / 3
            },
            FT_Pixel_Mode::FT_PIXEL_MODE_MONO |
            FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                bitmap.width
            }
            _ => {
                panic!("Unexpected pixel mode!");
            }
        } as i32;

        let actual_height = bitmap.rows as i32;
        let top = unsafe { (*slot).bitmap_top };
        let left = unsafe { (*slot).bitmap_left };
        let mut final_buffer = vec![0; (actual_width * actual_height * 4) as usize];

        // Extract the final glyph from FT format into RGBA8 format, which is
        // what WR expects.
        for y in 0..actual_height {
            // Get pointer to the bytes for this row.
            let mut src = unsafe {
                bitmap.buffer.offset((y * bitmap.pitch) as isize)
            };

            for x in 0..actual_width {
                let value = match pixel_mode {
                    FT_Pixel_Mode::FT_PIXEL_MODE_MONO => {
                        let mask = 0x80 >> (x & 0x7);
                        let byte = unsafe { *src.offset((x >> 3) as isize) };
                        let alpha = if byte & mask != 0 { 0xff } else { 0 };
                        [0xff, 0xff, 0xff, alpha]
                    }
                    FT_Pixel_Mode::FT_PIXEL_MODE_GRAY => {
                        let alpha = unsafe { *src };
                        src = unsafe { src.offset(1) };
                        [0xff, 0xff, 0xff, alpha]
                    }
                    FT_Pixel_Mode::FT_PIXEL_MODE_LCD => {
                        let t = unsafe { slice::from_raw_parts(src, 3) };
                        src = unsafe { src.offset(3) };
                        [t[2], t[1], t[0], 0xff]
                    }
                    _ => panic!("Unsupported {:?}", pixel_mode)
                };
                let i = 4 * (y * actual_width + x) as usize;
                let dest = &mut final_buffer[i..i+4];
                dest.clone_from_slice(&value);
            }
        }

        Some(RasterizedGlyph {
            left: (dimensions.left + left) as f32,
            top: (dimensions.top + top - actual_height) as f32,
            width: actual_width as u32,
            height: actual_height as u32,
            bytes: final_buffer,
        })
    }
}

impl Drop for FontContext {
    fn drop(&mut self) {
        unsafe {
            FT_Done_FreeType(self.lib);
        }
    }
}
<|endoftext|>


<commit_before>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous
//! code:
//!
//! - [Futures](crate::future::Future) are single eventual values produced by
//!   asychronous computations. Some programming languages (e.g. JavaScript)
//!   call this concept "promise".
//! - [Streams](crate::stream::Stream) represent a series of values
//!   produced asynchronously.
//! - [Sinks](crate::sink::Sink) provide support for asynchronous writing of
//!   data.
//! - [Executors](crate::executor) are responsible for running asynchronous
//!   tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](crate::io) and
//! [cross-task communication](crate::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![feature(pin, arbitrary_self_types, futures_api)]

#![cfg_attr(not(feature = "std"), no_std)]

#![warn(missing_docs, missing_debug_implementations)]
#![deny(bare_trait_objects)]

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.10/futures")]

#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]

#[doc(hidden)] pub use futures_util::core_reexport;

#[doc(hidden)] pub use futures_core::future::Future;
#[doc(hidden)] pub use futures_core::future::TryFuture;
#[doc(hidden)] pub use futures_util::future::FutureExt;
#[doc(hidden)] pub use futures_util::try_future::TryFutureExt;

#[doc(hidden)] pub use futures_core::stream::Stream;
#[doc(hidden)] pub use futures_core::stream::TryStream;
#[doc(hidden)] pub use futures_util::stream::StreamExt;
#[doc(hidden)] pub use futures_util::try_stream::TryStreamExt;

#[doc(hidden)] pub use futures_sink::Sink;
#[doc(hidden)] pub use futures_util::sink::SinkExt;

#[doc(hidden)] pub use futures_core::task::Poll;

// Macro reexports
pub use futures_util::{
    // Error/readiness propagation
    try_ready, try_poll, ready,
};
#[cfg(feature = "std")]
pub use futures_util::{
    // Async-await
    join, try_join, pending, poll,
};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](crate::channel::oneshot), a way of sending a single value
    //!   from one task to another.
    //! - [mpsc](crate::channel::mpsc), a multi-producer, single-consumer
    //!   channel for sending values between tasks, analogous to the
    //!   similarly-named structure in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "compat")]
pub mod compat {
    //! Interop between `futures` 0.1 and 0.3.

    pub use futures_util::compat::{
        Compat,
        Compat01As03,
        Executor01Future,
        Executor01As03,
        Executor01CompatExt,
        Future01CompatExt,
        Stream01CompatExt,
    };

    #[cfg(feature = "tokio-compat")]
    pub use futures_util::compat::TokioDefaultSpawner;
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](crate::executor::ThreadPool). A small set of worker threads can
    //! handle a very large set of spawned tasks (which are much lighter weight
    //! than threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](crate::executor::ThreadPool::run) an initial task on it, which
    //! can then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! #![feature(pin, arbitrary_self_types, futures_api)]
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app = lazy(|_| 42);
    //!
    //! // assuming `my_app: Future`
    //! ThreadPool::new().expect("Failed to create threadpool").run(my_app);
    //! ```
    //!
    //! The call to [`run`](crate::executor::ThreadPool::run) will block the
    //! current thread until the future defined by `my_app` completes, and will
    //! return the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! Tasks can be spawned onto a spawner by calling its
    //! [`spawn_obj`](crate::task::Spawn::spawn_obj) method directly.
    //! In the case of `!Send` futures,
    //! [`spawn_local_obj`](crate::task::LocalSpawn::spawn_local_obj)
    //! can be used instead.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](crate::executor::LocalPool) executor. Aside from cutting
    //! down on synchronization costs, this executor also makes it possible to
    //! spawn non-`Send` tasks, via
    //! [`spawn_local_obj`](crate::executor::LocalSpawn::spawn_local_obj).
    //! The `LocalPool` is best suited for running I/O-bound tasks that do
    //! relatively little work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](crate::executor::block_on), for simply running a future to
    //! completion on the current thread, while routing any spawned tasks
    //! to a global thread pool.

    pub use futures_executor::{
        BlockingStream,
        Enter, EnterError,
        LocalSpawner, LocalPool,
        ThreadPool, ThreadPoolBuilder,
        block_on, block_on_stream, enter,
    };
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](crate::future::Future).
    //! - The [`FutureExt`](crate::future::FutureExt) trait, which provides
    //!   adapters for chaining and composing futures.
    //! - Top-level future combinators like [`lazy`](crate::future::lazy) which
    //!   creates a future from a closure that defines its return value, and
    //!   [`ready`](crate::future::ready), which constructs a future with an
    //!   immediate defined value.

    pub use futures_core::future::{
        Future, TryFuture, FusedFuture,
        FutureObj, LocalFutureObj, UnsafeFutureObj,
    };

    pub use futures_util::future::{
        empty, Empty,
        lazy, Lazy,
        maybe_done, MaybeDone,
        poll_fn, PollFn,
        ready, ok, err, Ready,

        OptionFuture,

        FutureExt,
        FlattenStream, Flatten, Fuse, Inspect, IntoStream, Join, Join3, Join4,
        Join5, Map, Then,
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        abortable, Abortable, AbortHandle, AbortRegistration, Aborted,
        Remote, RemoteHandle,
        // For FutureExt:
        CatchUnwind, Shared,

        join_all, JoinAll,

        // ToDo: SelectAll, SelectOk, select_all, select_ok
    };

    pub use futures_util::try_future::{
        TryFutureExt,
        AndThen, ErrInto, FlattenSink, IntoFuture, MapErr, MapOk, OrElse,
        UnwrapOrElse,
        TryJoin, TryJoin3, TryJoin4, TryJoin5,
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](crate::io::AsyncRead) and
    //! [`AsyncWrite`](crate::io::AsyncWrite), which mirror the `Read` and
    //! `Write` traits of the standard library. However, these traits integrate
    //! with the asynchronous task system, so that if an I/O object isn't ready
    //! for reading (or writing), the thread is not blocked, and instead the
    //! current task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](crate::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](crate::io::AsyncWriteExt) extension traits offer a
    //! variety of useful combinators for operating with asynchronous I/O
    //! objects, including ways to work with them using futures, streams and
    //! sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

#[cfg(feature = "std")]
pub mod lock {
    //! Futures-powered synchronization primitives.
    pub use futures_util::lock::{Mutex, MutexLockFuture, MutexGuard};
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the
    //! standard library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use crate::future::{self, Future, TryFuture, FutureExt, TryFutureExt};
    pub use crate::stream::{self, Stream, TryStream, StreamExt, TryStreamExt};
    pub use crate::sink::{self, Sink, SinkExt};

    #[cfg(feature = "std")]
    pub use crate::io::{ AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](crate::sink::Sink), which allows you to
    //!   asynchronously write data.
    //! - The [`SinkExt`](crate::sink::SinkExt) trait, which provides adapters
    //!   for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        SinkExt, Fanout, Drain, DrainError, drain,
        // WithFlatMap,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](crate::stream::Stream), for objects that can
    //!   asynchronously produce a sequence of values.
    //! - The [`StreamExt`](crate::stream::StreamExt) trait, which provides
    //!   adapters for chaining and composing streams.
    //! - Top-level stream contructors like [`iter_ok`](crate::stream::iter)
    //!   which creates a stream from an iterator, and
    //!   [`futures_unordered`](crate::stream::futures_unordered()), which
    //!   constructs a stream from a collection of futures.

    pub use futures_core::stream::{
        Stream, TryStream, FusedStream,
        StreamObj, LocalStreamObj, UnsafeStreamObj,
    };

    pub use futures_util::stream::{
        iter, Iter,
        repeat, Repeat,
        empty, Empty,
        once, Once,
        poll_fn, PollFn,
        unfold, Unfold,

        StreamExt,
        Chain, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse,
        StreamFuture, Inspect, Map, Next, Peekable, Select, Skip, SkipWhile,
        Take, TakeWhile, Then, Zip
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_ordered, FuturesOrdered,
        futures_unordered, FuturesUnordered,

        // For StreamExt:
        BufferUnordered, Buffered, CatchUnwind, Chunks, Collect, SplitStream,
        SplitSink, ReuniteError,

        // ToDo: select_all, SelectAll,
    };

    pub use futures_util::try_stream::{
        TryStreamExt,
        TryNext, TryForEach, ErrInto,
        TryFold, TrySkipWhile,
        IntoStream,
        // ToDo: AndThen, ErrInto, InspectErr, MapErr, OrElse
    };

    #[cfg(feature = "std")]
    pub use futures_util::try_stream::{
        // For TryStreamExt:
        TryCollect, TryBufferUnordered,
        // ToDo: AndThen, InspectErr, MapErr, OrElse
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Spawn`](crate::task::Spawn), a trait for spawning new tasks.
    //! - [`Waker`](crate::task::Waker), a handle for waking up a task.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Poll, Spawn, LocalSpawn, SpawnError,
        Waker, LocalWaker, UnsafeWake,
    };

    #[cfg(feature = "std")]
    pub use futures_core::task::{
        Wake, local_waker, local_waker_from_nonlocal
    };

    #[cfg(feature = "std")]
    pub use futures_util::task::{
        LocalWakerRef, local_waker_ref, local_waker_ref_from_nonlocal,
        SpawnExt, LocalSpawnExt,
    };

    pub use futures_util::task::{
        noop_local_waker, noop_local_waker_ref,
    };

    #[cfg_attr(
        feature = "nightly",
        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
    )]
    pub use futures_util::task::AtomicWaker;
}

// `select!` re-export --------------------------------------

#[cfg(feature = "std")]
#[doc(hidden)]
pub use futures_util::rand_reexport;

#[cfg(feature = "std")]
#[doc(hidden)]
pub mod inner_select {
    pub use futures_util::select;
}

futures_util::document_select_macro! {
    #[macro_export]
    macro_rules! select { // replace `::futures_util` with `::futures` as the crate path
        ($($tokens:tt)*) => {
            $crate::inner_select::select! {
                futures_crate_path ( ::futures )
                $( $tokens )*
            }
        }
    }
}
<commit_msg>Add missing std cfg<commit_after>//! Abstractions for asynchronous programming.
//!
//! This crate provides a number of core abstractions for writing asynchronous
//! code:
//!
//! - [Futures](crate::future::Future) are single eventual values produced by
//!   asychronous computations. Some programming languages (e.g. JavaScript)
//!   call this concept "promise".
//! - [Streams](crate::stream::Stream) represent a series of values
//!   produced asynchronously.
//! - [Sinks](crate::sink::Sink) provide support for asynchronous writing of
//!   data.
//! - [Executors](crate::executor) are responsible for running asynchronous
//!   tasks.
//!
//! The crate also contains abstractions for [asynchronous I/O](crate::io) and
//! [cross-task communication](crate::channel).
//!
//! Underlying all of this is the *task system*, which is a form of lightweight
//! threading. Large asynchronous computations are built up using futures,
//! streams and sinks, and then spawned as independent tasks that are run to
//! completion, but *do not block* the thread running them.

#![feature(pin, arbitrary_self_types, futures_api)]

#![cfg_attr(not(feature = "std"), no_std)]

#![warn(missing_docs, missing_debug_implementations)]
#![deny(bare_trait_objects)]

#![doc(html_root_url = "https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.10/futures")]

#![cfg_attr(feature = "nightly", feature(cfg_target_has_atomic))]

#[doc(hidden)] pub use futures_util::core_reexport;

#[doc(hidden)] pub use futures_core::future::Future;
#[doc(hidden)] pub use futures_core::future::TryFuture;
#[doc(hidden)] pub use futures_util::future::FutureExt;
#[doc(hidden)] pub use futures_util::try_future::TryFutureExt;

#[doc(hidden)] pub use futures_core::stream::Stream;
#[doc(hidden)] pub use futures_core::stream::TryStream;
#[doc(hidden)] pub use futures_util::stream::StreamExt;
#[doc(hidden)] pub use futures_util::try_stream::TryStreamExt;

#[doc(hidden)] pub use futures_sink::Sink;
#[doc(hidden)] pub use futures_util::sink::SinkExt;

#[doc(hidden)] pub use futures_core::task::Poll;

// Macro reexports
pub use futures_util::{
    // Error/readiness propagation
    try_ready, try_poll, ready,
};
#[cfg(feature = "std")]
pub use futures_util::{
    // Async-await
    join, try_join, pending, poll,
};

#[cfg(feature = "std")]
pub mod channel {
    //! Cross-task communication.
    //!
    //! Like threads, concurrent tasks sometimes need to communicate with each
    //! other. This module contains two basic abstractions for doing so:
    //!
    //! - [oneshot](crate::channel::oneshot), a way of sending a single value
    //!   from one task to another.
    //! - [mpsc](crate::channel::mpsc), a multi-producer, single-consumer
    //!   channel for sending values between tasks, analogous to the
    //!   similarly-named structure in the standard library.

    pub use futures_channel::{oneshot, mpsc};
}

#[cfg(feature = "compat")]
pub mod compat {
    //! Interop between `futures` 0.1 and 0.3.

    pub use futures_util::compat::{
        Compat,
        Compat01As03,
        Executor01Future,
        Executor01As03,
        Executor01CompatExt,
        Future01CompatExt,
        Stream01CompatExt,
    };

    #[cfg(feature = "tokio-compat")]
    pub use futures_util::compat::TokioDefaultSpawner;
}

#[cfg(feature = "std")]
pub mod executor {
    //! Task execution.
    //!
    //! All asynchronous computation occurs within an executor, which is
    //! capable of spawning futures as tasks. This module provides several
    //! built-in executors, as well as tools for building your own.
    //!
    //! # Using a thread pool (M:N task scheduling)
    //!
    //! Most of the time tasks should be executed on a [thread
    //! pool](crate::executor::ThreadPool). A small set of worker threads can
    //! handle a very large set of spawned tasks (which are much lighter weight
    //! than threads).
    //!
    //! The simplest way to use a thread pool is to
    //! [`run`](crate::executor::ThreadPool::run) an initial task on it, which
    //! can then spawn further tasks back onto the pool to complete its work:
    //!
    //! ```
    //! #![feature(pin, arbitrary_self_types, futures_api)]
    //! use futures::executor::ThreadPool;
    //! # use futures::future::{Future, lazy};
    //! # let my_app = lazy(|_| 42);
    //!
    //! // assuming `my_app: Future`
    //! ThreadPool::new().expect("Failed to create threadpool").run(my_app);
    //! ```
    //!
    //! The call to [`run`](crate::executor::ThreadPool::run) will block the
    //! current thread until the future defined by `my_app` completes, and will
    //! return the result of that future.
    //!
    //! # Spawning additional tasks
    //!
    //! Tasks can be spawned onto a spawner by calling its
    //! [`spawn_obj`](crate::task::Spawn::spawn_obj) method directly.
    //! In the case of `!Send` futures,
    //! [`spawn_local_obj`](crate::task::LocalSpawn::spawn_local_obj)
    //! can be used instead.
    //!
    //! # Single-threaded execution
    //!
    //! In addition to thread pools, it's possible to run a task (and the tasks
    //! it spawns) entirely within a single thread via the
    //! [`LocalPool`](crate::executor::LocalPool) executor. Aside from cutting
    //! down on synchronization costs, this executor also makes it possible to
    //! spawn non-`Send` tasks, via
    //! [`spawn_local_obj`](crate::executor::LocalSpawn::spawn_local_obj).
    //! The `LocalPool` is best suited for running I/O-bound tasks that do
    //! relatively little work between I/O operations.
    //!
    //! There is also a convenience function,
    //! [`block_on`](crate::executor::block_on), for simply running a future to
    //! completion on the current thread, while routing any spawned tasks
    //! to a global thread pool.

    pub use futures_executor::{
        BlockingStream,
        Enter, EnterError,
        LocalSpawner, LocalPool,
        ThreadPool, ThreadPoolBuilder,
        block_on, block_on_stream, enter,
    };
}

pub mod future {
    //! Asynchronous values.
    //!
    //! This module contains:
    //!
    //! - The [`Future` trait](crate::future::Future).
    //! - The [`FutureExt`](crate::future::FutureExt) trait, which provides
    //!   adapters for chaining and composing futures.
    //! - Top-level future combinators like [`lazy`](crate::future::lazy) which
    //!   creates a future from a closure that defines its return value, and
    //!   [`ready`](crate::future::ready), which constructs a future with an
    //!   immediate defined value.

    pub use futures_core::future::{
        Future, TryFuture, FusedFuture,
        FutureObj, LocalFutureObj, UnsafeFutureObj,
    };

    pub use futures_util::future::{
        empty, Empty,
        lazy, Lazy,
        maybe_done, MaybeDone,
        poll_fn, PollFn,
        ready, ok, err, Ready,

        OptionFuture,

        FutureExt,
        FlattenStream, Flatten, Fuse, Inspect, IntoStream, Join, Join3, Join4,
        Join5, Map, Then,
    };

    #[cfg(feature = "std")]
    pub use futures_util::future::{
        abortable, Abortable, AbortHandle, AbortRegistration, Aborted,
        Remote, RemoteHandle,
        // For FutureExt:
        CatchUnwind, Shared,

        join_all, JoinAll,

        // ToDo: SelectAll, SelectOk, select_all, select_ok
    };

    pub use futures_util::try_future::{
        TryFutureExt,
        AndThen, ErrInto, FlattenSink, IntoFuture, MapErr, MapOk, OrElse,
        UnwrapOrElse,
        TryJoin, TryJoin3, TryJoin4, TryJoin5,
    };
}

#[cfg(feature = "std")]
pub mod io {
    //! Asynchronous I/O.
    //!
    //! This module is the asynchronous version of `std::io`. It defines two
    //! traits, [`AsyncRead`](crate::io::AsyncRead) and
    //! [`AsyncWrite`](crate::io::AsyncWrite), which mirror the `Read` and
    //! `Write` traits of the standard library. However, these traits integrate
    //! with the asynchronous task system, so that if an I/O object isn't ready
    //! for reading (or writing), the thread is not blocked, and instead the
    //! current task is queued to be woken when I/O is ready.
    //!
    //! In addition, the [`AsyncReadExt`](crate::io::AsyncReadExt) and
    //! [`AsyncWriteExt`](crate::io::AsyncWriteExt) extension traits offer a
    //! variety of useful combinators for operating with asynchronous I/O
    //! objects, including ways to work with them using futures, streams and
    //! sinks.

    pub use futures_io::{
        Error, Initializer, IoVec, ErrorKind, AsyncRead, AsyncWrite, Result
    };
    pub use futures_util::io::{
        AsyncReadExt, AsyncWriteExt, AllowStdIo, Close, CopyInto, Flush,
        Read, ReadExact, ReadHalf, ReadToEnd, Window, WriteAll, WriteHalf,
    };
}

#[cfg(feature = "std")]
pub mod lock {
    //! Futures-powered synchronization primitives.
    pub use futures_util::lock::{Mutex, MutexLockFuture, MutexGuard};
}

pub mod prelude {
    //! A "prelude" for crates using the `futures` crate.
    //!
    //! This prelude is similar to the standard library's prelude in that you'll
    //! almost always want to import its entire contents, but unlike the
    //! standard library's prelude you'll have to do so manually:
    //!
    //! ```
    //! use futures::prelude::*;
    //! ```
    //!
    //! The prelude may grow over time as additional items see ubiquitous use.

    pub use crate::future::{self, Future, TryFuture, FutureExt, TryFutureExt};
    pub use crate::stream::{self, Stream, TryStream, StreamExt, TryStreamExt};
    pub use crate::sink::{self, Sink, SinkExt};

    #[cfg(feature = "std")]
    pub use crate::io::{ AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt };
}

pub mod sink {
    //! Asynchronous sinks.
    //!
    //! This module contains:
    //!
    //! - The [`Sink` trait](crate::sink::Sink), which allows you to
    //!   asynchronously write data.
    //! - The [`SinkExt`](crate::sink::SinkExt) trait, which provides adapters
    //!   for chaining and composing sinks.

    pub use futures_sink::Sink;

    pub use futures_util::sink::{
        Close, Flush, Send, SendAll, SinkErrInto, SinkMapErr, With,
        SinkExt, Fanout, Drain, DrainError, drain,
        // WithFlatMap,
    };

    #[cfg(feature = "std")]
    pub use futures_util::sink::Buffer;
}

pub mod stream {
    //! Asynchronous streams.
    //!
    //! This module contains:
    //!
    //! - The [`Stream` trait](crate::stream::Stream), for objects that can
    //!   asynchronously produce a sequence of values.
    //! - The [`StreamExt`](crate::stream::StreamExt) trait, which provides
    //!   adapters for chaining and composing streams.
    //! - Top-level stream contructors like [`iter_ok`](crate::stream::iter)
    //!   which creates a stream from an iterator, and
    //!   [`futures_unordered`](crate::stream::futures_unordered()), which
    //!   constructs a stream from a collection of futures.

    pub use futures_core::stream::{
        Stream, TryStream, FusedStream,
        StreamObj, LocalStreamObj, UnsafeStreamObj,
    };

    pub use futures_util::stream::{
        iter, Iter,
        repeat, Repeat,
        empty, Empty,
        once, Once,
        poll_fn, PollFn,
        unfold, Unfold,

        StreamExt,
        Chain, Concat, Filter, FilterMap, Flatten, Fold, Forward, ForEach, Fuse,
        StreamFuture, Inspect, Map, Next, Peekable, Select, Skip, SkipWhile,
        Take, TakeWhile, Then, Zip
    };

    #[cfg(feature = "std")]
    pub use futures_util::stream::{
        futures_ordered, FuturesOrdered,
        futures_unordered, FuturesUnordered,

        // For StreamExt:
        BufferUnordered, Buffered, CatchUnwind, Chunks, Collect, SplitStream,
        SplitSink, ReuniteError,

        // ToDo: select_all, SelectAll,
    };

    pub use futures_util::try_stream::{
        TryStreamExt,
        TryNext, TryForEach, ErrInto,
        TryFold, TrySkipWhile,
        IntoStream,
        // ToDo: AndThen, ErrInto, InspectErr, MapErr, OrElse
    };

    #[cfg(feature = "std")]
    pub use futures_util::try_stream::{
        // For TryStreamExt:
        TryCollect, TryBufferUnordered,
        // ToDo: AndThen, InspectErr, MapErr, OrElse
    };
}

pub mod task {
    //! Tools for working with tasks.
    //!
    //! This module contains:
    //!
    //! - [`Spawn`](crate::task::Spawn), a trait for spawning new tasks.
    //! - [`Waker`](crate::task::Waker), a handle for waking up a task.
    //!
    //! The remaining types and traits in the module are used for implementing
    //! executors or dealing with synchronization issues around task wakeup.

    pub use futures_core::task::{
        Poll, Spawn, LocalSpawn, SpawnError,
        Waker, LocalWaker, UnsafeWake,
    };

    #[cfg(feature = "std")]
    pub use futures_core::task::{
        Wake, local_waker, local_waker_from_nonlocal
    };

    #[cfg(feature = "std")]
    pub use futures_util::task::{
        LocalWakerRef, local_waker_ref, local_waker_ref_from_nonlocal,
        SpawnExt, LocalSpawnExt,
    };

    pub use futures_util::task::{
        noop_local_waker, noop_local_waker_ref,
    };

    #[cfg_attr(
        feature = "nightly",
        cfg(all(target_has_atomic = "cas", target_has_atomic = "ptr"))
    )]
    pub use futures_util::task::AtomicWaker;
}

// `select!` re-export --------------------------------------

#[cfg(feature = "std")]
#[doc(hidden)]
pub use futures_util::rand_reexport;

#[cfg(feature = "std")]
#[doc(hidden)]
pub mod inner_select {
    pub use futures_util::select;
}

#[cfg(feature = "std")]
futures_util::document_select_macro! {
    #[macro_export]
    macro_rules! select { // replace `::futures_util` with `::futures` as the crate path
        ($($tokens:tt)*) => {
            $crate::inner_select::select! {
                futures_crate_path ( ::futures )
                $( $tokens )*
            }
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::glyph_rasterizer::{FontInstance, GlyphFormat, GlyphKey, GlyphRasterizer};
use crate::internal_types::FastHashMap;
use crate::render_backend::{FrameId, FrameStamp};
use crate::render_task_cache::RenderTaskCache;
use crate::resource_cache::ResourceClassCache;
use std::sync::Arc;
use crate::texture_cache::{EvictionNotice, TextureCache};
use crate::texture_cache::TextureCacheHandle;

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Debug)]
pub struct CachedGlyphInfo {
    pub format: GlyphFormat,
    pub texture_cache_handle: TextureCacheHandle,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum GlyphCacheEntry {
    // A glyph that has been successfully rasterized.
    Cached(CachedGlyphInfo),
    // A glyph that should not be rasterized (i.e. a space).
    Blank,
    // A glyph that has been submitted to the font backend for rasterization,
    // but is still pending a result.
    #[allow(dead_code)]
    Pending,
}

impl GlyphCacheEntry {
    fn get_allocated_size(&self, texture_cache: &TextureCache, _: &RenderTaskCache)
                          -> Option<usize> {
        match *self {
            GlyphCacheEntry::Cached(ref glyph) => {
                texture_cache.get_allocated_size(&glyph.texture_cache_handle)
            }
            GlyphCacheEntry::Pending => Some(0),
            // If the cache only has blank glyphs left, just get rid of it.
            GlyphCacheEntry::Blank => None,
        }
    }

    fn mark_unused(&self, texture_cache: &mut TextureCache) {
        if let GlyphCacheEntry::Cached(ref glyph) = *self {
            texture_cache.mark_unused(&glyph.texture_cache_handle);
        }
    }

    fn is_recently_used(&self, texture_cache: &mut TextureCache) -> bool {
        if let GlyphCacheEntry::Cached(ref glyph) = *self {
            texture_cache.is_recently_used(&glyph.texture_cache_handle, 1)
        } else {
            false
        }
    }
}

#[allow(dead_code)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone)]
pub enum CachedGlyphData {
    Memory(Arc<Vec<u8>>),
    Gpu,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Default)]
pub struct GlyphKeyCacheInfo {
    eviction_notice: EvictionNotice,
    last_frame_used: FrameId,
    bytes_used: usize,
}

pub type GlyphKeyCache = ResourceClassCache<GlyphKey, GlyphCacheEntry, GlyphKeyCacheInfo>;

impl GlyphKeyCache {
    const DIRTY: usize = !0;

    pub fn eviction_notice(&self) -> &EvictionNotice {
        &self.user_data.eviction_notice
    }

    fn is_recently_used(&self, current_frame: FrameId) -> bool {
        self.user_data.last_frame_used + 1 >= current_frame
    }

    fn clear_glyphs(&mut self, texture_cache: &mut TextureCache) -> usize {
        let pruned = self.user_data.bytes_used;
        for (_, entry) in self.iter() {
            entry.mark_unused(texture_cache);
        }
        self.clear();
        self.user_data.bytes_used = 0;
        pruned
    }

    fn prune_glyphs(
        &mut self,
        skip_recent: bool,
        excess_bytes_used: usize,
        texture_cache: &mut TextureCache,
        render_task_cache: &RenderTaskCache,
    ) -> usize {
        let mut pruned = 0;
        self.retain(|_, entry| {
            if pruned <= excess_bytes_used &&
               (!skip_recent || !entry.is_recently_used(texture_cache)) {
                match entry.get_allocated_size(texture_cache, render_task_cache) {
                    Some(size) => {
                        pruned += size;
                        entry.mark_unused(texture_cache);
                        false
                    }
                    None => true,
                }
            } else {
                true
            }
        });
        self.user_data.bytes_used -= pruned;
        pruned
    }

    pub fn add_glyph(&mut self, key: GlyphKey, value: GlyphCacheEntry) {
        self.insert(key, value);
        self.user_data.bytes_used = Self::DIRTY;
    }

    fn clear_evicted(
        &mut self,
        texture_cache: &TextureCache,
        render_task_cache: &RenderTaskCache,
    ) {
        if self.eviction_notice().check() || self.user_data.bytes_used == Self::DIRTY {
            // If there are evictions, filter out any glyphs evicted from the
            // texture cache from the glyph key cache.
            let mut usage = 0;
            self.retain(|_, entry| {
                let size = entry.get_allocated_size(texture_cache, render_task_cache);
                usage += size.unwrap_or(0);
                size.is_some()
            });
            self.user_data.bytes_used = usage;
        }
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct GlyphCache {
    glyph_key_caches: FastHashMap<FontInstance, GlyphKeyCache>,
    current_frame: FrameId,
    bytes_used: usize,
    max_bytes_used: usize,
}

impl GlyphCache {
    /// The default space usage threshold, in bytes, after which to start pruning away old fonts.
    pub const DEFAULT_MAX_BYTES_USED: usize = 6 * 1024 * 1024;

    pub fn new(max_bytes_used: usize) -> Self {
        GlyphCache {
            glyph_key_caches: FastHashMap::default(),
            current_frame: Default::default(),
            bytes_used: 0,
            max_bytes_used,
        }
    }

    pub fn get_glyph_key_cache_for_font_mut(&mut self, font: FontInstance) -> &mut GlyphKeyCache {
        let cache = self.glyph_key_caches
                        .entry(font)
                        .or_insert_with(GlyphKeyCache::new);
        cache.user_data.last_frame_used = self.current_frame;
        cache
    }

    pub fn get_glyph_key_cache_for_font(&self, font: &FontInstance) -> &GlyphKeyCache {
        self.glyph_key_caches
            .get(font)
            .expect("BUG: Unable to find glyph key cache!")
    }

    pub fn clear(&mut self) {
        for (_, glyph_key_cache) in &mut self.glyph_key_caches {
            glyph_key_cache.clear()
        }
        // We use this in on_memory_pressure where retaining memory allocations
        // isn't desirable, so we completely remove the hash map instead of clearing it.
        self.glyph_key_caches = FastHashMap::default();
    }

    pub fn clear_fonts<F>(&mut self, texture_cache: &mut TextureCache, key_fun: F)
    where
        for<'r> F: Fn(&'r &FontInstance) -> bool,
    {
        self.glyph_key_caches.retain(|k, cache| {
            let should_clear = key_fun(&k);
            if !should_clear {
                return true;
            }

            cache.clear_glyphs(texture_cache);
            false
        })
    }

    /// Clear out evicted entries from glyph key caches.
    fn clear_evicted(
        &mut self,
        texture_cache: &TextureCache,
        render_task_cache: &RenderTaskCache,
    ) {
        let mut usage = 0;
        for cache in self.glyph_key_caches.values_mut() {
            // Scan for any glyph key caches that have evictions.
            cache.clear_evicted(texture_cache, render_task_cache);
            usage += cache.user_data.bytes_used;
        }
        self.bytes_used = usage;
    }

    /// If possible, remove entirely any empty glyph key caches.
    fn clear_empty_caches(&mut self, glyph_rasterizer: &mut GlyphRasterizer) {
        self.glyph_key_caches.retain(|key, cache| {
            // Discard the glyph key cache if it has no valid glyphs.
            if cache.is_empty() {
                glyph_rasterizer.delete_font_instance(key);
                false
            } else {
                true
            }
        });
    }

    /// Check the total space usage of the glyph cache. If it exceeds the maximum usage threshold,
    /// then start clearing the oldest glyphs until below the threshold.
    fn prune_excess_usage(
        &mut self,
        texture_cache: &mut TextureCache,
        render_task_cache: &RenderTaskCache,
    ) {
        if self.bytes_used < self.max_bytes_used {
            return;
        }
        // Usage is above the threshold. Get a last-recently-used ordered list of caches to clear.
        let mut caches: Vec<_> = self.glyph_key_caches.values_mut().collect();
        caches.sort_unstable_by(|a, b| {
            a.user_data.last_frame_used.cmp(&b.user_data.last_frame_used)
        });
        // Clear out the oldest caches until below the threshold.
        for cache in caches {
            if self.bytes_used < self.max_bytes_used {
                break;
            }
            let recent = cache.is_recently_used(self.current_frame);
            let excess = self.bytes_used - self.max_bytes_used;
            if !recent && excess >= cache.user_data.bytes_used {
                // If the excess is greater than the cache's size, just clear the whole thing.
                self.bytes_used -= cache.clear_glyphs(texture_cache);
            } else {
                // Otherwise, just clear as little of the cache as needed to remove the excess
                // and avoid rematerialization costs.
                self.bytes_used -= cache.prune_glyphs(
                    recent,
                    excess,
                    texture_cache,
                    render_task_cache,
                );
            }
        }
    }

    pub fn begin_frame(
        &mut self,
        stamp: FrameStamp,
        texture_cache: &mut TextureCache,
        render_task_cache: &RenderTaskCache,
        glyph_rasterizer: &mut GlyphRasterizer,
    ) {
        self.current_frame = stamp.frame_id();
        self.clear_evicted(texture_cache, render_task_cache);
        self.prune_excess_usage(texture_cache, render_task_cache);
        // Clearing evicted glyphs and pruning excess usage might have produced empty caches,
        // so get rid of them if possible.
        self.clear_empty_caches(glyph_rasterizer);
    }
}
<commit_msg>Bug 1595768 - Don't evict blank glyphs to avoid re-rasterizing them continuously. r=gw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::glyph_rasterizer::{FontInstance, GlyphFormat, GlyphKey, GlyphRasterizer};
use crate::internal_types::FastHashMap;
use crate::render_backend::{FrameId, FrameStamp};
use crate::render_task_cache::RenderTaskCache;
use crate::resource_cache::ResourceClassCache;
use std::sync::Arc;
use crate::texture_cache::{EvictionNotice, TextureCache};
use crate::texture_cache::TextureCacheHandle;

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone, Debug)]
pub struct CachedGlyphInfo {
    pub format: GlyphFormat,
    pub texture_cache_handle: TextureCacheHandle,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum GlyphCacheEntry {
    // A glyph that has been successfully rasterized.
    Cached(CachedGlyphInfo),
    // A glyph that should not be rasterized (i.e. a space).
    Blank,
    // A glyph that has been submitted to the font backend for rasterization,
    // but is still pending a result.
    #[allow(dead_code)]
    Pending,
}

impl GlyphCacheEntry {
    fn get_allocated_size(&self, texture_cache: &TextureCache, _: &RenderTaskCache)
                          -> Option<usize> {
        match *self {
            GlyphCacheEntry::Cached(ref glyph) => {
                texture_cache.get_allocated_size(&glyph.texture_cache_handle)
            }
            GlyphCacheEntry::Pending | GlyphCacheEntry::Blank => Some(0),
        }
    }

    fn mark_unused(&self, texture_cache: &mut TextureCache) {
        if let GlyphCacheEntry::Cached(ref glyph) = *self {
            texture_cache.mark_unused(&glyph.texture_cache_handle);
        }
    }

    fn is_recently_used(&self, texture_cache: &mut TextureCache) -> bool {
        if let GlyphCacheEntry::Cached(ref glyph) = *self {
            texture_cache.is_recently_used(&glyph.texture_cache_handle, 1)
        } else {
            false
        }
    }
}

#[allow(dead_code)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Clone)]
pub enum CachedGlyphData {
    Memory(Arc<Vec<u8>>),
    Gpu,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Default)]
pub struct GlyphKeyCacheInfo {
    eviction_notice: EvictionNotice,
    last_frame_used: FrameId,
    bytes_used: usize,
}

pub type GlyphKeyCache = ResourceClassCache<GlyphKey, GlyphCacheEntry, GlyphKeyCacheInfo>;

impl GlyphKeyCache {
    const DIRTY: usize = !0;

    pub fn eviction_notice(&self) -> &EvictionNotice {
        &self.user_data.eviction_notice
    }

    fn is_recently_used(&self, current_frame: FrameId) -> bool {
        self.user_data.last_frame_used + 1 >= current_frame
    }

    fn clear_glyphs(&mut self, texture_cache: &mut TextureCache) -> usize {
        let pruned = self.user_data.bytes_used;
        for (_, entry) in self.iter() {
            entry.mark_unused(texture_cache);
        }
        self.clear();
        self.user_data.bytes_used = 0;
        pruned
    }

    fn prune_glyphs(
        &mut self,
        skip_recent: bool,
        excess_bytes_used: usize,
        texture_cache: &mut TextureCache,
        render_task_cache: &RenderTaskCache,
    ) -> usize {
        let mut pruned = 0;
        self.retain(|_, entry| {
            if pruned <= excess_bytes_used &&
               (!skip_recent || !entry.is_recently_used(texture_cache)) {
                match entry.get_allocated_size(texture_cache, render_task_cache) {
                    Some(size) => {
                        pruned += size;
                        entry.mark_unused(texture_cache);
                        false
                    }
                    None => true,
                }
            } else {
                true
            }
        });
        self.user_data.bytes_used -= pruned;
        pruned
    }

    pub fn add_glyph(&mut self, key: GlyphKey, value: GlyphCacheEntry) {
        self.insert(key, value);
        self.user_data.bytes_used = Self::DIRTY;
    }

    fn clear_evicted(
        &mut self,
        texture_cache: &TextureCache,
        render_task_cache: &RenderTaskCache,
    ) {
        if self.eviction_notice().check() || self.user_data.bytes_used == Self::DIRTY {
            // If there are evictions, filter out any glyphs evicted from the
            // texture cache from the glyph key cache.
            let mut usage = 0;
            self.retain(|_, entry| {
                let size = entry.get_allocated_size(texture_cache, render_task_cache);
                usage += size.unwrap_or(0);
                size.is_some()
            });
            self.user_data.bytes_used = usage;
        }
    }
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct GlyphCache {
    glyph_key_caches: FastHashMap<FontInstance, GlyphKeyCache>,
    current_frame: FrameId,
    bytes_used: usize,
    max_bytes_used: usize,
}

impl GlyphCache {
    /// The default space usage threshold, in bytes, after which to start pruning away old fonts.
    pub const DEFAULT_MAX_BYTES_USED: usize = 6 * 1024 * 1024;

    pub fn new(max_bytes_used: usize) -> Self {
        GlyphCache {
            glyph_key_caches: FastHashMap::default(),
            current_frame: Default::default(),
            bytes_used: 0,
            max_bytes_used,
        }
    }

    pub fn get_glyph_key_cache_for_font_mut(&mut self, font: FontInstance) -> &mut GlyphKeyCache {
        let cache = self.glyph_key_caches
                        .entry(font)
                        .or_insert_with(GlyphKeyCache::new);
        cache.user_data.last_frame_used = self.current_frame;
        cache
    }

    pub fn get_glyph_key_cache_for_font(&self, font: &FontInstance) -> &GlyphKeyCache {
        self.glyph_key_caches
            .get(font)
            .expect("BUG: Unable to find glyph key cache!")
    }

    pub fn clear(&mut self) {
        for (_, glyph_key_cache) in &mut self.glyph_key_caches {
            glyph_key_cache.clear()
        }
        // We use this in on_memory_pressure where retaining memory allocations
        // isn't desirable, so we completely remove the hash map instead of clearing it.
        self.glyph_key_caches = FastHashMap::default();
    }

    pub fn clear_fonts<F>(&mut self, texture_cache: &mut TextureCache, key_fun: F)
    where
        for<'r> F: Fn(&'r &FontInstance) -> bool,
    {
        self.glyph_key_caches.retain(|k, cache| {
            let should_clear = key_fun(&k);
            if !should_clear {
                return true;
            }

            cache.clear_glyphs(texture_cache);
            false
        })
    }

    /// Clear out evicted entries from glyph key caches.
    fn clear_evicted(
        &mut self,
        texture_cache: &TextureCache,
        render_task_cache: &RenderTaskCache,
    ) {
        let mut usage = 0;
        for cache in self.glyph_key_caches.values_mut() {
            // Scan for any glyph key caches that have evictions.
            cache.clear_evicted(texture_cache, render_task_cache);
            usage += cache.user_data.bytes_used;
        }
        self.bytes_used = usage;
    }

    /// If possible, remove entirely any empty glyph key caches.
    fn clear_empty_caches(&mut self, glyph_rasterizer: &mut GlyphRasterizer) {
        self.glyph_key_caches.retain(|key, cache| {
            // Discard the glyph key cache if it has no valid glyphs.
            if cache.is_empty() {
                glyph_rasterizer.delete_font_instance(key);
                false
            } else {
                true
            }
        });
    }

    /// Check the total space usage of the glyph cache. If it exceeds the maximum usage threshold,
    /// then start clearing the oldest glyphs until below the threshold.
    fn prune_excess_usage(
        &mut self,
        texture_cache: &mut TextureCache,
        render_task_cache: &RenderTaskCache,
    ) {
        if self.bytes_used < self.max_bytes_used {
            return;
        }
        // Usage is above the threshold. Get a last-recently-used ordered list of caches to clear.
        let mut caches: Vec<_> = self.glyph_key_caches.values_mut().collect();
        caches.sort_unstable_by(|a, b| {
            a.user_data.last_frame_used.cmp(&b.user_data.last_frame_used)
        });
        // Clear out the oldest caches until below the threshold.
        for cache in caches {
            if self.bytes_used < self.max_bytes_used {
                break;
            }
            let recent = cache.is_recently_used(self.current_frame);
            let excess = self.bytes_used - self.max_bytes_used;
            if !recent && excess >= cache.user_data.bytes_used {
                // If the excess is greater than the cache's size, just clear the whole thing.
                self.bytes_used -= cache.clear_glyphs(texture_cache);
            } else {
                // Otherwise, just clear as little of the cache as needed to remove the excess
                // and avoid rematerialization costs.
                self.bytes_used -= cache.prune_glyphs(
                    recent,
                    excess,
                    texture_cache,
                    render_task_cache,
                );
            }
        }
    }

    pub fn begin_frame(
        &mut self,
        stamp: FrameStamp,
        texture_cache: &mut TextureCache,
        render_task_cache: &RenderTaskCache,
        glyph_rasterizer: &mut GlyphRasterizer,
    ) {
        self.current_frame = stamp.frame_id();
        self.clear_evicted(texture_cache, render_task_cache);
        self.prune_excess_usage(texture_cache, render_task_cache);
        // Clearing evicted glyphs and pruning excess usage might have produced empty caches,
        // so get rid of them if possible.
        self.clear_empty_caches(glyph_rasterizer);
    }
}
<|endoftext|>


<commit_before>use crate::gen::out::{Content, OutFile};
use crate::syntax::{self, IncludeKind};
use std::ops::{Deref, DerefMut};

/// The complete contents of the "rust/cxx.h" header.
pub static HEADER: &str = include_str!("include/cxx.h");

/// A header to #include.
///
/// The cxxbridge tool does not parse or even require the given paths to exist;
/// they simply go into the generated C++ code as #include lines.
#[derive(Clone, PartialEq, Debug)]
pub struct Include {
    /// The header's path, not including the enclosing quotation marks or angle
    /// brackets.
    pub path: String,
    /// Whether to emit `#include "path"` or `#include <path>`.
    pub kind: IncludeKind,
}

#[derive(Default, PartialEq)]
pub struct Includes<'a> {
    pub custom: Vec<Include>,
    pub algorithm: bool,
    pub array: bool,
    pub cassert: bool,
    pub cstddef: bool,
    pub cstdint: bool,
    pub cstring: bool,
    pub exception: bool,
    pub functional: bool,
    pub initializer_list: bool,
    pub iterator: bool,
    pub memory: bool,
    pub new: bool,
    pub string: bool,
    pub type_traits: bool,
    pub utility: bool,
    pub vector: bool,
    pub basetsd: bool,
    pub sys_types: bool,
    pub content: Content<'a>,
}

impl<'a> Includes<'a> {
    pub fn new() -> Self {
        Includes::default()
    }

    pub fn insert(&mut self, include: impl Into<Include>) {
        self.custom.push(include.into());
    }

    pub fn has_cxx_header(&self) -> bool {
        self.custom
            .iter()
            .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
    }
}

pub(super) fn write(out: &mut OutFile) {
    let header = out.header;
    let include = &mut out.include;
    let out = &mut include.content;

    if header {
        writeln!(out, "#pragma once");
    }

    for include in &include.custom {
        match include.kind {
            IncludeKind::Quoted => {
                writeln!(out, "#include \"{}\"", include.path.escape_default());
            }
            IncludeKind::Bracketed => {
                writeln!(out, "#include <{}>", include.path);
            }
        }
    }

    let Includes {
        custom: _,
        algorithm,
        array,
        cassert,
        cstddef,
        cstdint,
        cstring,
        exception,
        functional,
        initializer_list,
        iterator,
        memory,
        new,
        string,
        type_traits,
        utility,
        vector,
        basetsd,
        sys_types,
        content: _,
    } = *include;

    if algorithm {
        writeln!(out, "#include <algorithm>");
    }
    if array {
        writeln!(out, "#include <array>");
    }
    if cassert {
        writeln!(out, "#include <cassert>");
    }
    if cstddef {
        writeln!(out, "#include <cstddef>");
    }
    if cstdint {
        writeln!(out, "#include <cstdint>");
    }
    if cstring {
        writeln!(out, "#include <cstring>");
    }
    if exception {
        writeln!(out, "#include <exception>");
    }
    if functional {
        writeln!(out, "#include <functional>");
    }
    if initializer_list {
        writeln!(out, "#include <initializer_list>");
    }
    if iterator {
        writeln!(out, "#include <iterator>");
    }
    if memory {
        writeln!(out, "#include <memory>");
    }
    if new {
        writeln!(out, "#include <new>");
    }
    if string {
        writeln!(out, "#include <string>");
    }
    if type_traits {
        writeln!(out, "#include <type_traits>");
    }
    if utility {
        writeln!(out, "#include <utility>");
    }
    if vector {
        writeln!(out, "#include <vector>");
    }
    if basetsd {
        writeln!(out, "#if defined(_WIN32)");
        writeln!(out, "#include <basetsd.h>");
    }
    if sys_types {
        if basetsd {
            writeln!(out, "#else");
        } else {
            writeln!(out, "#if not defined(_WIN32)");
        }
    }
    if sys_types {
        writeln!(out, "#include <sys/types.h>");
    }
    if basetsd || sys_types {
        writeln!(out, "#endif");
    }
}

impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
        self.custom.extend(iter.into_iter().cloned());
    }
}

impl<'i> From<&'i syntax::Include> for Include {
    fn from(include: &syntax::Include) -> Self {
        Include {
            path: include.path.clone(),
            kind: include.kind,
        }
    }
}

impl<'a> Deref for Includes<'a> {
    type Target = Content<'a>;

    fn deref(&self) -> &Self::Target {
        &self.content
    }
}

impl<'a> DerefMut for Includes<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.content
    }
}
<commit_msg>Reduce several standard library includes if cxx.h is included<commit_after>use crate::gen::out::{Content, OutFile};
use crate::syntax::{self, IncludeKind};
use std::ops::{Deref, DerefMut};

/// The complete contents of the "rust/cxx.h" header.
pub static HEADER: &str = include_str!("include/cxx.h");

/// A header to #include.
///
/// The cxxbridge tool does not parse or even require the given paths to exist;
/// they simply go into the generated C++ code as #include lines.
#[derive(Clone, PartialEq, Debug)]
pub struct Include {
    /// The header's path, not including the enclosing quotation marks or angle
    /// brackets.
    pub path: String,
    /// Whether to emit `#include "path"` or `#include <path>`.
    pub kind: IncludeKind,
}

#[derive(Default, PartialEq)]
pub struct Includes<'a> {
    pub custom: Vec<Include>,
    pub algorithm: bool,
    pub array: bool,
    pub cassert: bool,
    pub cstddef: bool,
    pub cstdint: bool,
    pub cstring: bool,
    pub exception: bool,
    pub functional: bool,
    pub initializer_list: bool,
    pub iterator: bool,
    pub memory: bool,
    pub new: bool,
    pub string: bool,
    pub type_traits: bool,
    pub utility: bool,
    pub vector: bool,
    pub basetsd: bool,
    pub sys_types: bool,
    pub content: Content<'a>,
}

impl<'a> Includes<'a> {
    pub fn new() -> Self {
        Includes::default()
    }

    pub fn insert(&mut self, include: impl Into<Include>) {
        self.custom.push(include.into());
    }

    pub fn has_cxx_header(&self) -> bool {
        self.custom
            .iter()
            .any(|header| header.path == "rust/cxx.h" || header.path == "rust\\cxx.h")
    }
}

pub(super) fn write(out: &mut OutFile) {
    let header = out.header;
    let include = &mut out.include;
    let cxx_header = include.has_cxx_header();
    let out = &mut include.content;

    if header {
        writeln!(out, "#pragma once");
    }

    for include in &include.custom {
        match include.kind {
            IncludeKind::Quoted => {
                writeln!(out, "#include \"{}\"", include.path.escape_default());
            }
            IncludeKind::Bracketed => {
                writeln!(out, "#include <{}>", include.path);
            }
        }
    }

    let Includes {
        custom: _,
        algorithm,
        array,
        cassert,
        cstddef,
        cstdint,
        cstring,
        exception,
        functional,
        initializer_list,
        iterator,
        memory,
        new,
        string,
        type_traits,
        utility,
        vector,
        basetsd,
        sys_types,
        content: _,
    } = *include;

    if algorithm && !cxx_header {
        writeln!(out, "#include <algorithm>");
    }
    if array && !cxx_header {
        writeln!(out, "#include <array>");
    }
    if cassert && !cxx_header {
        writeln!(out, "#include <cassert>");
    }
    if cstddef && !cxx_header {
        writeln!(out, "#include <cstddef>");
    }
    if cstdint && !cxx_header {
        writeln!(out, "#include <cstdint>");
    }
    if cstring {
        writeln!(out, "#include <cstring>");
    }
    if exception && !cxx_header {
        writeln!(out, "#include <exception>");
    }
    if functional {
        writeln!(out, "#include <functional>");
    }
    if initializer_list && !cxx_header {
        writeln!(out, "#include <initializer_list>");
    }
    if iterator && !cxx_header {
        writeln!(out, "#include <iterator>");
    }
    if memory {
        writeln!(out, "#include <memory>");
    }
    if new && !cxx_header {
        writeln!(out, "#include <new>");
    }
    if string && !cxx_header {
        writeln!(out, "#include <string>");
    }
    if type_traits && !cxx_header {
        writeln!(out, "#include <type_traits>");
    }
    if utility && !cxx_header {
        writeln!(out, "#include <utility>");
    }
    if vector && !cxx_header {
        writeln!(out, "#include <vector>");
    }
    if basetsd && !cxx_header {
        writeln!(out, "#if defined(_WIN32)");
        writeln!(out, "#include <basetsd.h>");
    }
    if sys_types && !cxx_header {
        if basetsd {
            writeln!(out, "#else");
        } else {
            writeln!(out, "#if not defined(_WIN32)");
        }
    }
    if sys_types && !cxx_header {
        writeln!(out, "#include <sys/types.h>");
    }
    if (basetsd || sys_types) && !cxx_header {
        writeln!(out, "#endif");
    }
}

impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
        self.custom.extend(iter.into_iter().cloned());
    }
}

impl<'i> From<&'i syntax::Include> for Include {
    fn from(include: &syntax::Include) -> Self {
        Include {
            path: include.path.clone(),
            kind: include.kind,
        }
    }
}

impl<'a> Deref for Includes<'a> {
    type Target = Content<'a>;

    fn deref(&self) -> &Self::Target {
        &self.content
    }
}

impl<'a> DerefMut for Includes<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.content
    }
}
<|endoftext|>


<commit_before>extern crate gooddata_fs;

use gooddata_fs::*;

const LRU_SIZE: usize = 32;

fn connect() -> gd::GoodDataClient {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    // Create instance of GoodData REST API Client
    let mut gd = gooddata_fs::gd::GoodDataClient::new(connector, None);
    gd.connect("tomas.korcak+gem_tester@gooddata.com", "jindrisska");
    gd
}

fn connect_to_staging3() -> gd::GoodDataClient {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new("https://staging3.intgdc.com".to_string(),
                                                    LRU_SIZE);
    // Create instance of GoodData REST API Client
    let mut gd = gooddata_fs::gd::GoodDataClient::new(connector, None);
    gd.connect("tomas.korcak+gem_tester@gooddata.com", "jindrisska");
    gd
}

#[test]
fn it_creates_connector() {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    assert_eq!(connector.token_updated.is_some(), false);
}

#[test]
fn it_creates_client() {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    // Create instance of GoodData REST API Client
    let gd = gd::GoodDataClient::new(connector, None);
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
    assert_eq!(gd.token.is_some(), false);
}

#[test]
fn it_creates_client_with_token() {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    let token = Some("xxx".to_string());
    // Create instance of GoodData REST API Client
    let gd = gd::GoodDataClient::new(connector, token);
    assert_eq!(gd.token.is_some(), true);
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
}

#[test]
fn client_can_connect() {
    let gd = connect();
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), true);

}

#[test]
fn client_can_connect_to_staging3() {
    let gd = connect_to_staging3();
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), true);

}

#[test]
fn client_can_disconnect() {
    let mut gd = connect();
    gd.disconnect();
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
}

#[test]
fn client_can_get_projects() {
    let mut gd = connect();
    gd.projects_fetch();
    assert_eq!(gd.projects.is_some(), true);
    assert_eq!(gd.user.is_some(), true);
    gd.disconnect();
}
<commit_msg>Disable test - client_can_connect_to_staging3<commit_after>extern crate gooddata_fs;

use gooddata_fs::*;

const LRU_SIZE: usize = 32;

fn connect() -> gd::GoodDataClient {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    // Create instance of GoodData REST API Client
    let mut gd = gooddata_fs::gd::GoodDataClient::new(connector, None);
    gd.connect("tomas.korcak+gem_tester@gooddata.com", "jindrisska");
    gd
}

fn connect_to_staging3() -> gd::GoodDataClient {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new("https://staging3.intgdc.com".to_string(),
                                                    LRU_SIZE);
    // Create instance of GoodData REST API Client
    let mut gd = gooddata_fs::gd::GoodDataClient::new(connector, None);
    gd.connect("tomas.korcak+gem_tester@gooddata.com", "jindrisska");
    gd
}

#[test]
fn it_creates_connector() {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    assert_eq!(connector.token_updated.is_some(), false);
}

#[test]
fn it_creates_client() {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    // Create instance of GoodData REST API Client
    let gd = gd::GoodDataClient::new(connector, None);
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
    assert_eq!(gd.token.is_some(), false);
}

#[test]
fn it_creates_client_with_token() {
    // Create instance of GoodData HTTP Connector
    let connector = gooddata_fs::gd::Connector::new(gooddata_fs::rest::url::SERVER.to_string(),
                                                    LRU_SIZE);
    let token = Some("xxx".to_string());
    // Create instance of GoodData REST API Client
    let gd = gd::GoodDataClient::new(connector, token);
    assert_eq!(gd.token.is_some(), true);
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
}

#[test]
fn client_can_connect() {
    let gd = connect();
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), true);

}

// #[test]
// fn client_can_connect_to_staging3() {
//     let gd = connect_to_staging3();
//     assert_eq!(gd.projects.is_some(), false);
//     assert_eq!(gd.user.is_some(), true);
//
// }

#[test]
fn client_can_disconnect() {
    let mut gd = connect();
    gd.disconnect();
    assert_eq!(gd.projects.is_some(), false);
    assert_eq!(gd.user.is_some(), false);
}

#[test]
fn client_can_get_projects() {
    let mut gd = connect();
    gd.projects_fetch();
    assert_eq!(gd.projects.is_some(), true);
    assert_eq!(gd.user.is_some(), true);
    gd.disconnect();
}
<|endoftext|>


<commit_before>use std::io;

fn is_prime(n: i32) -> bool {
    for a in 2..n {
        if n % a == 0 {
            return false;
        }
    }
    true
}

fn main() {
    println!("Enter value");
    let mut input = String::new();
    io::stdin().read_line(&mut input).unwrap();
    let n: i32 = input.trim().parse().unwrap();
    for i in 2..n{
        if(is_prime(i)){
            println!("{}", i);
        }
    }
}
<commit_msg>Delete prime.rs<commit_after><|endoftext|>