tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rasterizer.rs (75170B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 use api::{FontInstanceData, FontInstanceFlags, FontInstanceKey};
      6 use api::{FontInstanceOptions, FontInstancePlatformOptions};
      7 use api::{FontKey, FontRenderMode, FontSize, FontTemplate, FontVariation};
      8 use api::{ColorU, GlyphIndex, GlyphDimensions, SyntheticItalics};
      9 use api::{IdNamespace, BlobImageResources};
     10 use api::channel::crossbeam::{unbounded, Receiver, Sender};
     11 use api::units::*;
     12 use api::ImageFormat;
     13 use crate::platform::font::FontContext;
     14 use crate::profiler::GlyphRasterizeProfiler;
     15 use crate::types::{FastHashMap, FastHashSet};
     16 use crate::telemetry::Telemetry;
     17 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
     18 use rayon::ThreadPool;
     19 use rayon::prelude::*;
     20 use euclid::approxeq::ApproxEq;
     21 use smallvec::SmallVec;
     22 use std::cmp;
     23 use std::cell::Cell;
     24 use std::hash::{Hash, Hasher};
     25 use std::mem;
     26 use std::ops::Deref;
     27 use std::sync::{Arc, Condvar, Mutex, MutexGuard, Weak};
     28 use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
     29 use std::sync::atomic::{AtomicBool, Ordering};
     30 
     31 pub static GLYPH_FLASHING: AtomicBool = AtomicBool::new(false);
     32 const GLYPH_BATCH_SIZE: usize = 32;
     33 
     34 impl FontContexts {
     35    /// Get access to the font context associated to the current thread.
     36    pub fn lock_current_context(&self) -> MutexGuard<FontContext> {
     37        match self.current_worker_id() {
     38            Some(id) => self.lock_context(id),
     39            None => self.lock_any_context(),
     40        }
     41    }
     42 
     43    pub(in super) fn current_worker_id(&self) -> Option<usize> {
     44        self.workers.current_thread_index()
     45    }
     46 }
     47 
     48 thread_local! {
     49    pub static SEED: Cell<u32> = Cell::new(0);
     50 }
     51 
     52 // super simple random to avoid dependency on rand
     53 fn random() -> u32 {
     54    SEED.with(|seed| {
     55        seed.set(seed.get().wrapping_mul(22695477).wrapping_add(1));
     56        seed.get()
     57    })
     58 }
     59 
     60 impl GlyphRasterizer {
     61    pub fn request_glyphs<F>(
     62        &mut self,
     63        font: FontInstance,
     64        glyph_keys: &[GlyphKey],
     65        mut handle: F,
     66    )
     67    where F: FnMut(&GlyphKey) -> bool
     68    {
     69        assert!(self.has_font(font.font_key));
     70 
     71        let mut batch_size = 0;
     72 
     73        // select glyphs that have not been requested yet.
     74        for key in glyph_keys {
     75            if !handle(key) {
     76                continue;
     77            }
     78 
     79            // Increment the total number of glyphs that are pending. This is used to determine
     80            // later whether to use worker threads for the remaining glyphs during resolve time.
     81            self.pending_glyph_count += 1;
     82            self.glyph_request_count += 1;
     83 
     84            // Find a batch container for the font instance for this glyph. Use get_mut to avoid
     85            // cloning the font instance, since this is the common path.
     86            match self.pending_glyph_requests.get_mut(&font) {
     87                Some(container) => {
     88                    container.push(*key);
     89                    batch_size = container.len();
     90                }
     91                None => {
     92                    // If no batch exists for this font instance, add the glyph to a new one.
     93                    self.pending_glyph_requests.insert(
     94                        font.clone(),
     95                        smallvec![*key],
     96                    );
     97                }
     98            }
     99        }
    100 
    101        // If the batch for this font instance is big enough, kick off an async
    102        // job to start rasterizing these glyphs on other threads now.
    103        if batch_size >= GLYPH_BATCH_SIZE {
    104            let container = self.pending_glyph_requests.get_mut(&font).unwrap();
    105            let glyphs = mem::replace(container, SmallVec::new());
    106            self.flush_glyph_requests(font, glyphs, true);
    107        }
    108    }
    109 
    110    pub fn enable_multithreading(&mut self, enable: bool) {
    111        self.enable_multithreading = enable;
    112    }
    113 
    114    /// Internal method to flush a list of glyph requests to a set of worker threads,
    115    /// or process on this thread if there isn't much work to do (in which case the
    116    /// overhead of processing these on a thread is unlikely to be a performance win).
    117    fn flush_glyph_requests(
    118        &mut self,
    119        font: FontInstance,
    120        glyphs: SmallVec<[GlyphKey; 16]>,
    121        use_workers: bool,
    122    ) {
    123        let font = Arc::new(font);
    124        let font_contexts = Arc::clone(&self.font_contexts);
    125        self.pending_glyph_jobs += glyphs.len();
    126        self.pending_glyph_count -= glyphs.len();
    127 
    128        let can_use_r8_format = self.can_use_r8_format;
    129 
    130        // if the number of glyphs is small, do it inline to avoid the threading overhead;
    131        // send the result into glyph_tx so downstream code can't tell the difference.
    132        if let Some(thread) = &self.dedicated_thread {
    133            let tx = self.glyph_tx.clone();
    134            let _ = thread.tx.send(GlyphRasterMsg::Rasterize { font, glyphs, can_use_r8_format, tx });
    135        } else if self.enable_multithreading && use_workers {
    136            // spawn an async task to get off of the render backend thread as early as
    137            // possible and in that task use rayon's fork join dispatch to rasterize the
    138            // glyphs in the thread pool.
    139            profile_scope!("spawning process_glyph jobs");
    140            let tx = self.glyph_tx.clone();
    141            self.workers.spawn(move || {
    142                FontContext::begin_rasterize(&font);
    143                // If the FontContext supports distributing a font across multiple threads,
    144                // then use par_iter so different glyphs of the same font are processed on
    145                // multiple threads.
    146                if FontContext::distribute_across_threads() {
    147                    glyphs.par_iter().for_each(|key| {
    148                        let mut context = font_contexts.lock_current_context();
    149                        let job_font = font.clone();
    150                        let job = process_glyph(&mut context, can_use_r8_format, job_font, *key);
    151                        tx.send(job).unwrap();
    152                    });
    153                } else {
    154                    // For FontContexts that prefer to localize a font to a single thread,
    155                    // just process all the glyphs on the same worker to avoid contention.
    156                    for key in glyphs {
    157                        let mut context = font_contexts.lock_current_context();
    158                        let job_font = font.clone();
    159                        let job = process_glyph(&mut context, can_use_r8_format, job_font, key);
    160                        tx.send(job).unwrap();
    161                    }
    162                }
    163                FontContext::end_rasterize(&font);
    164            });
    165        } else {
    166            FontContext::begin_rasterize(&font);
    167            for key in glyphs {
    168                let mut context = font_contexts.lock_current_context();
    169                let job_font = font.clone();
    170                let job = process_glyph(&mut context, can_use_r8_format, job_font, key);
    171            self.glyph_tx.send(job).unwrap();
    172            }
    173            FontContext::end_rasterize(&font);
    174        }
    175    }
    176 
    177    pub fn resolve_glyphs<F, G>(
    178        &mut self,
    179        mut handle: F,
    180        profile: &mut G,
    181    )
    182    where
    183        F: FnMut(GlyphRasterJob, bool),
    184        G: GlyphRasterizeProfiler,
    185    {
    186        profile.start_time();
    187        let timer_id = Telemetry::start_rasterize_glyphs_time();
    188 
    189        // Work around the borrow checker, since we call flush_glyph_requests below
    190        let mut pending_glyph_requests = mem::replace(
    191            &mut self.pending_glyph_requests,
    192            FastHashMap::default(),
    193        );
    194        // If we have a large amount of remaining work to do, spawn to worker threads,
    195        // even if that work is shared among a number of different font instances.
    196        let use_workers = self.pending_glyph_count >= 8;
    197        for (font, pending_glyphs) in pending_glyph_requests.drain() {
    198            self.flush_glyph_requests(
    199                font,
    200                pending_glyphs,
    201                use_workers,
    202            );
    203        }
    204        // Restore this so that we don't heap allocate next frame
    205        self.pending_glyph_requests = pending_glyph_requests;
    206        debug_assert_eq!(self.pending_glyph_count, 0);
    207        debug_assert!(self.pending_glyph_requests.is_empty());
    208 
    209        if self.glyph_request_count > 0 {
    210            profile.set(self.glyph_request_count as f64);
    211            self.glyph_request_count = 0;
    212        }
    213 
    214        profile_scope!("resolve_glyphs");
    215        // TODO: rather than blocking until all pending glyphs are available
    216        // we could try_recv and steal work from the thread pool to take advantage
    217        // of the fact that this thread is alive and we avoid the added latency
    218        // of blocking it.
    219        let mut jobs = {
    220            profile_scope!("blocking wait on glyph_rx");
    221            self.glyph_rx.iter().take(self.pending_glyph_jobs).collect::<Vec<_>>()
    222        };
    223        assert_eq!(jobs.len(), self.pending_glyph_jobs, "BUG: Didn't receive all pending glyphs!");
    224        self.pending_glyph_jobs = 0;
    225 
    226        // Ensure that the glyphs are always processed in the same
    227        // order for a given text run (since iterating a hash set doesn't
    228        // guarantee order). This can show up as very small float inaccuracy
    229        // differences in rasterizers due to the different coordinates
    230        // that text runs get associated with by the texture cache allocator.
    231        jobs.sort_by(|a, b| (*a.font).cmp(&*b.font).then(a.key.cmp(&b.key)));
    232 
    233        for job in jobs {
    234            handle(job, self.can_use_r8_format);
    235        }
    236 
    237        // Now that we are done with the critical path (rendering the glyphs),
    238        // we can schedule removing the fonts if needed.
    239        self.remove_dead_fonts();
    240 
    241        Telemetry::stop_and_accumulate_rasterize_glyphs_time(timer_id);
    242        profile.end_time();
    243    }
    244 }
    245 
    246 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
    247 #[cfg_attr(feature = "capture", derive(Serialize))]
    248 #[cfg_attr(feature = "replay", derive(Deserialize))]
    249 pub struct FontTransform {
    250    pub scale_x: f32,
    251    pub skew_x: f32,
    252    pub skew_y: f32,
    253    pub scale_y: f32,
    254 }
    255 
    256 // Floats don't impl Hash/Eq/Ord...
    257 impl Eq for FontTransform {}
    258 impl Ord for FontTransform {
    259    fn cmp(&self, other: &Self) -> cmp::Ordering {
    260        self.partial_cmp(other).unwrap_or(cmp::Ordering::Equal)
    261    }
    262 }
    263 impl Hash for FontTransform {
    264    fn hash<H: Hasher>(&self, state: &mut H) {
    265        // Note: this is inconsistent with the Eq impl for -0.0 (don't care).
    266        self.scale_x.to_bits().hash(state);
    267        self.skew_x.to_bits().hash(state);
    268        self.skew_y.to_bits().hash(state);
    269        self.scale_y.to_bits().hash(state);
    270    }
    271 }
    272 
    273 impl FontTransform {
    274    const QUANTIZE_SCALE: f32 = 1024.0;
    275 
    276    pub fn new(scale_x: f32, skew_x: f32, skew_y: f32, scale_y: f32) -> Self {
    277        FontTransform { scale_x, skew_x, skew_y, scale_y }
    278    }
    279 
    280    pub fn identity() -> Self {
    281        FontTransform::new(1.0, 0.0, 0.0, 1.0)
    282    }
    283 
    284    #[allow(dead_code)]
    285    pub fn is_identity(&self) -> bool {
    286        *self == FontTransform::identity()
    287    }
    288 
    289    pub fn quantize(&self) -> Self {
    290        FontTransform::new(
    291            (self.scale_x * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
    292            (self.skew_x * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
    293            (self.skew_y * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
    294            (self.scale_y * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
    295        )
    296    }
    297 
    298    #[allow(dead_code)]
    299    pub fn determinant(&self) -> f64 {
    300        self.scale_x as f64 * self.scale_y as f64 - self.skew_y as f64 * self.skew_x as f64
    301    }
    302 
    303    #[allow(dead_code)]
    304    pub fn compute_scale(&self) -> Option<(f64, f64)> {
    305        let det = self.determinant();
    306        if det != 0.0 {
    307            let x_scale = (self.scale_x as f64).hypot(self.skew_y as f64);
    308            let y_scale = det.abs() / x_scale;
    309            Some((x_scale, y_scale))
    310        } else {
    311            None
    312        }
    313    }
    314 
    315    #[allow(dead_code)]
    316    pub fn pre_scale(&self, scale_x: f32, scale_y: f32) -> Self {
    317        FontTransform::new(
    318            self.scale_x * scale_x,
    319            self.skew_x * scale_y,
    320            self.skew_y * scale_x,
    321            self.scale_y * scale_y,
    322        )
    323    }
    324 
    325    #[allow(dead_code)]
    326    pub fn scale(&self, scale: f32) -> Self { self.pre_scale(scale, scale) }
    327 
    328    #[allow(dead_code)]
    329    pub fn invert_scale(&self, x_scale: f64, y_scale: f64) -> Self {
    330        self.pre_scale(x_scale.recip() as f32, y_scale.recip() as f32)
    331    }
    332 
    333    pub fn synthesize_italics(&self, angle: SyntheticItalics, size: f64, vertical: bool) -> (Self, (f64, f64)) {
    334        let skew_factor = angle.to_skew();
    335        if vertical {
    336          // origin delta to be applied so that we effectively skew around
    337          // the middle rather than edge of the glyph
    338          let (tx, ty) = (0.0, -size * 0.5 * skew_factor as f64);
    339          (FontTransform::new(
    340              self.scale_x + self.skew_x * skew_factor,
    341              self.skew_x,
    342              self.skew_y + self.scale_y * skew_factor,
    343              self.scale_y,
    344          ), (self.scale_x as f64 * tx + self.skew_x as f64 * ty,
    345              self.skew_y as f64 * tx + self.scale_y as f64 * ty))
    346        } else {
    347          (FontTransform::new(
    348              self.scale_x,
    349              self.skew_x - self.scale_x * skew_factor,
    350              self.skew_y,
    351              self.scale_y - self.skew_y * skew_factor,
    352          ), (0.0, 0.0))
    353        }
    354    }
    355 
    356    pub fn swap_xy(&self) -> Self {
    357        FontTransform::new(self.skew_x, self.scale_x, self.scale_y, self.skew_y)
    358    }
    359 
    360    pub fn flip_x(&self) -> Self {
    361        FontTransform::new(-self.scale_x, self.skew_x, -self.skew_y, self.scale_y)
    362    }
    363 
    364    pub fn flip_y(&self) -> Self {
    365        FontTransform::new(self.scale_x, -self.skew_x, self.skew_y, -self.scale_y)
    366    }
    367 
    368    pub fn transform(&self, point: &LayoutPoint) -> DevicePoint {
    369        DevicePoint::new(
    370            self.scale_x * point.x + self.skew_x * point.y,
    371            self.skew_y * point.x + self.scale_y * point.y,
    372        )
    373    }
    374 
    375    pub fn get_subpx_dir(&self) -> SubpixelDirection {
    376        if self.skew_y.approx_eq(&0.0) {
    377            // The X axis is not projected onto the Y axis
    378            SubpixelDirection::Horizontal
    379        } else if self.scale_x.approx_eq(&0.0) {
    380            // The X axis has been swapped with the Y axis
    381            SubpixelDirection::Vertical
    382        } else {
    383            // Mixed transforms get no subpixel positioning
    384            SubpixelDirection::None
    385        }
    386    }
    387 }
    388 
    389 impl<'a> From<&'a LayoutToWorldTransform> for FontTransform {
    390    fn from(xform: &'a LayoutToWorldTransform) -> Self {
    391        FontTransform::new(xform.m11, xform.m21, xform.m12, xform.m22)
    392    }
    393 }
    394 
    395 // Some platforms (i.e. Windows) may have trouble rasterizing glyphs above this size.
    396 // Ensure glyph sizes are reasonably limited to avoid that scenario.
    397 pub const FONT_SIZE_LIMIT: f32 = 320.0;
    398 
    399 /// Immutable description of a font instance's shared state.
    400 ///
    401 /// `BaseFontInstance` can be identified by a `FontInstanceKey` to avoid hashing it.
    402 #[derive(Clone, Debug, Ord, PartialOrd, MallocSizeOf)]
    403 #[cfg_attr(feature = "capture", derive(Serialize))]
    404 #[cfg_attr(feature = "replay", derive(Deserialize))]
    405 pub struct BaseFontInstance {
    406    ///
    407    pub instance_key: FontInstanceKey,
    408    ///
    409    pub font_key: FontKey,
    410    ///
    411    pub size: FontSize,
    412    ///
    413    pub options: FontInstanceOptions,
    414    ///
    415    #[cfg_attr(any(feature = "capture", feature = "replay"), serde(skip))]
    416    pub platform_options: Option<FontInstancePlatformOptions>,
    417    ///
    418    pub variations: Vec<FontVariation>,
    419 }
    420 
    421 impl BaseFontInstance {
    422    pub fn new(
    423        instance_key: FontInstanceKey,
    424        font_key: FontKey,
    425        size: f32,
    426        options: Option<FontInstanceOptions>,
    427        platform_options: Option<FontInstancePlatformOptions>,
    428        variations: Vec<FontVariation>,
    429    ) -> Self {
    430        BaseFontInstance {
    431            instance_key,
    432            font_key,
    433            size: size.into(),
    434            options: options.unwrap_or_default(),
    435            platform_options,
    436            variations,
    437        }
    438    }
    439 }
    440 
    441 impl Deref for BaseFontInstance {
    442    type Target = FontInstanceOptions;
    443    fn deref(&self) -> &FontInstanceOptions {
    444        &self.options
    445    }
    446 }
    447 
    448 impl Hash for BaseFontInstance {
    449    fn hash<H: Hasher>(&self, state: &mut H) {
    450        // Skip the instance key.
    451        self.font_key.hash(state);
    452        self.size.hash(state);
    453        self.options.hash(state);
    454        self.platform_options.hash(state);
    455        self.variations.hash(state);
    456    }
    457 }
    458 
    459 impl PartialEq for BaseFontInstance {
    460    fn eq(&self, other: &BaseFontInstance) -> bool {
    461        // Skip the instance key.
    462        self.font_key == other.font_key &&
    463            self.size == other.size &&
    464            self.options == other.options &&
    465            self.platform_options == other.platform_options &&
    466            self.variations == other.variations
    467    }
    468 }
    469 impl Eq for BaseFontInstance {}
    470 
    471 struct MappedFontKey {
    472    font_key: FontKey,
    473    template: FontTemplate,
    474 }
    475 
    476 struct FontKeyMapLocked {
    477    namespace: IdNamespace,
    478    next_id: u32,
    479    template_map: FastHashMap<FontTemplate, Arc<MappedFontKey>>,
    480    key_map: FastHashMap<FontKey, Arc<MappedFontKey>>,
    481 }
    482 
    483 /// A shared map from fonts key local to a namespace to shared font keys that
    484 /// can be shared across many namespaces. Local keys are tracked in a hashmap
    485 /// that stores a strong reference per mapping so that their count can be
    486 /// tracked. A map of font templates is used to hash font templates to their
    487 /// final shared key. The shared key will stay alive so long as there are
    488 /// any strong references to the mapping entry. Care must be taken when
    489 /// clearing namespaces of shared keys as this may trigger shared font keys
    490 /// to expire which require individual processing. Shared font keys will be
    491 /// created within the provided unique namespace.
    492 #[derive(Clone)]
    493 pub struct FontKeyMap(Arc<RwLock<FontKeyMapLocked>>);
    494 
    495 impl FontKeyMap {
    496    pub fn new(namespace: IdNamespace) -> Self {
    497        FontKeyMap(Arc::new(RwLock::new(FontKeyMapLocked {
    498            namespace,
    499            next_id: 1,
    500            template_map: FastHashMap::default(),
    501            key_map: FastHashMap::default(),
    502        })))
    503    }
    504 
    505    fn lock(&self) -> RwLockReadGuard<FontKeyMapLocked> {
    506        self.0.read().unwrap()
    507    }
    508 
    509    fn lock_mut(&mut self) -> RwLockWriteGuard<FontKeyMapLocked> {
    510        self.0.write().unwrap()
    511    }
    512 
    513    pub fn keys(&self) -> Vec<FontKey> {
    514        self.lock().key_map.keys().cloned().collect()
    515    }
    516 
    517    pub fn map_key(&self, font_key: &FontKey) -> FontKey {
    518        match self.lock().key_map.get(font_key) {
    519            Some(mapped) => mapped.font_key,
    520            None => *font_key,
    521        }
    522    }
    523 
    524    pub fn add_key(&mut self, font_key: &FontKey, template: &FontTemplate) -> Option<FontKey> {
    525        let mut locked = self.lock_mut();
    526        if locked.key_map.contains_key(font_key) {
    527            return None;
    528        }
    529        if let Some(mapped) = locked.template_map.get(template).cloned() {
    530            locked.key_map.insert(*font_key, mapped);
    531            return None;
    532        }
    533        let shared_key = FontKey::new(locked.namespace, locked.next_id);
    534        locked.next_id += 1;
    535        let mapped = Arc::new(MappedFontKey {
    536            font_key: shared_key,
    537            template: template.clone(),
    538        });
    539        locked.template_map.insert(template.clone(), mapped.clone());
    540        locked.key_map.insert(*font_key, mapped);
    541        Some(shared_key)
    542    }
    543 
    544    pub fn delete_key(&mut self, font_key: &FontKey) -> Option<FontKey> {
    545        let mut locked = self.lock_mut();
    546        let mapped = match locked.key_map.remove(font_key) {
    547            Some(mapped) => mapped,
    548            None => return Some(*font_key),
    549        };
    550        if Arc::strong_count(&mapped) <= 2 {
    551            // Only the last mapped key and template map point to it.
    552            locked.template_map.remove(&mapped.template);
    553            Some(mapped.font_key)
    554        } else {
    555            None
    556        }
    557    }
    558 
    559    pub fn clear_namespace(&mut self, namespace: IdNamespace) -> Vec<FontKey> {
    560        let mut locked = self.lock_mut();
    561        locked.key_map.retain(|key, _| {
    562            if key.0 == namespace {
    563                false
    564            } else {
    565                true
    566            }
    567        });
    568        let mut deleted_keys = Vec::new();
    569        locked.template_map.retain(|_, mapped| {
    570            if Arc::strong_count(mapped) <= 1 {
    571                // Only the template map points to it.
    572                deleted_keys.push(mapped.font_key);
    573                false
    574            } else {
    575                true
    576            }
    577        });
    578        deleted_keys
    579    }
    580 }
    581 
    582 type FontTemplateMapLocked = FastHashMap<FontKey, FontTemplate>;
    583 
    584 /// A map of font keys to font templates that might hold both namespace-local
    585 /// font templates as well as shared templates.
    586 #[derive(Clone)]
    587 pub struct FontTemplateMap(Arc<RwLock<FontTemplateMapLocked>>);
    588 
    589 impl FontTemplateMap {
    590    pub fn new() -> Self {
    591        FontTemplateMap(Arc::new(RwLock::new(FastHashMap::default())))
    592    }
    593 
    594    pub fn lock(&self) -> RwLockReadGuard<FontTemplateMapLocked> {
    595        self.0.read().unwrap()
    596    }
    597 
    598    fn lock_mut(&mut self) -> RwLockWriteGuard<FontTemplateMapLocked> {
    599        self.0.write().unwrap()
    600    }
    601 
    602    pub fn clear(&mut self) {
    603        self.lock_mut().clear();
    604    }
    605 
    606    pub fn len(&self) -> usize {
    607        self.lock().len()
    608    }
    609 
    610    pub fn has_font(&self, key: &FontKey) -> bool {
    611        self.lock().contains_key(key)
    612    }
    613 
    614    pub fn get_font(&self, key: &FontKey) -> Option<FontTemplate> {
    615        self.lock().get(key).cloned()
    616    }
    617 
    618    pub fn add_font(&mut self, key: FontKey, template: FontTemplate) -> bool {
    619        self.lock_mut().insert(key, template).is_none()
    620    }
    621 
    622    pub fn delete_font(&mut self, key: &FontKey) -> Option<FontTemplate> {
    623        self.lock_mut().remove(key)
    624    }
    625 
    626    pub fn delete_fonts(&mut self, keys: &[FontKey]) {
    627        if !keys.is_empty() {
    628            let mut map = self.lock_mut();
    629            for key in keys {
    630                map.remove(key);
    631            }
    632        }
    633    }
    634 
    635    pub fn clear_namespace(&mut self, namespace: IdNamespace) -> Vec<FontKey> {
    636        let mut deleted_keys = Vec::new();
    637        self.lock_mut().retain(|key, _| {
    638            if key.0 == namespace {
    639                deleted_keys.push(*key);
    640                false
    641            } else {
    642                true
    643            }
    644        });
    645        deleted_keys
    646    }
    647 }
    648 
    649 struct FontInstanceKeyMapLocked {
    650    namespace: IdNamespace,
    651    next_id: u32,
    652    instances: FastHashSet<Arc<BaseFontInstance>>,
    653    key_map: FastHashMap<FontInstanceKey, Weak<BaseFontInstance>>,
    654 }
    655 
    656 /// A map of namespace-local font instance keys to shared keys. Weak references
    657 /// are used to track the liveness of each key mapping as other consumers of
    658 /// BaseFontInstance might hold strong references to the entry. A mapping from
    659 /// BaseFontInstance to the shared key is then used to determine which shared
    660 /// key to assign to that instance. When the weak count of the mapping is zero,
    661 /// the entry is allowed to expire. Again, care must be taken when clearing
    662 /// a namespace within the key map as it may cause shared key expirations that
    663 /// require individual processing. Shared instance keys will be created within
    664 /// the provided unique namespace.
    665 #[derive(Clone)]
    666 pub struct FontInstanceKeyMap(Arc<RwLock<FontInstanceKeyMapLocked>>);
    667 
    668 impl FontInstanceKeyMap {
    669    pub fn new(namespace: IdNamespace) -> Self {
    670        FontInstanceKeyMap(Arc::new(RwLock::new(FontInstanceKeyMapLocked {
    671            namespace,
    672            next_id: 1,
    673            instances: FastHashSet::default(),
    674            key_map: FastHashMap::default(),
    675        })))
    676    }
    677 
    678    fn lock(&self) -> RwLockReadGuard<FontInstanceKeyMapLocked> {
    679        self.0.read().unwrap()
    680    }
    681 
    682    fn lock_mut(&mut self) -> RwLockWriteGuard<FontInstanceKeyMapLocked> {
    683        self.0.write().unwrap()
    684    }
    685 
    686    pub fn keys(&self) -> Vec<FontInstanceKey> {
    687        self.lock().key_map.keys().cloned().collect()
    688    }
    689 
    690    pub fn map_key(&self, key: &FontInstanceKey) -> FontInstanceKey {
    691        match self.lock().key_map.get(key).and_then(|weak| weak.upgrade()) {
    692            Some(mapped) => mapped.instance_key,
    693            None => *key,
    694        }
    695    }
    696 
    697    pub fn add_key(&mut self, mut instance: BaseFontInstance) -> Option<Arc<BaseFontInstance>> {
    698        let mut locked = self.lock_mut();
    699        if locked.key_map.contains_key(&instance.instance_key) {
    700            return None;
    701        }
    702        if let Some(weak) = locked.instances.get(&instance).map(|mapped| Arc::downgrade(mapped)) {
    703            locked.key_map.insert(instance.instance_key, weak);
    704            return None;
    705        }
    706        let unmapped_key = instance.instance_key;
    707        instance.instance_key = FontInstanceKey::new(locked.namespace, locked.next_id);
    708        locked.next_id += 1;
    709        let shared_instance = Arc::new(instance);
    710        locked.instances.insert(shared_instance.clone());
    711        locked.key_map.insert(unmapped_key, Arc::downgrade(&shared_instance));
    712        Some(shared_instance)
    713    }
    714 
    715    pub fn delete_key(&mut self, key: &FontInstanceKey) -> Option<FontInstanceKey> {
    716        let mut locked = self.lock_mut();
    717        let mapped = match locked.key_map.remove(key).and_then(|weak| weak.upgrade()) {
    718            Some(mapped) => mapped,
    719            None => return Some(*key),
    720        };
    721        if Arc::weak_count(&mapped) == 0 {
    722            // Only the instance set points to it.
    723            locked.instances.remove(&mapped);
    724            Some(mapped.instance_key)
    725        } else {
    726            None
    727        }
    728    }
    729 
    730    pub fn clear_namespace(&mut self, namespace: IdNamespace) -> Vec<FontInstanceKey> {
    731        let mut locked = self.lock_mut();
    732        locked.key_map.retain(|key, _| {
    733            if key.0 == namespace {
    734                false
    735            } else {
    736                true
    737            }
    738        });
    739        let mut deleted_keys = Vec::new();
    740        locked.instances.retain(|mapped| {
    741            if Arc::weak_count(mapped) == 0 {
    742                // Only the instance set points to it.
    743                deleted_keys.push(mapped.instance_key);
    744                false
    745            } else {
    746                true
    747            }
    748        });
    749        deleted_keys
    750    }
    751 }
    752 
    753 type FontInstanceMapLocked = FastHashMap<FontInstanceKey, Arc<BaseFontInstance>>;
    754 
    755 /// A map of font instance data accessed concurrently from multiple threads.
    756 #[derive(Clone)]
    757 pub struct FontInstanceMap(Arc<RwLock<FontInstanceMapLocked>>);
    758 
    759 impl FontInstanceMap {
    760    /// Creates an empty shared map.
    761    pub fn new() -> Self {
    762        FontInstanceMap(Arc::new(RwLock::new(FastHashMap::default())))
    763    }
    764 
    765    /// Acquires a read lock on the shared map.
    766    pub fn lock(&self) -> RwLockReadGuard<FontInstanceMapLocked> {
    767        self.0.read().unwrap()
    768    }
    769 
    770    /// Acquires a read lock on the shared map.
    771    fn lock_mut(&mut self) -> RwLockWriteGuard<FontInstanceMapLocked> {
    772        self.0.write().unwrap()
    773    }
    774 
    775    ///
    776    pub fn clear(&mut self) {
    777        self.lock_mut().clear();
    778    }
    779 
    780    ///
    781    pub fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData> {
    782        match self.lock().get(&key) {
    783            Some(instance) => Some(FontInstanceData {
    784                font_key: instance.font_key,
    785                size: instance.size.into(),
    786                options: Some(FontInstanceOptions {
    787                  render_mode: instance.render_mode,
    788                  flags: instance.flags,
    789                  synthetic_italics: instance.synthetic_italics,
    790                  _padding: 0,
    791                }),
    792                platform_options: instance.platform_options,
    793                variations: instance.variations.clone(),
    794            }),
    795            None => None,
    796        }
    797    }
    798 
    799    ///
    800    pub fn get_font_instance(&self, instance_key: FontInstanceKey) -> Option<Arc<BaseFontInstance>> {
    801        let instance_map = self.lock();
    802        instance_map.get(&instance_key).cloned()
    803    }
    804 
    805    ///
    806    pub fn add_font_instance(&mut self, instance: Arc<BaseFontInstance>) {
    807        self.lock_mut().insert(instance.instance_key, instance);
    808    }
    809 
    810    ///
    811    pub fn delete_font_instance(&mut self, instance_key: FontInstanceKey) {
    812        self.lock_mut().remove(&instance_key);
    813    }
    814 
    815    ///
    816    pub fn delete_font_instances(&mut self, keys: &[FontInstanceKey]) {
    817        if !keys.is_empty() {
    818            let mut map = self.lock_mut();
    819            for key in keys {
    820                map.remove(key);
    821            }
    822        }
    823    }
    824 
    825    ///
    826    pub fn clear_namespace(&mut self, namespace: IdNamespace) {
    827        self.lock_mut().retain(|key, _| key.0 != namespace);
    828    }
    829 }
    830 
    831 /// Shared font resources that may need to be passed between multiple threads
    832 /// such as font templates and font instances. They are individually protected
    833 /// by locks to ensure safety.
    834 #[derive(Clone)]
    835 pub struct SharedFontResources {
    836    pub templates: FontTemplateMap,
    837    pub instances: FontInstanceMap,
    838    pub font_keys: FontKeyMap,
    839    pub instance_keys: FontInstanceKeyMap,
    840 }
    841 
    842 impl SharedFontResources {
    843    pub fn new(namespace: IdNamespace) -> Self {
    844        SharedFontResources {
    845            templates: FontTemplateMap::new(),
    846            instances: FontInstanceMap::new(),
    847            font_keys: FontKeyMap::new(namespace),
    848            instance_keys: FontInstanceKeyMap::new(namespace),
    849        }
    850    }
    851 }
    852 
    853 impl BlobImageResources for SharedFontResources {
    854    fn get_font_data(&self, key: FontKey) -> Option<FontTemplate> {
    855        let shared_key = self.font_keys.map_key(&key);
    856        self.templates.get_font(&shared_key)
    857    }
    858 
    859    fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData> {
    860        let shared_key = self.instance_keys.map_key(&key);
    861        self.instances.get_font_instance_data(shared_key)
    862    }
    863 }
    864 
    865 /// A mutable font instance description.
    866 ///
    867 /// Performance is sensitive to the size of this structure, so it should only contain
    868 /// the fields that we need to modify from the original base font instance.
    869 #[derive(Clone, Debug, Ord, PartialOrd)]
    870 #[cfg_attr(feature = "capture", derive(Serialize))]
    871 #[cfg_attr(feature = "replay", derive(Deserialize))]
    872 pub struct FontInstance {
    873    pub base: Arc<BaseFontInstance>,
    874    pub transform: FontTransform,
    875    pub render_mode: FontRenderMode,
    876    pub flags: FontInstanceFlags,
    877    pub color: ColorU,
    878    // The font size is in *device/raster* pixels, not logical pixels.
    879    // It is stored as an f32 since we need sub-pixel sizes.
    880    pub size: FontSize,
    881 }
    882 
    883 impl Hash for FontInstance {
    884    fn hash<H: Hasher>(&self, state: &mut H) {
    885        // Hash only the base instance's key to avoid the cost of hashing
    886        // the rest.
    887        self.base.instance_key.hash(state);
    888        self.transform.hash(state);
    889        self.render_mode.hash(state);
    890        self.flags.hash(state);
    891        self.color.hash(state);
    892        self.size.hash(state);
    893    }
    894 }
    895 
    896 impl PartialEq for FontInstance {
    897    fn eq(&self, other: &FontInstance) -> bool {
    898        // Compare only the base instance's key.
    899        self.base.instance_key == other.base.instance_key &&
    900            self.transform == other.transform &&
    901            self.render_mode == other.render_mode &&
    902            self.flags == other.flags &&
    903            self.color == other.color &&
    904            self.size == other.size
    905    }
    906 }
    907 impl Eq for FontInstance {}
    908 
    909 impl Deref for FontInstance {
    910    type Target = BaseFontInstance;
    911    fn deref(&self) -> &BaseFontInstance {
    912        self.base.as_ref()
    913    }
    914 }
    915 
    916 impl MallocSizeOf for  FontInstance {
    917    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { 0 }
    918 }
    919 
    920 impl FontInstance {
    921    pub fn new(
    922        base: Arc<BaseFontInstance>,
    923        color: ColorU,
    924        render_mode: FontRenderMode,
    925        flags: FontInstanceFlags,
    926    ) -> Self {
    927        FontInstance {
    928            transform: FontTransform::identity(),
    929            color,
    930            size: base.size,
    931            base,
    932            render_mode,
    933            flags,
    934        }
    935    }
    936 
    937    pub fn from_base(
    938        base: Arc<BaseFontInstance>,
    939    ) -> Self {
    940        let color = ColorU::new(0, 0, 0, 255);
    941        let render_mode = base.render_mode;
    942        let flags = base.flags;
    943        Self::new(base, color, render_mode, flags)
    944    }
    945 
    946    pub fn use_texture_padding(&self) -> bool {
    947        self.flags.contains(FontInstanceFlags::TEXTURE_PADDING)
    948    }
    949 
    950    pub fn use_transform_glyphs(&self) -> bool {
    951        self.flags.contains(FontInstanceFlags::TRANSFORM_GLYPHS)
    952    }
    953 
    954    pub fn get_alpha_glyph_format(&self) -> GlyphFormat {
    955        if self.use_transform_glyphs() { GlyphFormat::TransformedAlpha } else { GlyphFormat::Alpha }
    956    }
    957 
    958    pub fn get_subpixel_glyph_format(&self) -> GlyphFormat {
    959        if self.use_transform_glyphs() { GlyphFormat::TransformedSubpixel } else { GlyphFormat::Subpixel }
    960    }
    961 
    962    pub fn disable_subpixel_aa(&mut self) {
    963        self.render_mode = self.render_mode.limit_by(FontRenderMode::Alpha);
    964    }
    965 
    966    pub fn disable_subpixel_position(&mut self) {
    967        self.flags.remove(FontInstanceFlags::SUBPIXEL_POSITION);
    968    }
    969 
    970    pub fn use_subpixel_position(&self) -> bool {
    971        self.flags.contains(FontInstanceFlags::SUBPIXEL_POSITION) &&
    972        self.render_mode != FontRenderMode::Mono
    973    }
    974 
    975    pub fn get_subpx_dir(&self) -> SubpixelDirection {
    976        if self.use_subpixel_position() {
    977            let mut subpx_dir = self.transform.get_subpx_dir();
    978            if self.flags.contains(FontInstanceFlags::TRANSPOSE) {
    979                subpx_dir = subpx_dir.swap_xy();
    980            }
    981            subpx_dir
    982        } else {
    983            SubpixelDirection::None
    984        }
    985    }
    986 
    987    #[allow(dead_code)]
    988    pub fn get_subpx_offset(&self, glyph: &GlyphKey) -> (f64, f64) {
    989        if self.use_subpixel_position() {
    990            let (dx, dy) = glyph.subpixel_offset();
    991            (dx.into(), dy.into())
    992        } else {
    993            (0.0, 0.0)
    994        }
    995    }
    996 
    997    #[allow(dead_code)]
    998    pub fn get_glyph_format(&self) -> GlyphFormat {
    999        match self.render_mode {
   1000            FontRenderMode::Mono | FontRenderMode::Alpha => self.get_alpha_glyph_format(),
   1001            FontRenderMode::Subpixel => self.get_subpixel_glyph_format(),
   1002        }
   1003    }
   1004 
   1005    #[allow(dead_code)]
   1006    pub fn get_extra_strikes(&self, flags: FontInstanceFlags, x_scale: f64) -> usize {
   1007        if self.flags.intersects(flags) {
   1008            let mut bold_offset = self.size.to_f64_px() / 48.0;
   1009            if bold_offset < 1.0 {
   1010                bold_offset = 0.25 + 0.75 * bold_offset;
   1011            }
   1012            (bold_offset * x_scale).max(1.0).round() as usize
   1013        } else {
   1014            0
   1015        }
   1016    }
   1017 
   1018    pub fn synthesize_italics(&self, transform: FontTransform, size: f64) -> (FontTransform, (f64, f64)) {
   1019        transform.synthesize_italics(self.synthetic_italics, size, self.flags.contains(FontInstanceFlags::VERTICAL))
   1020    }
   1021 
   1022    #[allow(dead_code)]
   1023    pub fn get_transformed_size(&self) -> f64 {
   1024        let (_, y_scale) = self.transform.compute_scale().unwrap_or((1.0, 1.0));
   1025        self.size.to_f64_px() * y_scale
   1026    }
   1027 }
   1028 
   1029 #[repr(u32)]
   1030 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
   1031 pub enum SubpixelDirection {
   1032    None = 0,
   1033    Horizontal,
   1034    Vertical,
   1035 }
   1036 
   1037 impl SubpixelDirection {
   1038    // Limit the subpixel direction to what is supported by the glyph format.
   1039    pub fn limit_by(self, glyph_format: GlyphFormat) -> Self {
   1040        match glyph_format {
   1041            GlyphFormat::Bitmap |
   1042            GlyphFormat::ColorBitmap => SubpixelDirection::None,
   1043            _ => self,
   1044        }
   1045    }
   1046 
   1047    pub fn swap_xy(self) -> Self {
   1048        match self {
   1049            SubpixelDirection::None => self,
   1050            SubpixelDirection::Horizontal => SubpixelDirection::Vertical,
   1051            SubpixelDirection::Vertical => SubpixelDirection::Horizontal,
   1052        }
   1053    }
   1054 }
   1055 
   1056 #[repr(u8)]
   1057 #[derive(Hash, Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
   1058 #[cfg_attr(feature = "capture", derive(Serialize))]
   1059 #[cfg_attr(feature = "replay", derive(Deserialize))]
   1060 pub enum SubpixelOffset {
   1061    Zero = 0,
   1062    Quarter = 1,
   1063    Half = 2,
   1064    ThreeQuarters = 3,
   1065 }
   1066 
   1067 impl SubpixelOffset {
   1068    // Skia quantizes subpixel offsets into 1/4 increments.
   1069    // Given the absolute position, return the quantized increment
   1070    fn quantize(pos: f32) -> Self {
   1071        // Following the conventions of Gecko and Skia, we want
   1072        // to quantize the subpixel position, such that abs(pos) gives:
   1073        // [0.0, 0.125) -> Zero
   1074        // [0.125, 0.375) -> Quarter
   1075        // [0.375, 0.625) -> Half
   1076        // [0.625, 0.875) -> ThreeQuarters,
   1077        // [0.875, 1.0) -> Zero
   1078        // The unit tests below check for this.
   1079        let apos = ((pos - pos.floor()) * 8.0) as i32;
   1080 
   1081        match apos {
   1082            1..=2 => SubpixelOffset::Quarter,
   1083            3..=4 => SubpixelOffset::Half,
   1084            5..=6 => SubpixelOffset::ThreeQuarters,
   1085            _ => SubpixelOffset::Zero,
   1086        }
   1087    }
   1088 }
   1089 
   1090 impl Into<f64> for SubpixelOffset {
   1091    fn into(self) -> f64 {
   1092        match self {
   1093            SubpixelOffset::Zero => 0.0,
   1094            SubpixelOffset::Quarter => 0.25,
   1095            SubpixelOffset::Half => 0.5,
   1096            SubpixelOffset::ThreeQuarters => 0.75,
   1097        }
   1098    }
   1099 }
   1100 
   1101 impl SubpixelOffset {
   1102    fn to_f32(self) -> f32 {
   1103        match self {
   1104            SubpixelOffset::Zero => 0.0,
   1105            SubpixelOffset::Quarter => 0.25,
   1106            SubpixelOffset::Half => 0.5,
   1107            SubpixelOffset::ThreeQuarters => 0.75,
   1108        }
   1109    }
   1110 }
   1111 
   1112 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
   1113 #[cfg_attr(feature = "capture", derive(Serialize))]
   1114 #[cfg_attr(feature = "replay", derive(Deserialize))]
   1115 pub struct GlyphKey(u32);
   1116 
   1117 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
   1118 #[cfg_attr(feature = "capture", derive(Serialize))]
   1119 #[cfg_attr(feature = "replay", derive(Deserialize))]
   1120 pub struct GlyphCacheKey(u32);
   1121 
   1122 impl GlyphKey {
   1123    pub fn new(
   1124        index: u32,
   1125        point: DevicePoint,
   1126        subpx_dir: SubpixelDirection,
   1127    ) -> Self {
   1128        let (dx, dy) = match subpx_dir {
   1129            SubpixelDirection::None => (0.0, 0.0),
   1130            SubpixelDirection::Horizontal => (point.x, 0.0),
   1131            SubpixelDirection::Vertical => (0.0, point.y),
   1132        };
   1133        let sox = SubpixelOffset::quantize(dx);
   1134        let soy = SubpixelOffset::quantize(dy);
   1135        assert_eq!(0, index & 0xFC000000);
   1136 
   1137        GlyphKey(index | (sox as u32) << 26 | (soy as u32) << 28 | (subpx_dir as u32) << 30)
   1138    }
   1139 
   1140    pub fn index(&self) -> GlyphIndex {
   1141        self.0 & 0x03FFFFFF
   1142    }
   1143 
   1144    pub fn subpixel_offset(&self) -> (SubpixelOffset, SubpixelOffset) {
   1145        let x = (self.0 >> 26) as u8 & 3;
   1146        let y = (self.0 >> 28) as u8 & 3;
   1147        unsafe {
   1148            (mem::transmute(x), mem::transmute(y))
   1149        }
   1150    }
   1151 
   1152    pub fn subpixel_dir(&self) -> SubpixelDirection {
   1153        let dir = (self.0 >> 30) as u8 & 3;
   1154        unsafe {
   1155            mem::transmute(dir as u32)
   1156        }
   1157    }
   1158 
   1159    pub fn cache_key(&self) -> GlyphCacheKey {
   1160        let index = self.index();
   1161        let subpx_dir = self.subpixel_dir();
   1162        assert_eq!(0, index & 0xFC000000);
   1163        GlyphCacheKey(index | (subpx_dir as u32) << 30)
   1164    }
   1165 }
   1166 
   1167 impl GlyphCacheKey {
   1168    pub fn index(&self) -> GlyphIndex {
   1169        self.0 & 0x03FFFFFF
   1170    }
   1171 
   1172    pub fn subpixel_dir(&self) -> SubpixelDirection {
   1173        let dir = ((self.0 >> 30) & 3) as u32;
   1174        unsafe {
   1175            mem::transmute(dir)
   1176        }
   1177    }
   1178 }
   1179 
   1180 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
   1181 #[cfg_attr(feature = "capture", derive(Serialize))]
   1182 #[cfg_attr(feature = "replay", derive(Deserialize))]
   1183 #[allow(dead_code)]
   1184 pub enum GlyphFormat {
   1185    Alpha,
   1186    TransformedAlpha,
   1187    Subpixel,
   1188    TransformedSubpixel,
   1189    Bitmap,
   1190    ColorBitmap,
   1191 }
   1192 
   1193 impl GlyphFormat {
   1194    /// Returns the ImageFormat that a glyph should be stored as in the texture cache.
   1195    /// can_use_r8_format should be set false on platforms where we have encountered
   1196    /// issues with R8 textures, so that we do not use them for glyphs.
   1197    pub fn image_format(&self, can_use_r8_format: bool) -> ImageFormat {
   1198        match *self {
   1199            GlyphFormat::Alpha |
   1200            GlyphFormat::TransformedAlpha |
   1201            GlyphFormat::Bitmap => {
   1202                if can_use_r8_format {
   1203                    ImageFormat::R8
   1204                } else {
   1205                    ImageFormat::BGRA8
   1206                }
   1207            }
   1208            GlyphFormat::Subpixel |
   1209            GlyphFormat::TransformedSubpixel |
   1210            GlyphFormat::ColorBitmap => ImageFormat::BGRA8,
   1211        }
   1212    }
   1213 }
   1214 
   1215 #[allow(dead_code)]
   1216 #[inline]
   1217 fn blend_strike_pixel(dest: u8, src: u32, src_alpha: u32) -> u8 {
   1218    // Assume premultiplied alpha such that src and dest are already multiplied
   1219    // by their respective alpha values and in range 0..=255. The rounded over
   1220    // blend is then (src * 255 + dest * (255 - src_alpha) + 128) / 255.
   1221    // We approximate (x + 128) / 255 as (x + 128 + ((x + 128) >> 8)) >> 8.
   1222    let x = src * 255 + dest as u32 * (255 - src_alpha) + 128;
   1223    ((x + (x >> 8)) >> 8) as u8
   1224 }
   1225 
   1226 // Blends a single strike at a given offset into a destination buffer, assuming
   1227 // the destination has been allocated with enough extra space to accommodate the
   1228 // offset.
   1229 #[allow(dead_code)]
   1230 fn blend_strike(
   1231    dest_bitmap: &mut [u8],
   1232    src_bitmap: &[u8],
   1233    width: usize,
   1234    height: usize,
   1235    subpixel_mask: bool,
   1236    offset: f64,
   1237 ) {
   1238    let dest_stride = dest_bitmap.len() / height;
   1239    let src_stride = width * 4;
   1240    let offset_integer = offset.floor() as usize * 4;
   1241    let offset_fract = (offset.fract() * 256.0) as u32;
   1242    for (src_row, dest_row) in src_bitmap.chunks(src_stride).zip(dest_bitmap.chunks_mut(dest_stride)) {
   1243        let mut prev_px = [0u32; 4];
   1244        let dest_row_offset = &mut dest_row[offset_integer .. offset_integer + src_stride];
   1245        for (src, dest) in src_row.chunks(4).zip(dest_row_offset.chunks_mut(4)) {
   1246            let px = [src[0] as u32, src[1] as u32, src[2] as u32, src[3] as u32];
   1247            // Blend current pixel with previous pixel based on fractional offset.
   1248            let next_px = [px[0] * offset_fract,
   1249                           px[1] * offset_fract,
   1250                           px[2] * offset_fract,
   1251                           px[3] * offset_fract];
   1252            let offset_px = [(((px[0] << 8) - next_px[0]) + prev_px[0] + 128) >> 8,
   1253                             (((px[1] << 8) - next_px[1]) + prev_px[1] + 128) >> 8,
   1254                             (((px[2] << 8) - next_px[2]) + prev_px[2] + 128) >> 8,
   1255                             (((px[3] << 8) - next_px[3]) + prev_px[3] + 128) >> 8];
   1256            if subpixel_mask {
   1257                // Subpixel masks assume each component is an independent weight.
   1258                dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[0]);
   1259                dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[1]);
   1260                dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[2]);
   1261                dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
   1262            } else {
   1263                // Otherwise assume we have a premultiplied alpha BGRA value.
   1264                dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[3]);
   1265                dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[3]);
   1266                dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[3]);
   1267                dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
   1268            }
   1269            // Save the remainder for blending onto the next pixel.
   1270            prev_px = next_px;
   1271        }
   1272        if offset_fract > 0 {
   1273            // When there is fractional offset, there will be a remaining value
   1274            // from the previous pixel but no next pixel, so just use that.
   1275            let dest = &mut dest_row[offset_integer + src_stride .. ];
   1276            let offset_px = [(prev_px[0] + 128) >> 8,
   1277                             (prev_px[1] + 128) >> 8,
   1278                             (prev_px[2] + 128) >> 8,
   1279                             (prev_px[3] + 128) >> 8];
   1280            if subpixel_mask {
   1281                dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[0]);
   1282                dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[1]);
   1283                dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[2]);
   1284                dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
   1285            } else {
   1286                dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[3]);
   1287                dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[3]);
   1288                dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[3]);
   1289                dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
   1290            }
   1291        }
   1292    }
   1293 }
   1294 
   1295 // Applies multistrike bold to a source bitmap. This assumes the source bitmap
   1296 // is a tighly packed slice of BGRA pixel values of exactly the specified width
   1297 // and height. The specified extra strikes and pixel step control where to put
   1298 // each strike. The pixel step is allowed to have a fractional offset and does
   1299 // not strictly need to be integer.
   1300 #[allow(dead_code)]
   1301 pub fn apply_multistrike_bold(
   1302    src_bitmap: &[u8],
   1303    width: usize,
   1304    height: usize,
   1305    subpixel_mask: bool,
   1306    extra_strikes: usize,
   1307    pixel_step: f64,
   1308 ) -> (Vec<u8>, usize) {
   1309    let src_stride = width * 4;
   1310    // The amount of extra width added to the bitmap from the extra strikes.
   1311    let extra_width = (extra_strikes as f64 * pixel_step).ceil() as usize;
   1312    let dest_width = width + extra_width;
   1313    let dest_stride = dest_width * 4;
   1314    // Zero out the initial bitmap so any extra width is cleared.
   1315    let mut dest_bitmap = vec![0u8; dest_stride * height];
   1316    for (src_row, dest_row) in src_bitmap.chunks(src_stride).zip(dest_bitmap.chunks_mut(dest_stride)) {
   1317        // Copy the initial bitmap strike rows directly from the source.
   1318        dest_row[0 .. src_stride].copy_from_slice(src_row);
   1319    }
   1320    // Finally blend each extra strike in turn.
   1321    for i in 1 ..= extra_strikes {
   1322        let offset = i as f64 * pixel_step;
   1323        blend_strike(&mut dest_bitmap, src_bitmap, width, height, subpixel_mask, offset);
   1324    }
   1325    (dest_bitmap, dest_width)
   1326 }
   1327 
   1328 pub struct RasterizedGlyph {
   1329    pub top: f32,
   1330    pub left: f32,
   1331    pub width: i32,
   1332    pub height: i32,
   1333    pub scale: f32,
   1334    pub format: GlyphFormat,
   1335    pub bytes: Vec<u8>,
   1336    pub is_packed_glyph: bool,
   1337 }
   1338 
   1339 impl RasterizedGlyph {
   1340    #[allow(dead_code)]
   1341    pub fn downscale_bitmap_if_required(&mut self, font: &FontInstance) {
   1342        // Check if the glyph is going to be downscaled in the shader. If the scaling is
   1343        // less than 0.5, that means bilinear filtering can't effectively filter the glyph
   1344        // without aliasing artifacts.
   1345        //
   1346        // Instead of fixing this by mipmapping the glyph cache texture, rather manually
   1347        // produce the appropriate mip level for individual glyphs where bilinear filtering
   1348        // will still produce acceptable results.
   1349        match self.format {
   1350            GlyphFormat::Bitmap | GlyphFormat::ColorBitmap => {},
   1351            _ => return,
   1352        }
   1353        let (x_scale, y_scale) = font.transform.compute_scale().unwrap_or((1.0, 1.0));
   1354        let upscaled = x_scale.max(y_scale) as f32;
   1355        let mut new_scale = self.scale;
   1356        if new_scale * upscaled <= 0.0 {
   1357            return;
   1358        }
   1359        let mut steps = 0;
   1360        while new_scale * upscaled <= 0.5 {
   1361            new_scale *= 2.0;
   1362            steps += 1;
   1363        }
   1364        // If no mipping is necessary, just bail.
   1365        if steps == 0 {
   1366            return;
   1367        }
   1368 
   1369        // Calculate the actual size of the mip level.
   1370        let new_width = (self.width as usize + (1 << steps) - 1) >> steps;
   1371        let new_height = (self.height as usize + (1 << steps) - 1) >> steps;
   1372        let mut new_bytes: Vec<u8> = Vec::with_capacity(new_width * new_height * 4);
   1373 
   1374        // Produce destination pixels by applying a box filter to the source pixels.
   1375        // The box filter corresponds to how graphics drivers may generate mipmaps.
   1376        for y in 0 .. new_height {
   1377            for x in 0 .. new_width {
   1378                // Calculate the number of source samples that contribute to the destination pixel.
   1379                let src_y = y << steps;
   1380                let src_x = x << steps;
   1381                let y_samples = (1 << steps).min(self.height as usize - src_y);
   1382                let x_samples = (1 << steps).min(self.width as usize - src_x);
   1383                let num_samples = (x_samples * y_samples) as u32;
   1384 
   1385                let mut src_idx = (src_y * self.width as usize + src_x) * 4;
   1386                // Initialize the accumulator with half an increment so that when later divided
   1387                // by the sample count, it will effectively round the accumulator to the nearest
   1388                // increment.
   1389                let mut accum = [num_samples / 2; 4];
   1390                // Accumulate all the contributing source sampless.
   1391                for _ in 0 .. y_samples {
   1392                    for _ in 0 .. x_samples {
   1393                        accum[0] += self.bytes[src_idx + 0] as u32;
   1394                        accum[1] += self.bytes[src_idx + 1] as u32;
   1395                        accum[2] += self.bytes[src_idx + 2] as u32;
   1396                        accum[3] += self.bytes[src_idx + 3] as u32;
   1397                        src_idx += 4;
   1398                    }
   1399                    src_idx += (self.width as usize - x_samples) * 4;
   1400                }
   1401 
   1402                // Finally, divide by the sample count to get the mean value for the new pixel.
   1403                new_bytes.extend_from_slice(&[
   1404                    (accum[0] / num_samples) as u8,
   1405                    (accum[1] / num_samples) as u8,
   1406                    (accum[2] / num_samples) as u8,
   1407                    (accum[3] / num_samples) as u8,
   1408                ]);
   1409            }
   1410        }
   1411 
   1412        // Fix the bounds for the new glyph data.
   1413        self.top /= (1 << steps) as f32;
   1414        self.left /= (1 << steps) as f32;
   1415        self.width = new_width as i32;
   1416        self.height = new_height as i32;
   1417        self.scale = new_scale;
   1418        self.bytes = new_bytes;
   1419    }
   1420 }
   1421 
   1422 pub struct FontContexts {
   1423    // These worker are mostly accessed from their corresponding worker threads.
   1424    // The goal is that there should be no noticeable contention on the mutexes.
   1425    worker_contexts: Vec<Mutex<FontContext>>,
   1426    // Stored here as a convenience to get the current thread index.
   1427    #[allow(dead_code)]
   1428    workers: Arc<ThreadPool>,
   1429    locked_mutex: Mutex<bool>,
   1430    locked_cond: Condvar,
   1431 }
   1432 
   1433 impl FontContexts {
   1434    /// Get access to any particular font context.
   1435    ///
   1436    /// The id is an index between 0 and num_worker_contexts for font contexts
   1437    /// associated to the thread pool.
   1438    pub fn lock_context(&self, id: usize) -> MutexGuard<FontContext> {
   1439        self.worker_contexts[id].lock().unwrap()
   1440    }
   1441 
   1442    // Find a context that is currently unlocked to use, otherwise defaulting
   1443    // to the first context.
   1444    pub fn lock_any_context(&self) -> MutexGuard<FontContext> {
   1445        for context in &self.worker_contexts {
   1446            if let Ok(mutex) = context.try_lock() {
   1447                return mutex;
   1448            }
   1449        }
   1450        self.lock_context(0)
   1451    }
   1452 
   1453    // number of contexts associated to workers
   1454    pub fn num_worker_contexts(&self) -> usize {
   1455        self.worker_contexts.len()
   1456    }
   1457 }
   1458 
   1459 pub trait AsyncForEach<T> {
   1460    fn async_for_each<F: Fn(MutexGuard<T>) + Send + 'static>(&self, f: F);
   1461 }
   1462 
   1463 impl AsyncForEach<FontContext> for Arc<FontContexts> {
   1464    fn async_for_each<F: Fn(MutexGuard<FontContext>) + Send + 'static>(&self, f: F) {
   1465        // Reset the locked condition.
   1466        let mut locked = self.locked_mutex.lock().unwrap();
   1467        *locked = false;
   1468 
   1469        // Arc that can be safely moved into a spawn closure.
   1470        let font_contexts = self.clone();
   1471        // Spawn a new thread on which to run the for-each off the main thread.
   1472        self.workers.spawn(move || {
   1473            // Lock the shared and worker contexts up front.
   1474            let mut locks = Vec::with_capacity(font_contexts.num_worker_contexts());
   1475            for i in 0 .. font_contexts.num_worker_contexts() {
   1476                locks.push(font_contexts.lock_context(i));
   1477            }
   1478 
   1479            // Signal the locked condition now that all contexts are locked.
   1480            *font_contexts.locked_mutex.lock().unwrap() = true;
   1481            font_contexts.locked_cond.notify_all();
   1482 
   1483            // Now that everything is locked, proceed to processing each locked context.
   1484            for context in locks {
   1485                f(context);
   1486            }
   1487        });
   1488 
   1489        // Wait for locked condition before resuming. Safe to proceed thereafter
   1490        // since any other thread that needs to use a FontContext will try to lock
   1491        // it first.
   1492        while !*locked {
   1493            locked = self.locked_cond.wait(locked).unwrap();
   1494        }
   1495    }
   1496 }
   1497 
   1498 pub struct GlyphRasterizer {
   1499    #[allow(dead_code)]
   1500    workers: Arc<ThreadPool>,
   1501    font_contexts: Arc<FontContexts>,
   1502    dedicated_thread: Option<GlyphRasterThread>,
   1503 
   1504    /// The current set of loaded fonts.
   1505    fonts: FastHashSet<FontKey>,
   1506 
   1507    /// The current number of individual glyphs waiting in pending batches.
   1508    pending_glyph_count: usize,
   1509 
   1510    /// The current number of glyph request jobs that have been kicked to worker threads.
   1511    pending_glyph_jobs: usize,
   1512 
   1513    /// The number of glyphs requested this frame.
   1514    glyph_request_count: usize,
   1515 
   1516    /// A map of current glyph request batches.
   1517    pending_glyph_requests: FastHashMap<FontInstance, SmallVec<[GlyphKey; 16]>>,
   1518 
   1519    // Receives the rendered glyphs.
   1520    glyph_rx: Receiver<GlyphRasterJob>,
   1521    glyph_tx: Sender<GlyphRasterJob>,
   1522 
   1523    // We defer removing fonts to the end of the frame so that:
   1524    // - this work is done outside of the critical path,
   1525    // - we don't have to worry about the ordering of events if a font is used on
   1526    //   a frame where it is used (although it seems unlikely).
   1527    fonts_to_remove: Vec<FontKey>,
   1528    // Defer removal of font instances, as for fonts.
   1529    font_instances_to_remove: Vec<FontInstance>,
   1530 
   1531    // Whether to parallelize glyph rasterization with rayon.
   1532    enable_multithreading: bool,
   1533 
   1534    // Whether glyphs can be rasterized in r8 format when it makes sense.
   1535    can_use_r8_format: bool,
   1536 }
   1537 
   1538 impl GlyphRasterizer {
   1539    pub fn new(workers: Arc<ThreadPool>, dedicated_thread: Option<GlyphRasterThread>, can_use_r8_format: bool) -> Self {
   1540        let (glyph_tx, glyph_rx) = unbounded();
   1541 
   1542        let num_workers = workers.current_num_threads();
   1543        let mut contexts = Vec::with_capacity(num_workers);
   1544 
   1545        for _ in 0 .. num_workers {
   1546            contexts.push(Mutex::new(FontContext::new()));
   1547        }
   1548 
   1549        let font_context = FontContexts {
   1550            worker_contexts: contexts,
   1551            workers: Arc::clone(&workers),
   1552            locked_mutex: Mutex::new(false),
   1553            locked_cond: Condvar::new(),
   1554        };
   1555 
   1556        GlyphRasterizer {
   1557            font_contexts: Arc::new(font_context),
   1558            fonts: FastHashSet::default(),
   1559            dedicated_thread,
   1560            pending_glyph_jobs: 0,
   1561            pending_glyph_count: 0,
   1562            glyph_request_count: 0,
   1563            glyph_rx,
   1564            glyph_tx,
   1565            workers,
   1566            fonts_to_remove: Vec::new(),
   1567            font_instances_to_remove: Vec::new(),
   1568            enable_multithreading: true,
   1569            pending_glyph_requests: FastHashMap::default(),
   1570            can_use_r8_format,
   1571        }
   1572    }
   1573 
   1574    pub fn add_font(&mut self, font_key: FontKey, template: FontTemplate) {
   1575        // Only add font to FontContexts if not previously added.
   1576        if self.fonts.insert(font_key.clone()) {
   1577            if let Some(thread) = &self.dedicated_thread {
   1578                let _ = thread.tx.send(GlyphRasterMsg::AddFont { font_key, template });
   1579            } else {
   1580                self.font_contexts.async_for_each(move |mut context| {
   1581                    context.add_font(&font_key, &template);
   1582                });
   1583            }
   1584        }
   1585    }
   1586 
   1587    pub fn delete_font(&mut self, font_key: FontKey) {
   1588        self.fonts_to_remove.push(font_key);
   1589    }
   1590 
   1591    pub fn delete_fonts(&mut self, font_keys: &[FontKey]) {
   1592        self.fonts_to_remove.extend_from_slice(font_keys);
   1593    }
   1594 
   1595    pub fn delete_font_instance(&mut self, instance: &FontInstance) {
   1596        self.font_instances_to_remove.push(instance.clone());
   1597    }
   1598 
   1599    pub fn prepare_font(&self, font: &mut FontInstance) {
   1600        FontContext::prepare_font(font);
   1601 
   1602        // Quantize the transform to minimize thrashing of the glyph cache, but
   1603        // only quantize the transform when preparing to access the glyph cache.
   1604        // This way, the glyph subpixel positions, which are calculated before
   1605        // this, can still use the precise transform which is required to match
   1606        // the subpixel positions computed for glyphs in the text run shader.
   1607        font.transform = font.transform.quantize();
   1608    }
   1609 
   1610    pub fn has_font(&self, font_key: FontKey) -> bool {
   1611        self.fonts.contains(&font_key)
   1612    }
   1613 
   1614    pub fn get_glyph_dimensions(
   1615        &mut self,
   1616        font: &FontInstance,
   1617        glyph_index: GlyphIndex,
   1618    ) -> Option<GlyphDimensions> {
   1619        let glyph_key = GlyphKey::new(
   1620            glyph_index,
   1621            DevicePoint::zero(),
   1622            SubpixelDirection::None,
   1623        );
   1624 
   1625        self.font_contexts
   1626            .lock_any_context()
   1627            .get_glyph_dimensions(font, &glyph_key)
   1628    }
   1629 
   1630    pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
   1631        self.font_contexts
   1632            .lock_any_context()
   1633            .get_glyph_index(font_key, ch)
   1634    }
   1635 
   1636    fn remove_dead_fonts(&mut self) {
   1637        if self.fonts_to_remove.is_empty() && self.font_instances_to_remove.is_empty() {
   1638            return
   1639        }
   1640 
   1641        profile_scope!("remove_dead_fonts");
   1642        let mut fonts_to_remove = mem::replace(& mut self.fonts_to_remove, Vec::new());
   1643        // Only remove font from FontContexts if previously added.
   1644        fonts_to_remove.retain(|font| self.fonts.remove(font));
   1645        let font_instances_to_remove = mem::replace(& mut self.font_instances_to_remove, Vec::new());
   1646        if let Some(thread) = &self.dedicated_thread {
   1647            for font_key in fonts_to_remove {
   1648                let _ = thread.tx.send(GlyphRasterMsg::DeleteFont { font_key });
   1649            }
   1650            for instance in font_instances_to_remove {
   1651                let _ = thread.tx.send(GlyphRasterMsg::DeleteFontInstance { instance });
   1652            }
   1653        } else {
   1654            self.font_contexts.async_for_each(move |mut context| {
   1655                for font_key in &fonts_to_remove {
   1656                    context.delete_font(font_key);
   1657                }
   1658                for instance in &font_instances_to_remove {
   1659                    context.delete_font_instance(instance);
   1660                }
   1661            });
   1662        }
   1663    }
   1664 
   1665    #[cfg(feature = "replay")]
   1666    pub fn reset(&mut self) {
   1667        //TODO: any signals need to be sent to the workers?
   1668        self.pending_glyph_jobs = 0;
   1669        self.pending_glyph_count = 0;
   1670        self.glyph_request_count = 0;
   1671        self.fonts_to_remove.clear();
   1672        self.font_instances_to_remove.clear();
   1673    }
   1674 }
   1675 
   1676 trait AddFont {
   1677    fn add_font(&mut self, font_key: &FontKey, template: &FontTemplate);
   1678 }
   1679 
   1680 impl AddFont for FontContext {
   1681    fn add_font(&mut self, font_key: &FontKey, template: &FontTemplate) {
   1682        match *template {
   1683            FontTemplate::Raw(ref bytes, index) => {
   1684                self.add_raw_font(font_key, bytes.clone(), index);
   1685            }
   1686            FontTemplate::Native(ref native_font_handle) => {
   1687                self.add_native_font(font_key, (*native_font_handle).clone());
   1688            }
   1689        }
   1690    }
   1691 }
   1692 
   1693 #[allow(dead_code)]
   1694 pub struct GlyphRasterJob {
   1695    pub font: Arc<FontInstance>,
   1696    pub key: GlyphKey,
   1697    pub result: GlyphRasterResult,
   1698 }
   1699 
   1700 #[allow(dead_code)]
   1701 #[derive(Debug)]
   1702 pub enum GlyphRasterError {
   1703    LoadFailed,
   1704 }
   1705 
   1706 #[allow(dead_code)]
   1707 pub type GlyphRasterResult = Result<RasterizedGlyph, GlyphRasterError>;
   1708 
   1709 #[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
   1710 #[cfg_attr(feature = "capture", derive(Serialize))]
   1711 #[cfg_attr(feature = "replay", derive(Deserialize))]
   1712 pub struct GpuGlyphCacheKey(pub u32);
   1713 
   1714 fn pack_glyph_variants_horizontal(variants: &[RasterizedGlyph]) -> RasterizedGlyph {
   1715    // Pack 4 glyph variants horizontally into a single texture.
   1716    // Normalize both left and top offsets via padding so all variants can use the same base offsets.
   1717 
   1718    let min_left = variants.iter().map(|v| v.left.floor()).fold(f32::INFINITY, f32::min);
   1719    let max_top = variants.iter().map(|v| v.top.floor()).fold(f32::NEG_INFINITY, f32::max);
   1720 
   1721    // Slot width must accommodate the widest variant plus left padding
   1722    let slot_width = variants.iter()
   1723        .map(|v| v.width + (v.left.floor() - min_left) as i32)
   1724        .max().unwrap();
   1725 
   1726    // Slot height must accommodate the tallest variant plus top padding
   1727    let slot_height = variants.iter()
   1728        .map(|v| v.height + (max_top - v.top.floor()) as i32)
   1729        .max().unwrap();
   1730 
   1731    let packed_width = slot_width * 4;
   1732    let bpp = 4;
   1733 
   1734    let mut packed_bytes = vec![0u8; (packed_width * slot_height * bpp) as usize];
   1735 
   1736    for (variant_idx, variant) in variants.iter().enumerate() {
   1737        // Compute padding needed to normalize both left and top offsets
   1738        let left_pad = (variant.left.floor() - min_left) as i32;
   1739        let top_pad = (max_top - variant.top.floor()) as i32;
   1740        let slot_x = variant_idx as i32 * slot_width;
   1741 
   1742        for src_y in 0..variant.height {
   1743            let dst_y = src_y + top_pad;
   1744            if dst_y >= slot_height {
   1745                break;
   1746            }
   1747 
   1748            let dst_x = slot_x + left_pad;
   1749            if dst_x < 0 {
   1750                continue;
   1751            }
   1752 
   1753            let src_row_start = (src_y * variant.width * bpp) as usize;
   1754            let src_row_end = src_row_start + (variant.width * bpp) as usize;
   1755            let dst_row_start = (dst_y * packed_width * bpp + dst_x * bpp) as usize;
   1756            let dst_row_end = dst_row_start + (variant.width * bpp) as usize;
   1757 
   1758            if dst_row_end <= packed_bytes.len() && src_row_end <= variant.bytes.len() {
   1759                packed_bytes[dst_row_start..dst_row_end]
   1760                    .copy_from_slice(&variant.bytes[src_row_start..src_row_end]);
   1761            }
   1762        }
   1763    }
   1764 
   1765    RasterizedGlyph {
   1766        top: max_top,
   1767        left: min_left,
   1768        width: packed_width,
   1769        height: slot_height,
   1770        scale: variants[0].scale,
   1771        format: variants[0].format,
   1772        bytes: packed_bytes,
   1773        is_packed_glyph: true,
   1774    }
   1775 }
   1776 
   1777 fn process_glyph(
   1778    context: &mut FontContext,
   1779    can_use_r8_format: bool,
   1780    font: Arc<FontInstance>,
   1781    key: GlyphKey,
   1782 ) -> GlyphRasterJob {
   1783    profile_scope!("glyph-raster");
   1784 
   1785    let subpx_dir = key.subpixel_dir();
   1786 
   1787    let result = if subpx_dir == SubpixelDirection::None {
   1788        context.rasterize_glyph(&font, &key)
   1789    } else {
   1790        let offsets = [
   1791            SubpixelOffset::Zero,
   1792            SubpixelOffset::Quarter,
   1793            SubpixelOffset::Half,
   1794            SubpixelOffset::ThreeQuarters,
   1795        ];
   1796 
   1797        let mut variants = Vec::with_capacity(4);
   1798        for offset in &offsets {
   1799            let variant_key = GlyphKey::new(
   1800                key.index(),
   1801                match subpx_dir {
   1802                    SubpixelDirection::Horizontal => DevicePoint::new(offset.to_f32(), 0.0),
   1803                    SubpixelDirection::Vertical => DevicePoint::new(0.0, offset.to_f32()),
   1804                    SubpixelDirection::None => DevicePoint::zero(),
   1805                },
   1806                subpx_dir,
   1807            );
   1808 
   1809            match context.rasterize_glyph(&font, &variant_key) {
   1810                Ok(glyph) => variants.push(glyph),
   1811                Err(e) => return GlyphRasterJob {
   1812                    font: font,
   1813                    key: key.clone(),
   1814                    result: Err(e),
   1815                },
   1816            }
   1817        }
   1818 
   1819        Ok(pack_glyph_variants_horizontal(&variants))
   1820    };
   1821 
   1822    let mut job = GlyphRasterJob {
   1823        font: font,
   1824        key: key.clone(),
   1825        result,
   1826    };
   1827 
   1828    if let Ok(ref mut glyph) = job.result {
   1829        // Sanity check.
   1830        let bpp = 4; // We always render glyphs in 32 bits RGBA format.
   1831        assert_eq!(
   1832            glyph.bytes.len(),
   1833            bpp * (glyph.width * glyph.height) as usize
   1834        );
   1835 
   1836        // a quick-and-dirty monochrome over
   1837        fn over(dst: u8, src: u8) -> u8 {
   1838            let a = src as u32;
   1839            let a = 256 - a;
   1840            let dst = ((dst as u32 * a) >> 8) as u8;
   1841            src + dst
   1842        }
   1843 
   1844        if GLYPH_FLASHING.load(Ordering::Relaxed) {
   1845            let color = (random() & 0xff) as u8;
   1846            for i in &mut glyph.bytes {
   1847                *i = over(*i, color);
   1848            }
   1849        }
   1850 
   1851        assert_eq!((glyph.left.fract(), glyph.top.fract()), (0.0, 0.0));
   1852 
   1853        // Check if the glyph has a bitmap that needs to be downscaled.
   1854        glyph.downscale_bitmap_if_required(&job.font);
   1855 
   1856        // Convert from BGRA8 to R8 if required. In the future we can make it the
   1857        // backends' responsibility to output glyphs in the desired format,
   1858        // potentially reducing the number of copies.
   1859        if glyph.format.image_format(can_use_r8_format).bytes_per_pixel() == 1 {
   1860            glyph.bytes = glyph.bytes
   1861                .chunks_mut(4)
   1862                .map(|pixel| pixel[3])
   1863                .collect::<Vec<_>>();
   1864        }
   1865    }
   1866 
   1867    job
   1868 }
   1869 
   1870 
   1871 pub enum GlyphRasterMsg {
   1872    Rasterize {
   1873        font: Arc<FontInstance>,
   1874        glyphs: SmallVec<[GlyphKey; 16]>,
   1875        can_use_r8_format: bool,
   1876        tx: Sender<GlyphRasterJob>,
   1877    },
   1878    AddFont { font_key: FontKey, template: FontTemplate },
   1879    DeleteFont { font_key: FontKey },
   1880    DeleteFontInstance { instance: FontInstance },
   1881    ShutDown,
   1882 }
   1883 
   1884 #[derive(Clone)]
   1885 pub struct GlyphRasterThread {
   1886    tx: Sender<GlyphRasterMsg>,
   1887 }
   1888 
   1889 impl GlyphRasterThread {
   1890    pub fn new(
   1891        on_start: impl FnOnce() + Send + 'static,
   1892        on_end: impl FnOnce() + Send+ 'static,
   1893    ) -> std::io::Result<Self> {
   1894        let (tx, rx) = unbounded();
   1895 
   1896        std::thread::Builder::new().name("Glyph rasterizer".to_string()).spawn(move || {
   1897            on_start();
   1898 
   1899            let mut context = FontContext::new();
   1900 
   1901            loop {
   1902                match rx.recv() {
   1903                    Ok(GlyphRasterMsg::Rasterize { font, glyphs, can_use_r8_format, tx }) => {
   1904                        for glyph in &glyphs {
   1905                            let job = process_glyph(&mut context, can_use_r8_format, font.clone(), *glyph);
   1906                            let _ = tx.send(job);
   1907                        }
   1908                    }
   1909                    Ok(GlyphRasterMsg::AddFont { font_key, template }) => {
   1910                        context.add_font(&font_key, &template)
   1911                    }
   1912                    Ok(GlyphRasterMsg::DeleteFont { font_key }) => {
   1913                        context.delete_font(&font_key)
   1914                    }
   1915                    Ok(GlyphRasterMsg::DeleteFontInstance { instance }) => {
   1916                        context.delete_font_instance(&instance)
   1917                    }
   1918                    Ok(GlyphRasterMsg::ShutDown) => {
   1919                        break;
   1920                    }
   1921                    Err(..) => {
   1922                        break;
   1923                    }
   1924                }
   1925            }
   1926 
   1927            on_end();
   1928        })?;
   1929 
   1930        Ok(GlyphRasterThread {
   1931            tx,
   1932        })
   1933    }
   1934 
   1935    pub fn shut_down(&self) {
   1936        let _ = self.tx.send(GlyphRasterMsg::ShutDown);
   1937    }
   1938 }
   1939 
   1940 #[cfg(test)]
   1941 mod test_glyph_rasterizer {
   1942    use crate::profiler::GlyphRasterizeProfiler;
   1943 
   1944    struct Profiler;
   1945    impl GlyphRasterizeProfiler for Profiler {
   1946        fn start_time(&mut self) {}
   1947        fn end_time(&mut self) -> f64 {
   1948            0.
   1949        }
   1950        fn set(&mut self, _value: f64) {}
   1951    }
   1952 
   1953    #[test]
   1954    fn rasterize_200_glyphs() {
   1955        // This test loads a font from disc, the renders 4 requests containing
   1956        // 50 glyphs each, deletes the font and waits for the result.
   1957 
   1958        use rayon::ThreadPoolBuilder;
   1959        use std::fs::File;
   1960        use std::io::Read;
   1961        use api::{FontKey, FontInstanceKey, FontTemplate, IdNamespace};
   1962        use api::units::DevicePoint;
   1963        use std::sync::Arc;
   1964        use crate::rasterizer::{FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
   1965 
   1966        let worker = ThreadPoolBuilder::new()
   1967            .thread_name(|idx|{ format!("WRWorker#{}", idx) })
   1968            .build();
   1969        let workers = Arc::new(worker.unwrap());
   1970        let mut glyph_rasterizer = GlyphRasterizer::new(workers, None, true);
   1971        let mut font_file =
   1972            File::open("../wrench/reftests/text/VeraBd.ttf").expect("Couldn't open font file");
   1973        let mut font_data = vec![];
   1974        font_file
   1975            .read_to_end(&mut font_data)
   1976            .expect("failed to read font file");
   1977 
   1978        let font_key = FontKey::new(IdNamespace(0), 0);
   1979        glyph_rasterizer.add_font(font_key, FontTemplate::Raw(Arc::new(font_data), 0));
   1980 
   1981        let font = FontInstance::from_base(Arc::new(BaseFontInstance::new(
   1982            FontInstanceKey::new(IdNamespace(0), 0),
   1983            font_key,
   1984            32.0,
   1985            None,
   1986            None,
   1987            Vec::new(),
   1988        )));
   1989 
   1990        let subpx_dir = font.get_subpx_dir();
   1991 
   1992        let mut glyph_keys = Vec::with_capacity(200);
   1993        for i in 0 .. 200 {
   1994            glyph_keys.push(GlyphKey::new(
   1995                i,
   1996                DevicePoint::zero(),
   1997                subpx_dir,
   1998            ));
   1999        }
   2000 
   2001        for i in 0 .. 4 {
   2002            glyph_rasterizer.request_glyphs(
   2003                font.clone(),
   2004                &glyph_keys[(50 * i) .. (50 * (i + 1))],
   2005                |_| true,
   2006            );
   2007        }
   2008 
   2009        glyph_rasterizer.delete_font(font_key);
   2010 
   2011        glyph_rasterizer.resolve_glyphs(
   2012            |_, _| {},
   2013            &mut Profiler,
   2014        );
   2015    }
   2016 
   2017    #[test]
   2018    fn rasterize_large_glyphs() {
   2019        // This test loads a font from disc and rasterize a few glyphs with a size of 200px to check
   2020        // that the texture cache handles them properly.
   2021        use rayon::ThreadPoolBuilder;
   2022        use std::fs::File;
   2023        use std::io::Read;
   2024        use api::{FontKey, FontInstanceKey, FontTemplate, IdNamespace};
   2025        use api::units::DevicePoint;
   2026        use std::sync::Arc;
   2027        use crate::rasterizer::{FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
   2028 
   2029        let worker = ThreadPoolBuilder::new()
   2030            .thread_name(|idx|{ format!("WRWorker#{}", idx) })
   2031            .build();
   2032        let workers = Arc::new(worker.unwrap());
   2033        let mut glyph_rasterizer = GlyphRasterizer::new(workers, None, true);
   2034        let mut font_file =
   2035            File::open("../wrench/reftests/text/VeraBd.ttf").expect("Couldn't open font file");
   2036        let mut font_data = vec![];
   2037        font_file
   2038            .read_to_end(&mut font_data)
   2039            .expect("failed to read font file");
   2040 
   2041        let font_key = FontKey::new(IdNamespace(0), 0);
   2042        glyph_rasterizer.add_font(font_key, FontTemplate::Raw(Arc::new(font_data), 0));
   2043 
   2044        let font = FontInstance::from_base(Arc::new(BaseFontInstance::new(
   2045            FontInstanceKey::new(IdNamespace(0), 0),
   2046            font_key,
   2047            200.0,
   2048            None,
   2049            None,
   2050            Vec::new(),
   2051        )));
   2052 
   2053        let subpx_dir = font.get_subpx_dir();
   2054 
   2055        let mut glyph_keys = Vec::with_capacity(10);
   2056        for i in 0 .. 10 {
   2057            glyph_keys.push(GlyphKey::new(
   2058                i,
   2059                DevicePoint::zero(),
   2060                subpx_dir,
   2061            ));
   2062        }
   2063 
   2064        glyph_rasterizer.request_glyphs(
   2065            font.clone(),
   2066            &glyph_keys,
   2067            |_| true,
   2068        );
   2069 
   2070        glyph_rasterizer.delete_font(font_key);
   2071 
   2072        glyph_rasterizer.resolve_glyphs(
   2073            |_, _| {},
   2074            &mut Profiler,
   2075        );
   2076    }
   2077 
   2078    #[test]
   2079    fn test_subpx_quantize() {
   2080        use crate::rasterizer::SubpixelOffset;
   2081 
   2082        assert_eq!(SubpixelOffset::quantize(0.0), SubpixelOffset::Zero);
   2083        assert_eq!(SubpixelOffset::quantize(-0.0), SubpixelOffset::Zero);
   2084 
   2085        assert_eq!(SubpixelOffset::quantize(0.1), SubpixelOffset::Zero);
   2086        assert_eq!(SubpixelOffset::quantize(0.01), SubpixelOffset::Zero);
   2087        assert_eq!(SubpixelOffset::quantize(0.05), SubpixelOffset::Zero);
   2088        assert_eq!(SubpixelOffset::quantize(0.12), SubpixelOffset::Zero);
   2089        assert_eq!(SubpixelOffset::quantize(0.124), SubpixelOffset::Zero);
   2090 
   2091        assert_eq!(SubpixelOffset::quantize(0.125), SubpixelOffset::Quarter);
   2092        assert_eq!(SubpixelOffset::quantize(0.2), SubpixelOffset::Quarter);
   2093        assert_eq!(SubpixelOffset::quantize(0.25), SubpixelOffset::Quarter);
   2094        assert_eq!(SubpixelOffset::quantize(0.33), SubpixelOffset::Quarter);
   2095        assert_eq!(SubpixelOffset::quantize(0.374), SubpixelOffset::Quarter);
   2096 
   2097        assert_eq!(SubpixelOffset::quantize(0.375), SubpixelOffset::Half);
   2098        assert_eq!(SubpixelOffset::quantize(0.4), SubpixelOffset::Half);
   2099        assert_eq!(SubpixelOffset::quantize(0.5), SubpixelOffset::Half);
   2100        assert_eq!(SubpixelOffset::quantize(0.58), SubpixelOffset::Half);
   2101        assert_eq!(SubpixelOffset::quantize(0.624), SubpixelOffset::Half);
   2102 
   2103        assert_eq!(SubpixelOffset::quantize(0.625), SubpixelOffset::ThreeQuarters);
   2104        assert_eq!(SubpixelOffset::quantize(0.67), SubpixelOffset::ThreeQuarters);
   2105        assert_eq!(SubpixelOffset::quantize(0.7), SubpixelOffset::ThreeQuarters);
   2106        assert_eq!(SubpixelOffset::quantize(0.78), SubpixelOffset::ThreeQuarters);
   2107        assert_eq!(SubpixelOffset::quantize(0.874), SubpixelOffset::ThreeQuarters);
   2108 
   2109        assert_eq!(SubpixelOffset::quantize(0.875), SubpixelOffset::Zero);
   2110        assert_eq!(SubpixelOffset::quantize(0.89), SubpixelOffset::Zero);
   2111        assert_eq!(SubpixelOffset::quantize(0.91), SubpixelOffset::Zero);
   2112        assert_eq!(SubpixelOffset::quantize(0.967), SubpixelOffset::Zero);
   2113        assert_eq!(SubpixelOffset::quantize(0.999), SubpixelOffset::Zero);
   2114 
   2115        assert_eq!(SubpixelOffset::quantize(-1.0), SubpixelOffset::Zero);
   2116        assert_eq!(SubpixelOffset::quantize(1.0), SubpixelOffset::Zero);
   2117        assert_eq!(SubpixelOffset::quantize(1.5), SubpixelOffset::Half);
   2118        assert_eq!(SubpixelOffset::quantize(-1.625), SubpixelOffset::Half);
   2119        assert_eq!(SubpixelOffset::quantize(-4.33), SubpixelOffset::ThreeQuarters);
   2120    }
   2121 }