direct_write.rs

   1use std::{
   2    borrow::Cow,
   3    ffi::{c_uint, c_void},
   4    mem::ManuallyDrop,
   5};
   6
   7use ::util::{ResultExt, maybe};
   8use anyhow::{Context, Result};
   9use collections::HashMap;
  10use parking_lot::{RwLock, RwLockUpgradableReadGuard};
  11use windows::{
  12    Win32::{
  13        Foundation::*,
  14        Globalization::GetUserDefaultLocaleName,
  15        Graphics::{
  16            Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, Direct3D11::*, DirectWrite::*,
  17            Dxgi::Common::*, Gdi::LOGFONTW,
  18        },
  19        System::SystemServices::LOCALE_NAME_MAX_LENGTH,
  20        UI::WindowsAndMessaging::*,
  21    },
  22    core::*,
  23};
  24use windows_numerics::Vector2;
  25
  26use crate::*;
  27use gpui::*;
  28
  29#[derive(Debug)]
  30struct FontInfo {
  31    font_family_h: HSTRING,
  32    font_face: IDWriteFontFace3,
  33    features: IDWriteTypography,
  34    fallbacks: Option<IDWriteFontFallback>,
  35    font_collection: IDWriteFontCollection1,
  36}
  37
  38pub(crate) struct DirectWriteTextSystem {
  39    components: DirectWriteComponents,
  40    state: RwLock<DirectWriteState>,
  41}
  42
  43struct DirectWriteComponents {
  44    locale: HSTRING,
  45    factory: IDWriteFactory5,
  46    in_memory_loader: IDWriteInMemoryFontFileLoader,
  47    builder: IDWriteFontSetBuilder1,
  48    text_renderer: TextRendererWrapper,
  49    system_ui_font_name: SharedString,
  50    system_subpixel_rendering: bool,
  51}
  52
  53impl Drop for DirectWriteComponents {
  54    fn drop(&mut self) {
  55        unsafe {
  56            let _ = self
  57                .factory
  58                .UnregisterFontFileLoader(&self.in_memory_loader);
  59        }
  60    }
  61}
  62
  63struct GPUState {
  64    device: ID3D11Device,
  65    device_context: ID3D11DeviceContext,
  66    sampler: Option<ID3D11SamplerState>,
  67    blend_state: ID3D11BlendState,
  68    vertex_shader: ID3D11VertexShader,
  69    pixel_shader: ID3D11PixelShader,
  70}
  71
  72struct DirectWriteState {
  73    gpu_state: GPUState,
  74    system_font_collection: IDWriteFontCollection1,
  75    custom_font_collection: IDWriteFontCollection1,
  76    fonts: Vec<FontInfo>,
  77    font_to_font_id: HashMap<Font, FontId>,
  78    font_info_cache: HashMap<usize, FontId>,
  79    layout_line_scratch: Vec<u16>,
  80}
  81
  82impl GPUState {
  83    fn new(directx_devices: &DirectXDevices) -> Result<Self> {
  84        let device = directx_devices.device.clone();
  85        let device_context = directx_devices.device_context.clone();
  86
  87        let blend_state = {
  88            let mut blend_state = None;
  89            let desc = D3D11_BLEND_DESC {
  90                AlphaToCoverageEnable: false.into(),
  91                IndependentBlendEnable: false.into(),
  92                RenderTarget: [
  93                    D3D11_RENDER_TARGET_BLEND_DESC {
  94                        BlendEnable: true.into(),
  95                        SrcBlend: D3D11_BLEND_ONE,
  96                        DestBlend: D3D11_BLEND_INV_SRC_ALPHA,
  97                        BlendOp: D3D11_BLEND_OP_ADD,
  98                        SrcBlendAlpha: D3D11_BLEND_ONE,
  99                        DestBlendAlpha: D3D11_BLEND_INV_SRC_ALPHA,
 100                        BlendOpAlpha: D3D11_BLEND_OP_ADD,
 101                        RenderTargetWriteMask: D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8,
 102                    },
 103                    Default::default(),
 104                    Default::default(),
 105                    Default::default(),
 106                    Default::default(),
 107                    Default::default(),
 108                    Default::default(),
 109                    Default::default(),
 110                ],
 111            };
 112            unsafe { device.CreateBlendState(&desc, Some(&mut blend_state)) }?;
 113            blend_state.unwrap()
 114        };
 115
 116        let sampler = {
 117            let mut sampler = None;
 118            let desc = D3D11_SAMPLER_DESC {
 119                Filter: D3D11_FILTER_MIN_MAG_MIP_POINT,
 120                AddressU: D3D11_TEXTURE_ADDRESS_BORDER,
 121                AddressV: D3D11_TEXTURE_ADDRESS_BORDER,
 122                AddressW: D3D11_TEXTURE_ADDRESS_BORDER,
 123                MipLODBias: 0.0,
 124                MaxAnisotropy: 1,
 125                ComparisonFunc: D3D11_COMPARISON_ALWAYS,
 126                BorderColor: [0.0, 0.0, 0.0, 0.0],
 127                MinLOD: 0.0,
 128                MaxLOD: 0.0,
 129            };
 130            unsafe { device.CreateSamplerState(&desc, Some(&mut sampler)) }?;
 131            sampler
 132        };
 133
 134        let vertex_shader = {
 135            let source = shader_resources::RawShaderBytes::new(
 136                shader_resources::ShaderModule::EmojiRasterization,
 137                shader_resources::ShaderTarget::Vertex,
 138            )?;
 139            let mut shader = None;
 140            unsafe { device.CreateVertexShader(source.as_bytes(), None, Some(&mut shader)) }?;
 141            shader.unwrap()
 142        };
 143
 144        let pixel_shader = {
 145            let source = shader_resources::RawShaderBytes::new(
 146                shader_resources::ShaderModule::EmojiRasterization,
 147                shader_resources::ShaderTarget::Fragment,
 148            )?;
 149            let mut shader = None;
 150            unsafe { device.CreatePixelShader(source.as_bytes(), None, Some(&mut shader)) }?;
 151            shader.unwrap()
 152        };
 153
 154        Ok(Self {
 155            device,
 156            device_context,
 157            sampler,
 158            blend_state,
 159            vertex_shader,
 160            pixel_shader,
 161        })
 162    }
 163}
 164
 165impl DirectWriteTextSystem {
 166    pub(crate) fn new(directx_devices: &DirectXDevices) -> Result<Self> {
 167        let factory: IDWriteFactory5 = unsafe { DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED)? };
 168        // The `IDWriteInMemoryFontFileLoader` here is supported starting from
 169        // Windows 10 Creators Update, which consequently requires the entire
 170        // `DirectWriteTextSystem` to run on `win10 1703`+.
 171        let in_memory_loader = unsafe { factory.CreateInMemoryFontFileLoader()? };
 172        unsafe { factory.RegisterFontFileLoader(&in_memory_loader)? };
 173        let builder = unsafe { factory.CreateFontSetBuilder()? };
 174        let mut locale = [0u16; LOCALE_NAME_MAX_LENGTH as usize];
 175        unsafe { GetUserDefaultLocaleName(&mut locale) };
 176        let locale = HSTRING::from_wide(&locale);
 177        let text_renderer = TextRendererWrapper::new(locale.clone());
 178
 179        let gpu_state = GPUState::new(directx_devices)?;
 180
 181        let system_subpixel_rendering = get_system_subpixel_rendering();
 182        let system_ui_font_name = get_system_ui_font_name();
 183        let components = DirectWriteComponents {
 184            locale,
 185            factory,
 186            in_memory_loader,
 187            builder,
 188            text_renderer,
 189            system_ui_font_name,
 190            system_subpixel_rendering,
 191        };
 192
 193        let system_font_collection = unsafe {
 194            let mut result = None;
 195            components
 196                .factory
 197                .GetSystemFontCollection(false, &mut result, true)?;
 198            result.context("Failed to get system font collection")?
 199        };
 200        let custom_font_set = unsafe { components.builder.CreateFontSet()? };
 201        let custom_font_collection = unsafe {
 202            components
 203                .factory
 204                .CreateFontCollectionFromFontSet(&custom_font_set)?
 205        };
 206
 207        Ok(Self {
 208            components,
 209            state: RwLock::new(DirectWriteState {
 210                gpu_state,
 211                system_font_collection,
 212                custom_font_collection,
 213                fonts: Vec::new(),
 214                font_to_font_id: HashMap::default(),
 215                font_info_cache: HashMap::default(),
 216                layout_line_scratch: Vec::new(),
 217            }),
 218        })
 219    }
 220
 221    pub(crate) fn handle_gpu_lost(&self, directx_devices: &DirectXDevices) -> Result<()> {
 222        self.state.write().handle_gpu_lost(directx_devices)
 223    }
 224}
 225
 226impl PlatformTextSystem for DirectWriteTextSystem {
 227    fn add_fonts(&self, fonts: Vec<Cow<'static, [u8]>>) -> Result<()> {
 228        self.state.write().add_fonts(&self.components, fonts)
 229    }
 230
 231    fn all_font_names(&self) -> Vec<String> {
 232        self.state.read().all_font_names(&self.components)
 233    }
 234
 235    fn font_id(&self, font: &Font) -> Result<FontId> {
 236        let lock = self.state.upgradable_read();
 237        if let Some(font_id) = lock.font_to_font_id.get(font) {
 238            Ok(*font_id)
 239        } else {
 240            RwLockUpgradableReadGuard::upgrade(lock)
 241                .select_and_cache_font(&self.components, font)
 242                .with_context(|| format!("Failed to select font: {:?}", font))
 243        }
 244    }
 245
 246    fn font_metrics(&self, font_id: FontId) -> FontMetrics {
 247        self.state.read().font_metrics(font_id)
 248    }
 249
 250    fn typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
 251        self.state.read().get_typographic_bounds(font_id, glyph_id)
 252    }
 253
 254    fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>> {
 255        self.state.read().get_advance(font_id, glyph_id)
 256    }
 257
 258    fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId> {
 259        self.state.read().glyph_for_char(font_id, ch)
 260    }
 261
 262    fn glyph_raster_bounds(
 263        &self,
 264        params: &RenderGlyphParams,
 265    ) -> anyhow::Result<Bounds<DevicePixels>> {
 266        self.state.read().raster_bounds(&self.components, params)
 267    }
 268
 269    fn rasterize_glyph(
 270        &self,
 271        params: &RenderGlyphParams,
 272        raster_bounds: Bounds<DevicePixels>,
 273    ) -> anyhow::Result<(Size<DevicePixels>, Vec<u8>)> {
 274        self.state
 275            .read()
 276            .rasterize_glyph(&self.components, params, raster_bounds)
 277    }
 278
 279    fn layout_line(&self, text: &str, font_size: Pixels, runs: &[FontRun]) -> LineLayout {
 280        self.state
 281            .write()
 282            .layout_line(&self.components, text, font_size, runs)
 283            .log_err()
 284            .unwrap_or(LineLayout {
 285                font_size,
 286                ..Default::default()
 287            })
 288    }
 289
 290    fn recommended_rendering_mode(
 291        &self,
 292        _font_id: FontId,
 293        _font_size: Pixels,
 294    ) -> TextRenderingMode {
 295        if self.components.system_subpixel_rendering {
 296            TextRenderingMode::Subpixel
 297        } else {
 298            TextRenderingMode::Grayscale
 299        }
 300    }
 301}
 302
 303impl DirectWriteState {
 304    fn select_and_cache_font(
 305        &mut self,
 306        components: &DirectWriteComponents,
 307        font: &Font,
 308    ) -> Option<FontId> {
 309        let select_font = |this: &mut DirectWriteState, font: &Font| -> Option<FontId> {
 310            let info = [&this.custom_font_collection, &this.system_font_collection]
 311                .into_iter()
 312                .find_map(|font_collection| unsafe {
 313                    DirectWriteState::make_font_from_font_collection(
 314                        font,
 315                        font_collection,
 316                        &components.factory,
 317                        &this.system_font_collection,
 318                        &components.system_ui_font_name,
 319                    )
 320                })?;
 321
 322            let font_id = FontId(this.fonts.len());
 323            let font_face_key = info.font_face.cast::<IUnknown>().unwrap().as_raw().addr();
 324            this.fonts.push(info);
 325            this.font_info_cache.insert(font_face_key, font_id);
 326            Some(font_id)
 327        };
 328
 329        let mut font_id = select_font(self, font);
 330        if font_id.is_none() {
 331            // try updating system fonts and reselect
 332            let mut collection = None;
 333            let font_collection_updated = unsafe {
 334                components
 335                    .factory
 336                    .GetSystemFontCollection(false, &mut collection, true)
 337            }
 338            .log_err()
 339            .is_some();
 340            if font_collection_updated && let Some(collection) = collection {
 341                self.system_font_collection = collection;
 342            }
 343            font_id = select_font(self, font);
 344        };
 345        let font_id = font_id?;
 346        self.font_to_font_id.insert(font.clone(), font_id);
 347        Some(font_id)
 348    }
 349
 350    fn add_fonts(
 351        &mut self,
 352        components: &DirectWriteComponents,
 353        fonts: Vec<Cow<'static, [u8]>>,
 354    ) -> Result<()> {
 355        for font_data in fonts {
 356            match font_data {
 357                Cow::Borrowed(data) => unsafe {
 358                    let font_file = components
 359                        .in_memory_loader
 360                        .CreateInMemoryFontFileReference(
 361                            &components.factory,
 362                            data.as_ptr().cast(),
 363                            data.len() as _,
 364                            None,
 365                        )?;
 366                    components.builder.AddFontFile(&font_file)?;
 367                },
 368                Cow::Owned(data) => unsafe {
 369                    let font_file = components
 370                        .in_memory_loader
 371                        .CreateInMemoryFontFileReference(
 372                            &components.factory,
 373                            data.as_ptr().cast(),
 374                            data.len() as _,
 375                            None,
 376                        )?;
 377                    components.builder.AddFontFile(&font_file)?;
 378                },
 379            }
 380        }
 381        let set = unsafe { components.builder.CreateFontSet()? };
 382        let collection = unsafe { components.factory.CreateFontCollectionFromFontSet(&set)? };
 383        self.custom_font_collection = collection;
 384
 385        Ok(())
 386    }
 387
 388    fn generate_font_fallbacks(
 389        fallbacks: &FontFallbacks,
 390        factory: &IDWriteFactory5,
 391        system_font_collection: &IDWriteFontCollection1,
 392    ) -> Result<Option<IDWriteFontFallback>> {
 393        let fallback_list = fallbacks.fallback_list();
 394        if fallback_list.is_empty() {
 395            return Ok(None);
 396        }
 397        unsafe {
 398            let builder = factory.CreateFontFallbackBuilder()?;
 399            let font_set = &system_font_collection.GetFontSet()?;
 400            let mut unicode_ranges = Vec::new();
 401            for family_name in fallback_list {
 402                let family_name = HSTRING::from(family_name);
 403                let Some(fonts) = font_set
 404                    .GetMatchingFonts(
 405                        &family_name,
 406                        DWRITE_FONT_WEIGHT_NORMAL,
 407                        DWRITE_FONT_STRETCH_NORMAL,
 408                        DWRITE_FONT_STYLE_NORMAL,
 409                    )
 410                    .log_err()
 411                else {
 412                    continue;
 413                };
 414                let Ok(font_face) = fonts.GetFontFaceReference(0) else {
 415                    continue;
 416                };
 417                let font = font_face.CreateFontFace()?;
 418                let mut count = 0;
 419                font.GetUnicodeRanges(None, &mut count).ok();
 420                if count == 0 {
 421                    continue;
 422                }
 423                unicode_ranges.clear();
 424                unicode_ranges.resize_with(count as usize, DWRITE_UNICODE_RANGE::default);
 425                let Some(_) = font
 426                    .GetUnicodeRanges(Some(&mut unicode_ranges), &mut count)
 427                    .log_err()
 428                else {
 429                    continue;
 430                };
 431                builder.AddMapping(
 432                    &unicode_ranges,
 433                    &[family_name.as_ptr()],
 434                    None,
 435                    None,
 436                    None,
 437                    1.0,
 438                )?;
 439            }
 440            let system_fallbacks = factory.GetSystemFontFallback()?;
 441            builder.AddMappings(&system_fallbacks)?;
 442            Ok(Some(builder.CreateFontFallback()?))
 443        }
 444    }
 445
 446    unsafe fn generate_font_features(
 447        factory: &IDWriteFactory5,
 448        font_features: &FontFeatures,
 449    ) -> Result<IDWriteTypography> {
 450        let direct_write_features = unsafe { factory.CreateTypography()? };
 451        apply_font_features(&direct_write_features, font_features)?;
 452        Ok(direct_write_features)
 453    }
 454
 455    unsafe fn make_font_from_font_collection(
 456        &Font {
 457            ref family,
 458            ref features,
 459            ref fallbacks,
 460            weight,
 461            style,
 462        }: &Font,
 463        collection: &IDWriteFontCollection1,
 464        factory: &IDWriteFactory5,
 465        system_font_collection: &IDWriteFontCollection1,
 466        system_ui_font_name: &SharedString,
 467    ) -> Option<FontInfo> {
 468        const SYSTEM_UI_FONT_NAME: &str = ".SystemUIFont";
 469        let family = if family == SYSTEM_UI_FONT_NAME {
 470            system_ui_font_name
 471        } else {
 472            gpui::font_name_with_fallbacks_shared(&family, &system_ui_font_name)
 473        };
 474        let fontset = unsafe { collection.GetFontSet().log_err()? };
 475        let font_family_h = HSTRING::from(family.as_str());
 476        let font = unsafe {
 477            fontset
 478                .GetMatchingFonts(
 479                    &font_family_h,
 480                    font_weight_to_dwrite(weight),
 481                    DWRITE_FONT_STRETCH_NORMAL,
 482                    font_style_to_dwrite(style),
 483                )
 484                .log_err()?
 485        };
 486        let total_number = unsafe { font.GetFontCount() };
 487        for index in 0..total_number {
 488            let res = maybe!({
 489                let font_face_ref = unsafe { font.GetFontFaceReference(index).log_err()? };
 490                let font_face = unsafe { font_face_ref.CreateFontFace().log_err()? };
 491                let direct_write_features =
 492                    unsafe { Self::generate_font_features(factory, features).log_err()? };
 493                let fallbacks = fallbacks.as_ref().and_then(|fallbacks| {
 494                    Self::generate_font_fallbacks(fallbacks, factory, system_font_collection)
 495                        .log_err()
 496                        .flatten()
 497                });
 498                let font_info = FontInfo {
 499                    font_family_h: font_family_h.clone(),
 500                    font_face,
 501                    features: direct_write_features,
 502                    fallbacks,
 503                    font_collection: collection.clone(),
 504                };
 505                Some(font_info)
 506            });
 507            if res.is_some() {
 508                return res;
 509            }
 510        }
 511        None
 512    }
 513
 514    fn layout_line(
 515        &mut self,
 516        components: &DirectWriteComponents,
 517        text: &str,
 518        font_size: Pixels,
 519        font_runs: &[FontRun],
 520    ) -> Result<LineLayout> {
 521        if font_runs.is_empty() {
 522            return Ok(LineLayout {
 523                font_size,
 524                ..Default::default()
 525            });
 526        }
 527        unsafe {
 528            self.layout_line_scratch.clear();
 529            self.layout_line_scratch.extend(text.encode_utf16());
 530            let text_wide = &*self.layout_line_scratch;
 531
 532            let mut utf8_offset = 0usize;
 533            let mut utf16_offset = 0u32;
 534            let text_layout = {
 535                let first_run = &font_runs[0];
 536                let font_info = &self.fonts[first_run.font_id.0];
 537                let collection = &font_info.font_collection;
 538                let format: IDWriteTextFormat1 = components
 539                    .factory
 540                    .CreateTextFormat(
 541                        &font_info.font_family_h,
 542                        collection,
 543                        font_info.font_face.GetWeight(),
 544                        font_info.font_face.GetStyle(),
 545                        DWRITE_FONT_STRETCH_NORMAL,
 546                        font_size.as_f32(),
 547                        &components.locale,
 548                    )?
 549                    .cast()?;
 550                if let Some(ref fallbacks) = font_info.fallbacks {
 551                    format.SetFontFallback(fallbacks)?;
 552                }
 553
 554                let layout = components.factory.CreateTextLayout(
 555                    text_wide,
 556                    &format,
 557                    f32::INFINITY,
 558                    f32::INFINITY,
 559                )?;
 560                let current_text = &text[utf8_offset..(utf8_offset + first_run.len)];
 561                utf8_offset += first_run.len;
 562                let current_text_utf16_length = current_text.encode_utf16().count() as u32;
 563                let text_range = DWRITE_TEXT_RANGE {
 564                    startPosition: utf16_offset,
 565                    length: current_text_utf16_length,
 566                };
 567                layout.SetTypography(&font_info.features, text_range)?;
 568                utf16_offset += current_text_utf16_length;
 569
 570                layout
 571            };
 572
 573            let (ascent, descent) = {
 574                let mut first_metrics = [DWRITE_LINE_METRICS::default(); 4];
 575                let mut line_count = 0u32;
 576                text_layout.GetLineMetrics(Some(&mut first_metrics), &mut line_count)?;
 577                (
 578                    px(first_metrics[0].baseline),
 579                    px(first_metrics[0].height - first_metrics[0].baseline),
 580                )
 581            };
 582            let mut break_ligatures = true;
 583            for run in &font_runs[1..] {
 584                let font_info = &self.fonts[run.font_id.0];
 585                let current_text = &text[utf8_offset..(utf8_offset + run.len)];
 586                utf8_offset += run.len;
 587                let current_text_utf16_length = current_text.encode_utf16().count() as u32;
 588
 589                let collection = &font_info.font_collection;
 590                let text_range = DWRITE_TEXT_RANGE {
 591                    startPosition: utf16_offset,
 592                    length: current_text_utf16_length,
 593                };
 594                utf16_offset += current_text_utf16_length;
 595                text_layout.SetFontCollection(collection, text_range)?;
 596                text_layout.SetFontFamilyName(&font_info.font_family_h, text_range)?;
 597                let font_size = if break_ligatures {
 598                    font_size.as_f32().next_up()
 599                } else {
 600                    font_size.as_f32()
 601                };
 602                text_layout.SetFontSize(font_size, text_range)?;
 603                text_layout.SetFontStyle(font_info.font_face.GetStyle(), text_range)?;
 604                text_layout.SetFontWeight(font_info.font_face.GetWeight(), text_range)?;
 605                text_layout.SetTypography(&font_info.features, text_range)?;
 606
 607                break_ligatures = !break_ligatures;
 608            }
 609
 610            let mut runs = Vec::new();
 611            let renderer_context = RendererContext {
 612                text_system: self,
 613                components,
 614                index_converter: StringIndexConverter::new(text),
 615                runs: &mut runs,
 616                width: 0.0,
 617            };
 618            text_layout.Draw(
 619                Some((&raw const renderer_context).cast::<c_void>()),
 620                &components.text_renderer.0,
 621                0.0,
 622                0.0,
 623            )?;
 624            let width = px(renderer_context.width);
 625
 626            Ok(LineLayout {
 627                font_size,
 628                width,
 629                ascent,
 630                descent,
 631                runs,
 632                len: text.len(),
 633            })
 634        }
 635    }
 636
 637    fn font_metrics(&self, font_id: FontId) -> FontMetrics {
 638        unsafe {
 639            let font_info = &self.fonts[font_id.0];
 640            let mut metrics = std::mem::zeroed();
 641            font_info.font_face.GetMetrics(&mut metrics);
 642
 643            FontMetrics {
 644                units_per_em: metrics.Base.designUnitsPerEm as _,
 645                ascent: metrics.Base.ascent as _,
 646                descent: -(metrics.Base.descent as f32),
 647                line_gap: metrics.Base.lineGap as _,
 648                underline_position: metrics.Base.underlinePosition as _,
 649                underline_thickness: metrics.Base.underlineThickness as _,
 650                cap_height: metrics.Base.capHeight as _,
 651                x_height: metrics.Base.xHeight as _,
 652                bounding_box: Bounds {
 653                    origin: Point {
 654                        x: metrics.glyphBoxLeft as _,
 655                        y: metrics.glyphBoxBottom as _,
 656                    },
 657                    size: Size {
 658                        width: (metrics.glyphBoxRight - metrics.glyphBoxLeft) as _,
 659                        height: (metrics.glyphBoxTop - metrics.glyphBoxBottom) as _,
 660                    },
 661                },
 662            }
 663        }
 664    }
 665
 666    fn create_glyph_run_analysis(
 667        &self,
 668        components: &DirectWriteComponents,
 669        params: &RenderGlyphParams,
 670    ) -> Result<IDWriteGlyphRunAnalysis> {
 671        let font = &self.fonts[params.font_id.0];
 672        let glyph_id = [params.glyph_id.0 as u16];
 673        let advance = [0.0];
 674        let offset = [DWRITE_GLYPH_OFFSET::default()];
 675        let glyph_run = DWRITE_GLYPH_RUN {
 676            fontFace: ManuallyDrop::new(Some(unsafe { std::ptr::read(&***font.font_face) })),
 677            fontEmSize: params.font_size.as_f32(),
 678            glyphCount: 1,
 679            glyphIndices: glyph_id.as_ptr(),
 680            glyphAdvances: advance.as_ptr(),
 681            glyphOffsets: offset.as_ptr(),
 682            isSideways: BOOL(0),
 683            bidiLevel: 0,
 684        };
 685        let transform = DWRITE_MATRIX {
 686            m11: params.scale_factor,
 687            m12: 0.0,
 688            m21: 0.0,
 689            m22: params.scale_factor,
 690            dx: 0.0,
 691            dy: 0.0,
 692        };
 693        let baseline_origin_x =
 694            params.subpixel_variant.x as f32 / SUBPIXEL_VARIANTS_X as f32 / params.scale_factor;
 695        let baseline_origin_y = params.subpixel_variant.y as f32
 696            / gpui::SUBPIXEL_VARIANTS_Y as f32
 697            / params.scale_factor;
 698
 699        let mut rendering_mode = DWRITE_RENDERING_MODE1::default();
 700        let mut grid_fit_mode = DWRITE_GRID_FIT_MODE::default();
 701        unsafe {
 702            font.font_face.GetRecommendedRenderingMode(
 703                params.font_size.as_f32(),
 704                // Using 96 as scale is applied by the transform
 705                96.0,
 706                96.0,
 707                Some(&transform),
 708                false,
 709                DWRITE_OUTLINE_THRESHOLD_ANTIALIASED,
 710                DWRITE_MEASURING_MODE_NATURAL,
 711                None,
 712                &mut rendering_mode,
 713                &mut grid_fit_mode,
 714            )?;
 715        }
 716        let rendering_mode = match rendering_mode {
 717            DWRITE_RENDERING_MODE1_OUTLINE => DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC,
 718            m => m,
 719        };
 720
 721        let antialias_mode = if params.subpixel_rendering {
 722            DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE
 723        } else {
 724            DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE
 725        };
 726
 727        let glyph_analysis = unsafe {
 728            components.factory.CreateGlyphRunAnalysis(
 729                &glyph_run,
 730                Some(&transform),
 731                rendering_mode,
 732                DWRITE_MEASURING_MODE_NATURAL,
 733                grid_fit_mode,
 734                antialias_mode,
 735                baseline_origin_x,
 736                baseline_origin_y,
 737            )
 738        }?;
 739        Ok(glyph_analysis)
 740    }
 741
 742    fn raster_bounds(
 743        &self,
 744        components: &DirectWriteComponents,
 745        params: &RenderGlyphParams,
 746    ) -> Result<Bounds<DevicePixels>> {
 747        let glyph_analysis = self.create_glyph_run_analysis(components, params)?;
 748
 749        let texture_type = if params.subpixel_rendering {
 750            DWRITE_TEXTURE_CLEARTYPE_3x1
 751        } else {
 752            DWRITE_TEXTURE_ALIASED_1x1
 753        };
 754
 755        let bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(texture_type)? };
 756
 757        if bounds.right < bounds.left {
 758            Ok(Bounds {
 759                origin: point(0.into(), 0.into()),
 760                size: size(0.into(), 0.into()),
 761            })
 762        } else {
 763            Ok(Bounds {
 764                origin: point(bounds.left.into(), bounds.top.into()),
 765                size: size(
 766                    (bounds.right - bounds.left).into(),
 767                    (bounds.bottom - bounds.top).into(),
 768                ),
 769            })
 770        }
 771    }
 772
 773    fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId> {
 774        let font_info = &self.fonts[font_id.0];
 775        let codepoints = ch as u32;
 776        let mut glyph_indices = 0u16;
 777        unsafe {
 778            font_info
 779                .font_face
 780                .GetGlyphIndices(&raw const codepoints, 1, &raw mut glyph_indices)
 781                .log_err()
 782        }
 783        .map(|_| GlyphId(glyph_indices as u32))
 784    }
 785
 786    fn rasterize_glyph(
 787        &self,
 788        components: &DirectWriteComponents,
 789        params: &RenderGlyphParams,
 790        glyph_bounds: Bounds<DevicePixels>,
 791    ) -> Result<(Size<DevicePixels>, Vec<u8>)> {
 792        if glyph_bounds.size.width.0 == 0 || glyph_bounds.size.height.0 == 0 {
 793            anyhow::bail!("glyph bounds are empty");
 794        }
 795
 796        let bitmap_data = if params.is_emoji {
 797            if let Ok(color) = self.rasterize_color(components, params, glyph_bounds) {
 798                color
 799            } else {
 800                let monochrome = self.rasterize_monochrome(components, params, glyph_bounds)?;
 801                monochrome
 802                    .into_iter()
 803                    .flat_map(|pixel| [0, 0, 0, pixel])
 804                    .collect::<Vec<_>>()
 805            }
 806        } else {
 807            self.rasterize_monochrome(components, params, glyph_bounds)?
 808        };
 809
 810        Ok((glyph_bounds.size, bitmap_data))
 811    }
 812
 813    fn rasterize_monochrome(
 814        &self,
 815        components: &DirectWriteComponents,
 816        params: &RenderGlyphParams,
 817        glyph_bounds: Bounds<DevicePixels>,
 818    ) -> Result<Vec<u8>> {
 819        let glyph_analysis = self.create_glyph_run_analysis(components, params)?;
 820        if !params.subpixel_rendering {
 821            let mut bitmap_data =
 822                vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize];
 823            unsafe {
 824                glyph_analysis.CreateAlphaTexture(
 825                    DWRITE_TEXTURE_ALIASED_1x1,
 826                    &RECT {
 827                        left: glyph_bounds.origin.x.0,
 828                        top: glyph_bounds.origin.y.0,
 829                        right: glyph_bounds.size.width.0 + glyph_bounds.origin.x.0,
 830                        bottom: glyph_bounds.size.height.0 + glyph_bounds.origin.y.0,
 831                    },
 832                    &mut bitmap_data,
 833                )?;
 834            }
 835
 836            return Ok(bitmap_data);
 837        }
 838
 839        let width = glyph_bounds.size.width.0 as usize;
 840        let height = glyph_bounds.size.height.0 as usize;
 841        let pixel_count = width * height;
 842
 843        let mut bitmap_data = vec![0u8; pixel_count * 4];
 844
 845        unsafe {
 846            glyph_analysis.CreateAlphaTexture(
 847                DWRITE_TEXTURE_CLEARTYPE_3x1,
 848                &RECT {
 849                    left: glyph_bounds.origin.x.0,
 850                    top: glyph_bounds.origin.y.0,
 851                    right: glyph_bounds.size.width.0 + glyph_bounds.origin.x.0,
 852                    bottom: glyph_bounds.size.height.0 + glyph_bounds.origin.y.0,
 853                },
 854                &mut bitmap_data[..pixel_count * 3],
 855            )?;
 856        }
 857
 858        // The output buffer expects RGBA data, so pad the alpha channel with zeros.
 859        for pixel_ix in (0..pixel_count).rev() {
 860            let src = pixel_ix * 3;
 861            let dst = pixel_ix * 4;
 862            (
 863                bitmap_data[dst],
 864                bitmap_data[dst + 1],
 865                bitmap_data[dst + 2],
 866                bitmap_data[dst + 3],
 867            ) = (
 868                bitmap_data[src],
 869                bitmap_data[src + 1],
 870                bitmap_data[src + 2],
 871                0,
 872            );
 873        }
 874
 875        Ok(bitmap_data)
 876    }
 877
 878    fn rasterize_color(
 879        &self,
 880        components: &DirectWriteComponents,
 881        params: &RenderGlyphParams,
 882        glyph_bounds: Bounds<DevicePixels>,
 883    ) -> Result<Vec<u8>> {
 884        let bitmap_size = glyph_bounds.size;
 885        let subpixel_shift = params
 886            .subpixel_variant
 887            .map(|v| v as f32 / SUBPIXEL_VARIANTS_X as f32);
 888        let baseline_origin_x = subpixel_shift.x / params.scale_factor;
 889        let baseline_origin_y = subpixel_shift.y / params.scale_factor;
 890
 891        let transform = DWRITE_MATRIX {
 892            m11: params.scale_factor,
 893            m12: 0.0,
 894            m21: 0.0,
 895            m22: params.scale_factor,
 896            dx: 0.0,
 897            dy: 0.0,
 898        };
 899
 900        let font = &self.fonts[params.font_id.0];
 901        let glyph_id = [params.glyph_id.0 as u16];
 902        let advance = [glyph_bounds.size.width.0 as f32];
 903        let offset = [DWRITE_GLYPH_OFFSET {
 904            advanceOffset: -glyph_bounds.origin.x.0 as f32 / params.scale_factor,
 905            ascenderOffset: glyph_bounds.origin.y.0 as f32 / params.scale_factor,
 906        }];
 907        let glyph_run = DWRITE_GLYPH_RUN {
 908            fontFace: ManuallyDrop::new(Some(unsafe { std::ptr::read(&***font.font_face) })),
 909            fontEmSize: params.font_size.as_f32(),
 910            glyphCount: 1,
 911            glyphIndices: glyph_id.as_ptr(),
 912            glyphAdvances: advance.as_ptr(),
 913            glyphOffsets: offset.as_ptr(),
 914            isSideways: BOOL(0),
 915            bidiLevel: 0,
 916        };
 917
 918        // todo: support formats other than COLR
 919        let color_enumerator = unsafe {
 920            components.factory.TranslateColorGlyphRun(
 921                Vector2::new(baseline_origin_x, baseline_origin_y),
 922                &glyph_run,
 923                None,
 924                DWRITE_GLYPH_IMAGE_FORMATS_COLR,
 925                DWRITE_MEASURING_MODE_NATURAL,
 926                Some(&transform),
 927                0,
 928            )
 929        }?;
 930
 931        let mut glyph_layers = Vec::new();
 932        let mut alpha_data = Vec::new();
 933        loop {
 934            let color_run = unsafe { color_enumerator.GetCurrentRun() }?;
 935            let color_run = unsafe { &*color_run };
 936            let image_format = color_run.glyphImageFormat & !DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE;
 937            if image_format == DWRITE_GLYPH_IMAGE_FORMATS_COLR {
 938                let color_analysis = unsafe {
 939                    components.factory.CreateGlyphRunAnalysis(
 940                        &color_run.Base.glyphRun as *const _,
 941                        Some(&transform),
 942                        DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC,
 943                        DWRITE_MEASURING_MODE_NATURAL,
 944                        DWRITE_GRID_FIT_MODE_DEFAULT,
 945                        DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE,
 946                        baseline_origin_x,
 947                        baseline_origin_y,
 948                    )
 949                }?;
 950
 951                let color_bounds =
 952                    unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1) }?;
 953
 954                let color_size = size(
 955                    color_bounds.right - color_bounds.left,
 956                    color_bounds.bottom - color_bounds.top,
 957                );
 958                if color_size.width > 0 && color_size.height > 0 {
 959                    alpha_data.clear();
 960                    alpha_data.resize((color_size.width * color_size.height) as usize, 0);
 961                    unsafe {
 962                        color_analysis.CreateAlphaTexture(
 963                            DWRITE_TEXTURE_ALIASED_1x1,
 964                            &color_bounds,
 965                            &mut alpha_data,
 966                        )
 967                    }?;
 968
 969                    let run_color = {
 970                        let run_color = color_run.Base.runColor;
 971                        Rgba {
 972                            r: run_color.r,
 973                            g: run_color.g,
 974                            b: run_color.b,
 975                            a: run_color.a,
 976                        }
 977                    };
 978                    let bounds = bounds(point(color_bounds.left, color_bounds.top), color_size);
 979                    glyph_layers.push(GlyphLayerTexture::new(
 980                        &self.gpu_state,
 981                        run_color,
 982                        bounds,
 983                        &alpha_data,
 984                    )?);
 985                }
 986            }
 987
 988            let has_next = unsafe { color_enumerator.MoveNext() }
 989                .map(|e| e.as_bool())
 990                .unwrap_or(false);
 991            if !has_next {
 992                break;
 993            }
 994        }
 995
 996        let gpu_state = &self.gpu_state;
 997        let params_buffer = {
 998            let desc = D3D11_BUFFER_DESC {
 999                ByteWidth: std::mem::size_of::<GlyphLayerTextureParams>() as u32,
1000                Usage: D3D11_USAGE_DYNAMIC,
1001                BindFlags: D3D11_BIND_CONSTANT_BUFFER.0 as u32,
1002                CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
1003                MiscFlags: 0,
1004                StructureByteStride: 0,
1005            };
1006
1007            let mut buffer = None;
1008            unsafe {
1009                gpu_state
1010                    .device
1011                    .CreateBuffer(&desc, None, Some(&mut buffer))
1012            }?;
1013            buffer
1014        };
1015
1016        let render_target_texture = {
1017            let mut texture = None;
1018            let desc = D3D11_TEXTURE2D_DESC {
1019                Width: bitmap_size.width.0 as u32,
1020                Height: bitmap_size.height.0 as u32,
1021                MipLevels: 1,
1022                ArraySize: 1,
1023                Format: DXGI_FORMAT_B8G8R8A8_UNORM,
1024                SampleDesc: DXGI_SAMPLE_DESC {
1025                    Count: 1,
1026                    Quality: 0,
1027                },
1028                Usage: D3D11_USAGE_DEFAULT,
1029                BindFlags: D3D11_BIND_RENDER_TARGET.0 as u32,
1030                CPUAccessFlags: 0,
1031                MiscFlags: 0,
1032            };
1033            unsafe {
1034                gpu_state
1035                    .device
1036                    .CreateTexture2D(&desc, None, Some(&mut texture))
1037            }?;
1038            texture.unwrap()
1039        };
1040
1041        let render_target_view = {
1042            let desc = D3D11_RENDER_TARGET_VIEW_DESC {
1043                Format: DXGI_FORMAT_B8G8R8A8_UNORM,
1044                ViewDimension: D3D11_RTV_DIMENSION_TEXTURE2D,
1045                Anonymous: D3D11_RENDER_TARGET_VIEW_DESC_0 {
1046                    Texture2D: D3D11_TEX2D_RTV { MipSlice: 0 },
1047                },
1048            };
1049            let mut rtv = None;
1050            unsafe {
1051                gpu_state.device.CreateRenderTargetView(
1052                    &render_target_texture,
1053                    Some(&desc),
1054                    Some(&mut rtv),
1055                )
1056            }?;
1057            rtv
1058        };
1059
1060        let staging_texture = {
1061            let mut texture = None;
1062            let desc = D3D11_TEXTURE2D_DESC {
1063                Width: bitmap_size.width.0 as u32,
1064                Height: bitmap_size.height.0 as u32,
1065                MipLevels: 1,
1066                ArraySize: 1,
1067                Format: DXGI_FORMAT_B8G8R8A8_UNORM,
1068                SampleDesc: DXGI_SAMPLE_DESC {
1069                    Count: 1,
1070                    Quality: 0,
1071                },
1072                Usage: D3D11_USAGE_STAGING,
1073                BindFlags: 0,
1074                CPUAccessFlags: D3D11_CPU_ACCESS_READ.0 as u32,
1075                MiscFlags: 0,
1076            };
1077            unsafe {
1078                gpu_state
1079                    .device
1080                    .CreateTexture2D(&desc, None, Some(&mut texture))
1081            }?;
1082            texture.unwrap()
1083        };
1084
1085        let device_context = &gpu_state.device_context;
1086        unsafe { device_context.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP) };
1087        unsafe { device_context.VSSetShader(&gpu_state.vertex_shader, None) };
1088        unsafe { device_context.PSSetShader(&gpu_state.pixel_shader, None) };
1089        unsafe {
1090            device_context.VSSetConstantBuffers(0, Some(std::slice::from_ref(&params_buffer)))
1091        };
1092        unsafe {
1093            device_context.PSSetConstantBuffers(0, Some(std::slice::from_ref(&params_buffer)))
1094        };
1095        unsafe {
1096            device_context.OMSetRenderTargets(Some(std::slice::from_ref(&render_target_view)), None)
1097        };
1098        unsafe { device_context.PSSetSamplers(0, Some(std::slice::from_ref(&gpu_state.sampler))) };
1099        unsafe { device_context.OMSetBlendState(&gpu_state.blend_state, None, 0xffffffff) };
1100
1101        let crate::FontInfo {
1102            gamma_ratios,
1103            grayscale_enhanced_contrast,
1104            ..
1105        } = DirectXRenderer::get_font_info();
1106
1107        for layer in glyph_layers {
1108            let params = GlyphLayerTextureParams {
1109                run_color: layer.run_color,
1110                bounds: layer.bounds,
1111                gamma_ratios: *gamma_ratios,
1112                grayscale_enhanced_contrast: *grayscale_enhanced_contrast,
1113                _pad: [0f32; 3],
1114            };
1115            unsafe {
1116                let mut dest = std::mem::zeroed();
1117                gpu_state.device_context.Map(
1118                    params_buffer.as_ref().unwrap(),
1119                    0,
1120                    D3D11_MAP_WRITE_DISCARD,
1121                    0,
1122                    Some(&mut dest),
1123                )?;
1124                std::ptr::copy_nonoverlapping(&params as *const _, dest.pData as *mut _, 1);
1125                gpu_state
1126                    .device_context
1127                    .Unmap(params_buffer.as_ref().unwrap(), 0);
1128            };
1129
1130            let texture = [Some(layer.texture_view)];
1131            unsafe { device_context.PSSetShaderResources(0, Some(&texture)) };
1132
1133            let viewport = [D3D11_VIEWPORT {
1134                TopLeftX: layer.bounds.origin.x as f32,
1135                TopLeftY: layer.bounds.origin.y as f32,
1136                Width: layer.bounds.size.width as f32,
1137                Height: layer.bounds.size.height as f32,
1138                MinDepth: 0.0,
1139                MaxDepth: 1.0,
1140            }];
1141            unsafe { device_context.RSSetViewports(Some(&viewport)) };
1142
1143            unsafe { device_context.Draw(4, 0) };
1144        }
1145
1146        unsafe { device_context.CopyResource(&staging_texture, &render_target_texture) };
1147
1148        let mapped_data = {
1149            let mut mapped_data = D3D11_MAPPED_SUBRESOURCE::default();
1150            unsafe {
1151                device_context.Map(
1152                    &staging_texture,
1153                    0,
1154                    D3D11_MAP_READ,
1155                    0,
1156                    Some(&mut mapped_data),
1157                )
1158            }?;
1159            mapped_data
1160        };
1161        let mut rasterized =
1162            vec![0u8; (bitmap_size.width.0 as u32 * bitmap_size.height.0 as u32 * 4) as usize];
1163
1164        for y in 0..bitmap_size.height.0 as usize {
1165            let width = bitmap_size.width.0 as usize;
1166            unsafe {
1167                std::ptr::copy_nonoverlapping::<u8>(
1168                    (mapped_data.pData as *const u8).byte_add(mapped_data.RowPitch as usize * y),
1169                    rasterized
1170                        .as_mut_ptr()
1171                        .byte_add(width * y * std::mem::size_of::<u32>()),
1172                    width * std::mem::size_of::<u32>(),
1173                )
1174            };
1175        }
1176
1177        // Convert from premultiplied to straight alpha
1178        for chunk in rasterized.chunks_exact_mut(4) {
1179            let b = chunk[0] as f32;
1180            let g = chunk[1] as f32;
1181            let r = chunk[2] as f32;
1182            let a = chunk[3] as f32;
1183            if a > 0.0 {
1184                let inv_a = 255.0 / a;
1185                chunk[0] = (b * inv_a).clamp(0.0, 255.0) as u8;
1186                chunk[1] = (g * inv_a).clamp(0.0, 255.0) as u8;
1187                chunk[2] = (r * inv_a).clamp(0.0, 255.0) as u8;
1188            }
1189        }
1190
1191        Ok(rasterized)
1192    }
1193
1194    fn get_typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
1195        unsafe {
1196            let font = &self.fonts[font_id.0].font_face;
1197            let glyph_indices = [glyph_id.0 as u16];
1198            let mut metrics = [DWRITE_GLYPH_METRICS::default()];
1199            font.GetDesignGlyphMetrics(glyph_indices.as_ptr(), 1, metrics.as_mut_ptr(), false)?;
1200
1201            let metrics = &metrics[0];
1202            let advance_width = metrics.advanceWidth as i32;
1203            let advance_height = metrics.advanceHeight as i32;
1204            let left_side_bearing = metrics.leftSideBearing;
1205            let right_side_bearing = metrics.rightSideBearing;
1206            let top_side_bearing = metrics.topSideBearing;
1207            let bottom_side_bearing = metrics.bottomSideBearing;
1208            let vertical_origin_y = metrics.verticalOriginY;
1209
1210            let y_offset = vertical_origin_y + bottom_side_bearing - advance_height;
1211            let width = advance_width - (left_side_bearing + right_side_bearing);
1212            let height = advance_height - (top_side_bearing + bottom_side_bearing);
1213
1214            Ok(Bounds {
1215                origin: Point {
1216                    x: left_side_bearing as f32,
1217                    y: y_offset as f32,
1218                },
1219                size: Size {
1220                    width: width as f32,
1221                    height: height as f32,
1222                },
1223            })
1224        }
1225    }
1226
1227    fn get_advance(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Size<f32>> {
1228        unsafe {
1229            let font = &self.fonts[font_id.0].font_face;
1230            let glyph_indices = [glyph_id.0 as u16];
1231            let mut metrics = [DWRITE_GLYPH_METRICS::default()];
1232            font.GetDesignGlyphMetrics(glyph_indices.as_ptr(), 1, metrics.as_mut_ptr(), false)?;
1233
1234            let metrics = &metrics[0];
1235
1236            Ok(Size {
1237                width: metrics.advanceWidth as f32,
1238                height: 0.0,
1239            })
1240        }
1241    }
1242
1243    fn all_font_names(&self, components: &DirectWriteComponents) -> Vec<String> {
1244        let mut result =
1245            get_font_names_from_collection(&self.system_font_collection, &components.locale);
1246        result.extend(get_font_names_from_collection(
1247            &self.custom_font_collection,
1248            &components.locale,
1249        ));
1250        result
1251    }
1252
1253    fn handle_gpu_lost(&mut self, directx_devices: &DirectXDevices) -> Result<()> {
1254        try_to_recover_from_device_lost(|| {
1255            GPUState::new(directx_devices).context("Recreating GPU state for DirectWrite")
1256        })
1257        .map(|gpu_state| self.gpu_state = gpu_state)
1258    }
1259}
1260
1261struct GlyphLayerTexture {
1262    run_color: Rgba,
1263    bounds: Bounds<i32>,
1264    texture_view: ID3D11ShaderResourceView,
1265    // holding on to the texture to not RAII drop it
1266    _texture: ID3D11Texture2D,
1267}
1268
1269impl GlyphLayerTexture {
1270    fn new(
1271        gpu_state: &GPUState,
1272        run_color: Rgba,
1273        bounds: Bounds<i32>,
1274        alpha_data: &[u8],
1275    ) -> Result<Self> {
1276        let texture_size = bounds.size;
1277
1278        let desc = D3D11_TEXTURE2D_DESC {
1279            Width: texture_size.width as u32,
1280            Height: texture_size.height as u32,
1281            MipLevels: 1,
1282            ArraySize: 1,
1283            Format: DXGI_FORMAT_R8_UNORM,
1284            SampleDesc: DXGI_SAMPLE_DESC {
1285                Count: 1,
1286                Quality: 0,
1287            },
1288            Usage: D3D11_USAGE_DEFAULT,
1289            BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32,
1290            CPUAccessFlags: 0,
1291            MiscFlags: 0,
1292        };
1293
1294        let texture = {
1295            let mut texture: Option<ID3D11Texture2D> = None;
1296            unsafe {
1297                gpu_state
1298                    .device
1299                    .CreateTexture2D(&desc, None, Some(&mut texture))?
1300            };
1301            texture.unwrap()
1302        };
1303        let texture_view = {
1304            let mut view: Option<ID3D11ShaderResourceView> = None;
1305            unsafe {
1306                gpu_state
1307                    .device
1308                    .CreateShaderResourceView(&texture, None, Some(&mut view))?
1309            };
1310            view.unwrap()
1311        };
1312
1313        unsafe {
1314            gpu_state.device_context.UpdateSubresource(
1315                &texture,
1316                0,
1317                None,
1318                alpha_data.as_ptr() as _,
1319                texture_size.width as u32,
1320                0,
1321            )
1322        };
1323
1324        Ok(GlyphLayerTexture {
1325            run_color,
1326            bounds,
1327            texture_view,
1328            _texture: texture,
1329        })
1330    }
1331}
1332
1333#[repr(C)]
1334struct GlyphLayerTextureParams {
1335    bounds: Bounds<i32>,
1336    run_color: Rgba,
1337    gamma_ratios: [f32; 4],
1338    grayscale_enhanced_contrast: f32,
1339    _pad: [f32; 3],
1340}
1341
1342struct TextRendererWrapper(IDWriteTextRenderer);
1343
1344impl TextRendererWrapper {
1345    fn new(locale_str: HSTRING) -> Self {
1346        let inner = TextRenderer::new(locale_str);
1347        TextRendererWrapper(inner.into())
1348    }
1349}
1350
1351#[implement(IDWriteTextRenderer)]
1352struct TextRenderer {
1353    locale: HSTRING,
1354}
1355
1356impl TextRenderer {
1357    fn new(locale: HSTRING) -> Self {
1358        TextRenderer { locale }
1359    }
1360}
1361
1362struct RendererContext<'t, 'a, 'b> {
1363    text_system: &'t mut DirectWriteState,
1364    components: &'a DirectWriteComponents,
1365    index_converter: StringIndexConverter<'a>,
1366    runs: &'b mut Vec<ShapedRun>,
1367    width: f32,
1368}
1369
1370#[derive(Debug)]
1371struct ClusterAnalyzer<'t> {
1372    utf16_idx: usize,
1373    glyph_idx: usize,
1374    glyph_count: usize,
1375    cluster_map: &'t [u16],
1376}
1377
1378impl<'t> ClusterAnalyzer<'t> {
1379    fn new(cluster_map: &'t [u16], glyph_count: usize) -> Self {
1380        ClusterAnalyzer {
1381            utf16_idx: 0,
1382            glyph_idx: 0,
1383            glyph_count,
1384            cluster_map,
1385        }
1386    }
1387}
1388
1389impl Iterator for ClusterAnalyzer<'_> {
1390    type Item = (usize, usize);
1391
1392    fn next(&mut self) -> Option<(usize, usize)> {
1393        if self.utf16_idx >= self.cluster_map.len() {
1394            return None; // No more clusters
1395        }
1396        let start_utf16_idx = self.utf16_idx;
1397        let current_glyph = self.cluster_map[start_utf16_idx] as usize;
1398
1399        // Find the end of current cluster (where glyph index changes)
1400        let mut end_utf16_idx = start_utf16_idx + 1;
1401        while end_utf16_idx < self.cluster_map.len()
1402            && self.cluster_map[end_utf16_idx] as usize == current_glyph
1403        {
1404            end_utf16_idx += 1;
1405        }
1406
1407        let utf16_len = end_utf16_idx - start_utf16_idx;
1408
1409        // Calculate glyph count for this cluster
1410        let next_glyph = if end_utf16_idx < self.cluster_map.len() {
1411            self.cluster_map[end_utf16_idx] as usize
1412        } else {
1413            self.glyph_count
1414        };
1415
1416        let glyph_count = next_glyph - current_glyph;
1417
1418        // Update state for next call
1419        self.utf16_idx = end_utf16_idx;
1420        self.glyph_idx = next_glyph;
1421
1422        Some((utf16_len, glyph_count))
1423    }
1424}
1425
1426#[allow(non_snake_case)]
1427impl IDWritePixelSnapping_Impl for TextRenderer_Impl {
1428    fn IsPixelSnappingDisabled(
1429        &self,
1430        _clientdrawingcontext: *const ::core::ffi::c_void,
1431    ) -> windows::core::Result<BOOL> {
1432        Ok(BOOL(0))
1433    }
1434
1435    fn GetCurrentTransform(
1436        &self,
1437        _clientdrawingcontext: *const ::core::ffi::c_void,
1438        transform: *mut DWRITE_MATRIX,
1439    ) -> windows::core::Result<()> {
1440        unsafe {
1441            *transform = DWRITE_MATRIX {
1442                m11: 1.0,
1443                m12: 0.0,
1444                m21: 0.0,
1445                m22: 1.0,
1446                dx: 0.0,
1447                dy: 0.0,
1448            };
1449        }
1450        Ok(())
1451    }
1452
1453    fn GetPixelsPerDip(
1454        &self,
1455        _clientdrawingcontext: *const ::core::ffi::c_void,
1456    ) -> windows::core::Result<f32> {
1457        Ok(1.0)
1458    }
1459}
1460
1461#[allow(non_snake_case)]
1462impl IDWriteTextRenderer_Impl for TextRenderer_Impl {
1463    fn DrawGlyphRun(
1464        &self,
1465        clientdrawingcontext: *const ::core::ffi::c_void,
1466        _baselineoriginx: f32,
1467        _baselineoriginy: f32,
1468        _measuringmode: DWRITE_MEASURING_MODE,
1469        glyphrun: *const DWRITE_GLYPH_RUN,
1470        glyphrundescription: *const DWRITE_GLYPH_RUN_DESCRIPTION,
1471        _clientdrawingeffect: windows::core::Ref<windows::core::IUnknown>,
1472    ) -> windows::core::Result<()> {
1473        let glyphrun = unsafe { &*glyphrun };
1474        let glyph_count = glyphrun.glyphCount as usize;
1475        if glyph_count == 0 {
1476            return Ok(());
1477        }
1478        let desc = unsafe { &*glyphrundescription };
1479        let context = unsafe { &mut *(clientdrawingcontext.cast::<RendererContext>().cast_mut()) };
1480        let Some(font_face) = glyphrun.fontFace.as_ref() else {
1481            return Ok(());
1482        };
1483        // This `cast()` action here should never fail since we are running on Win10+, and
1484        // `IDWriteFontFace3` requires Win10
1485        let Ok(font_face) = &font_face.cast::<IDWriteFontFace3>() else {
1486            return Err(Error::new(
1487                DWRITE_E_UNSUPPORTEDOPERATION,
1488                "Failed to cast font face",
1489            ));
1490        };
1491
1492        let font_face_key = font_face.cast::<IUnknown>().unwrap().as_raw().addr();
1493        let font_id = context
1494            .text_system
1495            .font_info_cache
1496            .get(&font_face_key)
1497            .copied()
1498            // in some circumstances, we might be getting served a FontFace that we did not create ourselves
1499            // so create a new font from it and cache it accordingly. The usual culprit here seems to be Segoe UI Symbol
1500            .map_or_else(
1501                || {
1502                    let font = font_face_to_font(font_face, &self.locale)
1503                        .ok_or_else(|| Error::new(DWRITE_E_NOFONT, "Failed to create font"))?;
1504                    let font_id = match context.text_system.font_to_font_id.get(&font) {
1505                        Some(&font_id) => font_id,
1506                        None => context
1507                            .text_system
1508                            .select_and_cache_font(context.components, &font)
1509                            .ok_or_else(|| Error::new(DWRITE_E_NOFONT, "Failed to create font"))?,
1510                    };
1511                    context
1512                        .text_system
1513                        .font_info_cache
1514                        .insert(font_face_key, font_id);
1515                    windows::core::Result::Ok(font_id)
1516                },
1517                Ok,
1518            )?;
1519
1520        let color_font = unsafe { font_face.IsColorFont().as_bool() };
1521
1522        let glyph_ids = unsafe { std::slice::from_raw_parts(glyphrun.glyphIndices, glyph_count) };
1523        let glyph_advances =
1524            unsafe { std::slice::from_raw_parts(glyphrun.glyphAdvances, glyph_count) };
1525        let glyph_offsets =
1526            unsafe { std::slice::from_raw_parts(glyphrun.glyphOffsets, glyph_count) };
1527        let cluster_map =
1528            unsafe { std::slice::from_raw_parts(desc.clusterMap, desc.stringLength as usize) };
1529
1530        let cluster_analyzer = ClusterAnalyzer::new(cluster_map, glyph_count);
1531        let mut utf16_idx = desc.textPosition as usize;
1532        let mut glyph_idx = 0;
1533        let mut glyphs = Vec::with_capacity(glyph_count);
1534        for (cluster_utf16_len, cluster_glyph_count) in cluster_analyzer {
1535            context.index_converter.advance_to_utf16_ix(utf16_idx);
1536            utf16_idx += cluster_utf16_len;
1537            for (cluster_glyph_idx, glyph_id) in glyph_ids
1538                [glyph_idx..(glyph_idx + cluster_glyph_count)]
1539                .iter()
1540                .enumerate()
1541            {
1542                let id = GlyphId(*glyph_id as u32);
1543                let is_emoji =
1544                    color_font && is_color_glyph(font_face, id, &context.components.factory);
1545                let this_glyph_idx = glyph_idx + cluster_glyph_idx;
1546                glyphs.push(ShapedGlyph {
1547                    id,
1548                    position: point(
1549                        px(context.width + glyph_offsets[this_glyph_idx].advanceOffset),
1550                        px(-glyph_offsets[this_glyph_idx].ascenderOffset),
1551                    ),
1552                    index: context.index_converter.utf8_ix,
1553                    is_emoji,
1554                });
1555                context.width += glyph_advances[this_glyph_idx];
1556            }
1557            glyph_idx += cluster_glyph_count;
1558        }
1559        context.runs.push(ShapedRun { font_id, glyphs });
1560        Ok(())
1561    }
1562
1563    fn DrawUnderline(
1564        &self,
1565        _clientdrawingcontext: *const ::core::ffi::c_void,
1566        _baselineoriginx: f32,
1567        _baselineoriginy: f32,
1568        _underline: *const DWRITE_UNDERLINE,
1569        _clientdrawingeffect: windows::core::Ref<windows::core::IUnknown>,
1570    ) -> windows::core::Result<()> {
1571        Err(windows::core::Error::new(
1572            E_NOTIMPL,
1573            "DrawUnderline unimplemented",
1574        ))
1575    }
1576
1577    fn DrawStrikethrough(
1578        &self,
1579        _clientdrawingcontext: *const ::core::ffi::c_void,
1580        _baselineoriginx: f32,
1581        _baselineoriginy: f32,
1582        _strikethrough: *const DWRITE_STRIKETHROUGH,
1583        _clientdrawingeffect: windows::core::Ref<windows::core::IUnknown>,
1584    ) -> windows::core::Result<()> {
1585        Err(windows::core::Error::new(
1586            E_NOTIMPL,
1587            "DrawStrikethrough unimplemented",
1588        ))
1589    }
1590
1591    fn DrawInlineObject(
1592        &self,
1593        _clientdrawingcontext: *const ::core::ffi::c_void,
1594        _originx: f32,
1595        _originy: f32,
1596        _inlineobject: windows::core::Ref<IDWriteInlineObject>,
1597        _issideways: BOOL,
1598        _isrighttoleft: BOOL,
1599        _clientdrawingeffect: windows::core::Ref<windows::core::IUnknown>,
1600    ) -> windows::core::Result<()> {
1601        Err(windows::core::Error::new(
1602            E_NOTIMPL,
1603            "DrawInlineObject unimplemented",
1604        ))
1605    }
1606}
1607
1608struct StringIndexConverter<'a> {
1609    text: &'a str,
1610    utf8_ix: usize,
1611    utf16_ix: usize,
1612}
1613
1614impl<'a> StringIndexConverter<'a> {
1615    fn new(text: &'a str) -> Self {
1616        Self {
1617            text,
1618            utf8_ix: 0,
1619            utf16_ix: 0,
1620        }
1621    }
1622
1623    #[allow(dead_code)]
1624    fn advance_to_utf8_ix(&mut self, utf8_target: usize) {
1625        for (ix, c) in self.text[self.utf8_ix..].char_indices() {
1626            if self.utf8_ix + ix >= utf8_target {
1627                self.utf8_ix += ix;
1628                return;
1629            }
1630            self.utf16_ix += c.len_utf16();
1631        }
1632        self.utf8_ix = self.text.len();
1633    }
1634
1635    fn advance_to_utf16_ix(&mut self, utf16_target: usize) {
1636        for (ix, c) in self.text[self.utf8_ix..].char_indices() {
1637            if self.utf16_ix >= utf16_target {
1638                self.utf8_ix += ix;
1639                return;
1640            }
1641            self.utf16_ix += c.len_utf16();
1642        }
1643        self.utf8_ix = self.text.len();
1644    }
1645}
1646
1647fn font_style_to_dwrite(style: FontStyle) -> DWRITE_FONT_STYLE {
1648    match style {
1649        FontStyle::Normal => DWRITE_FONT_STYLE_NORMAL,
1650        FontStyle::Italic => DWRITE_FONT_STYLE_ITALIC,
1651        FontStyle::Oblique => DWRITE_FONT_STYLE_OBLIQUE,
1652    }
1653}
1654
1655fn font_style_from_dwrite(value: DWRITE_FONT_STYLE) -> FontStyle {
1656    match value.0 {
1657        0 => FontStyle::Normal,
1658        1 => FontStyle::Italic,
1659        2 => FontStyle::Oblique,
1660        _ => unreachable!(),
1661    }
1662}
1663
1664fn font_weight_to_dwrite(weight: FontWeight) -> DWRITE_FONT_WEIGHT {
1665    DWRITE_FONT_WEIGHT(weight.0 as i32)
1666}
1667
1668fn font_weight_from_dwrite(value: DWRITE_FONT_WEIGHT) -> FontWeight {
1669    FontWeight(value.0 as f32)
1670}
1671
1672fn get_font_names_from_collection(
1673    collection: &IDWriteFontCollection1,
1674    locale: &HSTRING,
1675) -> Vec<String> {
1676    unsafe {
1677        let mut result = Vec::new();
1678        let family_count = collection.GetFontFamilyCount();
1679        for index in 0..family_count {
1680            let Some(font_family) = collection.GetFontFamily(index).log_err() else {
1681                continue;
1682            };
1683            let Some(localized_family_name) = font_family.GetFamilyNames().log_err() else {
1684                continue;
1685            };
1686            let Some(family_name) = get_name(localized_family_name, locale).log_err() else {
1687                continue;
1688            };
1689            result.push(family_name);
1690        }
1691
1692        result
1693    }
1694}
1695
1696fn font_face_to_font(font_face: &IDWriteFontFace3, locale: &HSTRING) -> Option<Font> {
1697    let localized_family_name = unsafe { font_face.GetFamilyNames().log_err() }?;
1698    let family_name = get_name(localized_family_name, locale).log_err()?;
1699    let weight = unsafe { font_face.GetWeight() };
1700    let style = unsafe { font_face.GetStyle() };
1701    Some(Font {
1702        family: family_name.into(),
1703        features: FontFeatures::default(),
1704        weight: font_weight_from_dwrite(weight),
1705        style: font_style_from_dwrite(style),
1706        fallbacks: None,
1707    })
1708}
1709
1710// https://learn.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_font_feature_tag
1711fn apply_font_features(
1712    direct_write_features: &IDWriteTypography,
1713    features: &FontFeatures,
1714) -> Result<()> {
1715    let tag_values = features.tag_value_list();
1716    if tag_values.is_empty() {
1717        return Ok(());
1718    }
1719
1720    // All of these features are enabled by default by DirectWrite.
1721    // If you want to (and can) peek into the source of DirectWrite
1722    let mut feature_liga = make_direct_write_feature("liga", 1);
1723    let mut feature_clig = make_direct_write_feature("clig", 1);
1724    let mut feature_calt = make_direct_write_feature("calt", 1);
1725
1726    for (tag, value) in tag_values {
1727        if tag.as_str() == "liga" && *value == 0 {
1728            feature_liga.parameter = 0;
1729            continue;
1730        }
1731        if tag.as_str() == "clig" && *value == 0 {
1732            feature_clig.parameter = 0;
1733            continue;
1734        }
1735        if tag.as_str() == "calt" && *value == 0 {
1736            feature_calt.parameter = 0;
1737            continue;
1738        }
1739
1740        unsafe {
1741            direct_write_features.AddFontFeature(make_direct_write_feature(tag, *value))?;
1742        }
1743    }
1744    unsafe {
1745        direct_write_features.AddFontFeature(feature_liga)?;
1746        direct_write_features.AddFontFeature(feature_clig)?;
1747        direct_write_features.AddFontFeature(feature_calt)?;
1748    }
1749
1750    Ok(())
1751}
1752
1753#[inline]
1754const fn make_direct_write_feature(feature_name: &str, parameter: u32) -> DWRITE_FONT_FEATURE {
1755    let tag = make_direct_write_tag(feature_name);
1756    DWRITE_FONT_FEATURE {
1757        nameTag: tag,
1758        parameter,
1759    }
1760}
1761
1762#[inline]
1763const fn make_open_type_tag(tag_name: &str) -> u32 {
1764    let bytes = tag_name.as_bytes();
1765    debug_assert!(bytes.len() == 4);
1766    u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])
1767}
1768
1769#[inline]
1770const fn make_direct_write_tag(tag_name: &str) -> DWRITE_FONT_FEATURE_TAG {
1771    DWRITE_FONT_FEATURE_TAG(make_open_type_tag(tag_name))
1772}
1773
1774#[inline]
1775fn get_name(string: IDWriteLocalizedStrings, locale: &HSTRING) -> Result<String> {
1776    let mut locale_name_index = 0u32;
1777    let mut exists = BOOL(0);
1778    unsafe { string.FindLocaleName(locale, &mut locale_name_index, &mut exists as _)? };
1779    if !exists.as_bool() {
1780        unsafe {
1781            string.FindLocaleName(
1782                DEFAULT_LOCALE_NAME,
1783                &mut locale_name_index as _,
1784                &mut exists as _,
1785            )?
1786        };
1787        anyhow::ensure!(exists.as_bool(), "No localised string for {locale}");
1788    }
1789
1790    let name_length = unsafe { string.GetStringLength(locale_name_index) }? as usize;
1791    let mut name_vec = vec![0u16; name_length + 1];
1792    unsafe {
1793        string.GetString(locale_name_index, &mut name_vec)?;
1794    }
1795
1796    Ok(String::from_utf16_lossy(&name_vec[..name_length]))
1797}
1798
1799fn get_system_subpixel_rendering() -> bool {
1800    let mut value = c_uint::default();
1801    let result = unsafe {
1802        SystemParametersInfoW(
1803            SPI_GETFONTSMOOTHINGTYPE,
1804            0,
1805            Some((&mut value) as *mut c_uint as *mut c_void),
1806            SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS::default(),
1807        )
1808    };
1809    if result.log_err().is_some() {
1810        value == FE_FONTSMOOTHINGCLEARTYPE
1811    } else {
1812        true
1813    }
1814}
1815
1816fn get_system_ui_font_name() -> SharedString {
1817    unsafe {
1818        let mut info: LOGFONTW = std::mem::zeroed();
1819        let font_family = if SystemParametersInfoW(
1820            SPI_GETICONTITLELOGFONT,
1821            std::mem::size_of::<LOGFONTW>() as u32,
1822            Some(&mut info as *mut _ as _),
1823            SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0),
1824        )
1825        .log_err()
1826        .is_none()
1827        {
1828            // https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts
1829            // Segoe UI is the Windows font intended for user interface text strings.
1830            "Segoe UI".into()
1831        } else {
1832            let font_name = String::from_utf16_lossy(&info.lfFaceName);
1833            font_name.trim_matches(char::from(0)).to_owned().into()
1834        };
1835        log::info!("Use {} as UI font.", font_family);
1836        font_family
1837    }
1838}
1839
1840// One would think that with newer DirectWrite method: IDWriteFontFace4::GetGlyphImageFormats
1841// but that doesn't seem to work for some glyphs, say โค
1842fn is_color_glyph(
1843    font_face: &IDWriteFontFace3,
1844    glyph_id: GlyphId,
1845    factory: &IDWriteFactory5,
1846) -> bool {
1847    let glyph_run = DWRITE_GLYPH_RUN {
1848        fontFace: ManuallyDrop::new(Some(unsafe { std::ptr::read(&****font_face) })),
1849        fontEmSize: 14.0,
1850        glyphCount: 1,
1851        glyphIndices: &(glyph_id.0 as u16),
1852        glyphAdvances: &0.0,
1853        glyphOffsets: &DWRITE_GLYPH_OFFSET {
1854            advanceOffset: 0.0,
1855            ascenderOffset: 0.0,
1856        },
1857        isSideways: BOOL(0),
1858        bidiLevel: 0,
1859    };
1860    unsafe {
1861        factory.TranslateColorGlyphRun(
1862            Vector2::default(),
1863            &glyph_run as _,
1864            None,
1865            DWRITE_GLYPH_IMAGE_FORMATS_COLR
1866                | DWRITE_GLYPH_IMAGE_FORMATS_SVG
1867                | DWRITE_GLYPH_IMAGE_FORMATS_PNG
1868                | DWRITE_GLYPH_IMAGE_FORMATS_JPEG
1869                | DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8,
1870            DWRITE_MEASURING_MODE_NATURAL,
1871            None,
1872            0,
1873        )
1874    }
1875    .is_ok()
1876}
1877
1878const DEFAULT_LOCALE_NAME: PCWSTR = windows::core::w!("en-US");
1879
1880#[cfg(test)]
1881mod tests {
1882    use crate::direct_write::ClusterAnalyzer;
1883
1884    #[test]
1885    fn test_cluster_map() {
1886        let cluster_map = [0];
1887        let mut analyzer = ClusterAnalyzer::new(&cluster_map, 1);
1888        let next = analyzer.next();
1889        assert_eq!(next, Some((1, 1)));
1890        let next = analyzer.next();
1891        assert_eq!(next, None);
1892
1893        let cluster_map = [0, 1, 2];
1894        let mut analyzer = ClusterAnalyzer::new(&cluster_map, 3);
1895        let next = analyzer.next();
1896        assert_eq!(next, Some((1, 1)));
1897        let next = analyzer.next();
1898        assert_eq!(next, Some((1, 1)));
1899        let next = analyzer.next();
1900        assert_eq!(next, Some((1, 1)));
1901        let next = analyzer.next();
1902        assert_eq!(next, None);
1903        // ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘ฉโ€๐Ÿ’ป
1904        let cluster_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4];
1905        let mut analyzer = ClusterAnalyzer::new(&cluster_map, 5);
1906        let next = analyzer.next();
1907        assert_eq!(next, Some((11, 4)));
1908        let next = analyzer.next();
1909        assert_eq!(next, Some((5, 1)));
1910        let next = analyzer.next();
1911        assert_eq!(next, None);
1912        // ๐Ÿ‘ฉโ€๐Ÿ’ป
1913        let cluster_map = [0, 0, 0, 0, 0];
1914        let mut analyzer = ClusterAnalyzer::new(&cluster_map, 1);
1915        let next = analyzer.next();
1916        assert_eq!(next, Some((5, 1)));
1917        let next = analyzer.next();
1918        assert_eq!(next, None);
1919    }
1920}