This commit is contained in:
Junkui Zhang 2025-08-01 18:00:12 +08:00
parent 3be48a9813
commit a4e8d2501a

View file

@ -728,6 +728,7 @@ impl DirectWriteState {
fn create_glyph_run_analysis(
&self,
params: &RenderGlyphParams,
scale: f32,
) -> Result<IDWriteGlyphRunAnalysis> {
let font = &self.fonts[params.font_id.0];
let glyph_id = [params.glyph_id.0 as u16];
@ -744,18 +745,18 @@ impl DirectWriteState {
bidiLevel: 0,
};
let transform = DWRITE_MATRIX {
m11: params.scale_factor,
m11: params.scale_factor * scale,
m12: 0.0,
m21: 0.0,
m22: params.scale_factor,
m22: params.scale_factor * scale,
dx: 0.0,
dy: 0.0,
};
let subpixel_shift = params
.subpixel_variant
.map(|v| v as f32 / SUBPIXEL_VARIANTS as f32);
let baseline_origin_x = subpixel_shift.x / params.scale_factor;
let baseline_origin_y = subpixel_shift.y / params.scale_factor;
let baseline_origin_x = subpixel_shift.x * scale / params.scale_factor;
let baseline_origin_y = subpixel_shift.y * scale / params.scale_factor;
let mut rendering_mode = DWRITE_RENDERING_MODE1::default();
let mut grid_fit_mode = DWRITE_GRID_FIT_MODE::default();
@ -783,7 +784,8 @@ impl DirectWriteState {
DWRITE_MEASURING_MODE_NATURAL,
grid_fit_mode,
// We're using cleartype not grayscale for monochrome is because it provides better quality
DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
// DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE,
baseline_origin_x,
baseline_origin_y,
)
@ -792,7 +794,7 @@ impl DirectWriteState {
}
fn raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
let glyph_analysis = self.create_glyph_run_analysis(params)?;
let glyph_analysis = self.create_glyph_run_analysis(params, 1.0)?;
let bounds = unsafe { glyph_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1)? };
// Some glyphs cannot be drawn with ClearType, such as bitmap fonts. In that case
@ -817,10 +819,13 @@ impl DirectWriteState {
})
} else {
Ok(Bounds {
origin: point((bounds.left as i32).into(), (bounds.top as i32).into()),
origin: point(
(bounds.left as i32 - 1).into(),
(bounds.top as i32 - 1).into(),
),
size: size(
(bounds.right - bounds.left).into(),
(bounds.bottom - bounds.top).into(),
(bounds.right - bounds.left + 2).into(),
(bounds.bottom - bounds.top + 2).into(),
),
})
}
@ -872,18 +877,19 @@ impl DirectWriteState {
glyph_bounds: Bounds<DevicePixels>,
) -> Result<Vec<u8>> {
let mut bitmap_data =
vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize * 3];
vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize * 4];
let glyph_analysis = self.create_glyph_run_analysis(params)?;
let glyph_analysis = self.create_glyph_run_analysis(params, 2.0)?;
unsafe {
glyph_analysis.CreateAlphaTexture(
// We're using cleartype not grayscale for monochrome is because it provides better quality
DWRITE_TEXTURE_CLEARTYPE_3x1,
// DWRITE_TEXTURE_CLEARTYPE_3x1,
DWRITE_TEXTURE_ALIASED_1x1,
&RECT {
left: glyph_bounds.origin.x.0,
top: glyph_bounds.origin.y.0,
right: glyph_bounds.size.width.0 + glyph_bounds.origin.x.0,
bottom: glyph_bounds.size.height.0 + glyph_bounds.origin.y.0,
left: glyph_bounds.origin.x.0 * 2,
top: glyph_bounds.origin.y.0 * 2,
right: glyph_bounds.size.width.0 * 2 + glyph_bounds.origin.x.0 * 2,
bottom: glyph_bounds.size.height.0 * 2 + glyph_bounds.origin.y.0 * 2,
},
&mut bitmap_data,
)?;
@ -892,21 +898,31 @@ impl DirectWriteState {
let bitmap_factory = self.components.bitmap_factory.resolve()?;
let bitmap = unsafe {
bitmap_factory.CreateBitmapFromMemory(
glyph_bounds.size.width.0 as u32,
glyph_bounds.size.height.0 as u32,
&GUID_WICPixelFormat24bppRGB,
glyph_bounds.size.width.0 as u32 * 3,
glyph_bounds.size.width.0 as u32 * 2,
glyph_bounds.size.height.0 as u32 * 2,
// &GUID_WICPixelFormat24bppRGB,
&GUID_WICPixelFormat8bppGray,
glyph_bounds.size.width.0 as u32 * 2,
&bitmap_data,
)
}?;
let grayscale_bitmap =
unsafe { WICConvertBitmapSource(&GUID_WICPixelFormat8bppGray, &bitmap) }?;
// let grayscale_bitmap =
// unsafe { WICConvertBitmapSource(&GUID_WICPixelFormat8bppGray, &bitmap) }?;
let scaler = unsafe { bitmap_factory.CreateBitmapScaler()? };
unsafe {
scaler.Initialize(
&bitmap,
glyph_bounds.size.width.0 as u32,
glyph_bounds.size.height.0 as u32,
WICBitmapInterpolationModeHighQualityCubic,
)?;
}
let mut bitmap_data =
vec![0u8; glyph_bounds.size.width.0 as usize * glyph_bounds.size.height.0 as usize];
unsafe {
grayscale_bitmap.CopyPixels(
scaler.CopyPixels(
std::ptr::null() as _,
glyph_bounds.size.width.0 as u32,
&mut bitmap_data,