use std::collections::HashMap;
use std::sync::{ Arc, OnceLock };
use fontdue::{ Font, FontSettings, LineMetrics, Metrics };
use glow::HasContext;
use crate::theme::{ FontRegistry, FontStyle };
use super::helpers::{ alloc_fbo_tex, bytemuck_cast_slice, compile_program, compile_program_with_attribs, load_default_font_bytes };
use super::shaders::
{
BACKDROP_BLUR_H_FRAG_SRC, BACKDROP_COMPOSITE_FRAG_SRC,
BACKDROP_FAST_BLUR_H_FRAG_SRC, BACKDROP_FAST_COMPOSITE_FRAG_SRC,
BLIT_FRAG_SRC, BLIT_VERT_SRC,
GLYPH_FRAG_SRC, GLYPH_BATCH_VERT_SRC, GLYPH_BATCH_FRAG_SRC,
LINEAR_GRADIENT_FRAG_SRC, RADIAL_GRADIENT_FRAG_SRC,
RECT_FRAG_SRC,
SHADOW_INSET_FRAG_SRC, SHADOW_INSET_OVERLAY_FRAG_SRC, SHADOW_OUTER_FRAG_SRC,
SUB_BLIT_FRAG_SRC,
TEX_FRAG_SRC, VERT_SRC,
};
use super::{ GlesCanvas, GlesVersion };
static DEFAULT_FONT_GLES: OnceLock<crate::system_fonts::FontHandle> = OnceLock::new();
fn default_handle_gles() -> crate::system_fonts::FontHandle
{
DEFAULT_FONT_GLES.get_or_init( ||
{
let bytes = load_default_font_bytes();
let font = Font::from_bytes( bytes.as_slice(), FontSettings::default() )
.expect( "bad font" );
crate::system_fonts::FontHandle
{
font: Arc::new( font ),
bytes: Arc::new( bytes ),
face: 0,
}
} ).clone()
}
impl GlesCanvas
{
pub fn new( gl: Arc<glow::Context>, version: GlesVersion, width: u32, height: u32 ) -> Self
{
let font_handle = default_handle_gles();
let font = font_handle.font.clone();
let font_bytes = font_handle.bytes.clone();
let font_face = font_handle.face;
let rect_program = compile_program( &gl, VERT_SRC, RECT_FRAG_SRC );
let tex_program = compile_program( &gl, VERT_SRC, TEX_FRAG_SRC );
let glyph_program = compile_program( &gl, VERT_SRC, GLYPH_FRAG_SRC );
let glyph_batch_program = compile_program_with_attribs( &gl, GLYPH_BATCH_VERT_SRC, GLYPH_BATCH_FRAG_SRC, &[ ( 0, "a_pos" ), ( 1, "a_uv" ) ] );
let blit_program = compile_program( &gl, BLIT_VERT_SRC, BLIT_FRAG_SRC );
let sub_blit_program = compile_program( &gl, VERT_SRC, SUB_BLIT_FRAG_SRC );
let linear_gradient_program = compile_program( &gl, VERT_SRC, LINEAR_GRADIENT_FRAG_SRC );
let radial_gradient_program = compile_program( &gl, VERT_SRC, RADIAL_GRADIENT_FRAG_SRC );
let shadow_outer_program = compile_program( &gl, VERT_SRC, SHADOW_OUTER_FRAG_SRC );
let shadow_inset_program = compile_program( &gl, VERT_SRC, SHADOW_INSET_FRAG_SRC );
let shadow_inset_overlay_program = compile_program( &gl, VERT_SRC, SHADOW_INSET_OVERLAY_FRAG_SRC );
let backdrop_blur_h_program = compile_program( &gl, BLIT_VERT_SRC, BACKDROP_BLUR_H_FRAG_SRC );
let backdrop_composite_program = compile_program( &gl, VERT_SRC, BACKDROP_COMPOSITE_FRAG_SRC );
let backdrop_fast_blur_h_program = compile_program( &gl, BLIT_VERT_SRC, BACKDROP_FAST_BLUR_H_FRAG_SRC );
let backdrop_fast_composite_program = compile_program( &gl, VERT_SRC, BACKDROP_FAST_COMPOSITE_FRAG_SRC );
let (
u_rect_mvp, u_rect_color, u_rect_size, u_rect_radii, u_rect_stroke, u_rect_pad,
u_tex_mvp, u_tex_opacity, u_tex_sampler,
u_glyph_mvp, u_glyph_color, u_glyph_opacity, u_glyph_sampler,
u_glyph_uv_offset, u_glyph_uv_scale,
u_blit_sampler,
u_subblit_mvp, u_subblit_sampler, u_subblit_opacity, u_subblit_fade_bottom, u_subblit_height_px,
u_lingrad_mvp, u_lingrad_lut, u_lingrad_dir, u_lingrad_size, u_lingrad_line_length,
u_lingrad_radii, u_lingrad_pad, u_lingrad_lut_domain_min, u_lingrad_lut_domain_span,
u_radgrad_mvp, u_radgrad_lut, u_radgrad_center, u_radgrad_radius_frac, u_radgrad_size,
u_radgrad_radii, u_radgrad_pad, u_radgrad_lut_domain_min, u_radgrad_lut_domain_span,
u_shadow_mvp, u_shadow_size, u_shadow_padding, u_shadow_radii, u_shadow_spread, u_shadow_sigma, u_shadow_color,
u_inset_mvp, u_inset_size, u_inset_padding, u_inset_radii, u_inset_spread, u_inset_sigma, u_inset_offset, u_inset_color,
u_inset_ov_mvp, u_inset_ov_size, u_inset_ov_padding, u_inset_ov_radii,
u_inset_ov_spread, u_inset_ov_sigma, u_inset_ov_offset, u_inset_ov_color,
u_inset_ov_snapshot, u_inset_ov_canvas_size,
u_bd_h_source, u_bd_h_texel, u_bd_h_canvas_size, u_bd_h_sigma,
u_bd_c_mvp, u_bd_c_source, u_bd_c_canvas_size, u_bd_c_texel, u_bd_c_sigma,
u_bd_c_size, u_bd_c_padding, u_bd_c_radii, u_bd_c_tint,
u_bd_fh_source, u_bd_fh_texel, u_bd_fh_canvas_size, u_bd_fh_sigma,
u_bd_fc_mvp, u_bd_fc_source, u_bd_fc_canvas_size, u_bd_fc_texel, u_bd_fc_sigma,
u_bd_fc_size, u_bd_fc_padding, u_bd_fc_radii, u_bd_fc_tint,
) = unsafe
{(
gl.get_uniform_location( rect_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( rect_program, "u_color" ).unwrap(),
gl.get_uniform_location( rect_program, "u_size" ).unwrap(),
gl.get_uniform_location( rect_program, "u_radii" ).unwrap(),
gl.get_uniform_location( rect_program, "u_stroke" ).unwrap(),
gl.get_uniform_location( rect_program, "u_pad" ).unwrap(),
gl.get_uniform_location( tex_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( tex_program, "u_opacity" ).unwrap(),
gl.get_uniform_location( tex_program, "u_sampler" ).unwrap(),
gl.get_uniform_location( glyph_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( glyph_program, "u_color" ).unwrap(),
gl.get_uniform_location( glyph_program, "u_opacity" ).unwrap(),
gl.get_uniform_location( glyph_program, "u_sampler" ).unwrap(),
gl.get_uniform_location( glyph_program, "u_uv_offset" ).unwrap(),
gl.get_uniform_location( glyph_program, "u_uv_scale" ).unwrap(),
gl.get_uniform_location( blit_program, "u_sampler" ).unwrap(),
gl.get_uniform_location( sub_blit_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( sub_blit_program, "u_sampler" ).unwrap(),
gl.get_uniform_location( sub_blit_program, "u_opacity" ).unwrap(),
gl.get_uniform_location( sub_blit_program, "u_fade_bottom_px" ).unwrap(),
gl.get_uniform_location( sub_blit_program, "u_height_px" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_lut" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_dir" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_size" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_line_length" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_radii" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_pad" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_lut_domain_min" ).unwrap(),
gl.get_uniform_location( linear_gradient_program, "u_lut_domain_span" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_lut" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_center" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_radius_frac" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_size" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_radii" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_pad" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_lut_domain_min" ).unwrap(),
gl.get_uniform_location( radial_gradient_program, "u_lut_domain_span" ).unwrap(),
gl.get_uniform_location( shadow_outer_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( shadow_outer_program, "u_size" ).unwrap(),
gl.get_uniform_location( shadow_outer_program, "u_padding" ).unwrap(),
gl.get_uniform_location( shadow_outer_program, "u_radii" ).unwrap(),
gl.get_uniform_location( shadow_outer_program, "u_spread" ).unwrap(),
gl.get_uniform_location( shadow_outer_program, "u_sigma" ).unwrap(),
gl.get_uniform_location( shadow_outer_program, "u_color" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_size" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_padding" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_radii" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_spread" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_sigma" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_offset" ).unwrap(),
gl.get_uniform_location( shadow_inset_program, "u_color" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_size" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_padding" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_radii" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_spread" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_sigma" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_offset" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_color" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_snapshot" ).unwrap(),
gl.get_uniform_location( shadow_inset_overlay_program, "u_canvas_size" ).unwrap(),
gl.get_uniform_location( backdrop_blur_h_program, "u_source" ).unwrap(),
gl.get_uniform_location( backdrop_blur_h_program, "u_texel" ).unwrap(),
gl.get_uniform_location( backdrop_blur_h_program, "u_canvas_size" ).unwrap(),
gl.get_uniform_location( backdrop_blur_h_program, "u_sigma" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_source" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_canvas_size" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_texel" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_sigma" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_size" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_padding" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_radii" ).unwrap(),
gl.get_uniform_location( backdrop_composite_program, "u_tint" ).unwrap(),
gl.get_uniform_location( backdrop_fast_blur_h_program, "u_source" ).unwrap(),
gl.get_uniform_location( backdrop_fast_blur_h_program, "u_texel" ).unwrap(),
gl.get_uniform_location( backdrop_fast_blur_h_program, "u_canvas_size" ).unwrap(),
gl.get_uniform_location( backdrop_fast_blur_h_program, "u_sigma" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_mvp" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_source" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_canvas_size" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_texel" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_sigma" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_size" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_padding" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_radii" ).unwrap(),
gl.get_uniform_location( backdrop_fast_composite_program, "u_tint" ).unwrap(),
)};
let ( u_glyph_batch_color, u_glyph_batch_opacity, u_glyph_batch_sampler ) = unsafe
{(
gl.get_uniform_location( glyph_batch_program, "u_color" ).unwrap(),
gl.get_uniform_location( glyph_batch_program, "u_opacity" ).unwrap(),
gl.get_uniform_location( glyph_batch_program, "u_sampler" ).unwrap(),
)};
let ( glyph_batch_vao, glyph_batch_vbo ) = unsafe
{
let vao = gl.create_vertex_array().unwrap();
let vbo = gl.create_buffer().unwrap();
gl.bind_vertex_array( Some( vao ) );
gl.bind_buffer( glow::ARRAY_BUFFER, Some( vbo ) );
gl.enable_vertex_attrib_array( 0 );
gl.vertex_attrib_pointer_f32( 0, 2, glow::FLOAT, false, 16, 0 );
gl.enable_vertex_attrib_array( 1 );
gl.vertex_attrib_pointer_f32( 1, 2, glow::FLOAT, false, 16, 8 );
gl.bind_vertex_array( None );
( vao, vbo )
};
let quad_vertices: [f32; 12] = [
0.0, 0.0, 1.0, 0.0, 0.0, 1.0,
1.0, 0.0, 1.0, 1.0, 0.0, 1.0,
];
let ( quad_vao, quad_vbo ) = unsafe
{
let vao = gl.create_vertex_array().unwrap();
let vbo = gl.create_buffer().unwrap();
gl.bind_vertex_array( Some( vao ) );
gl.bind_buffer( glow::ARRAY_BUFFER, Some( vbo ) );
gl.buffer_data_u8_slice(
glow::ARRAY_BUFFER,
bytemuck_cast_slice( &quad_vertices ),
glow::STATIC_DRAW,
);
gl.enable_vertex_attrib_array( 0 );
gl.vertex_attrib_pointer_f32( 0, 2, glow::FLOAT, false, 8, 0 );
gl.bind_vertex_array( None );
( vao, vbo )
};
let ( fbo, fbo_tex ) = unsafe
{
let fbo = gl.create_framebuffer().expect( "create_framebuffer" );
let fbo_tex = alloc_fbo_tex( &gl, version, width, height );
gl.bind_framebuffer( glow::FRAMEBUFFER, Some( fbo ) );
gl.framebuffer_texture_2d(
glow::FRAMEBUFFER, glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D, Some( fbo_tex ), 0,
);
let status = gl.check_framebuffer_status( glow::FRAMEBUFFER );
assert_eq!( status, glow::FRAMEBUFFER_COMPLETE, "FBO incomplete: 0x{status:x}" );
gl.enable( glow::BLEND );
gl.blend_func( glow::ONE, glow::ONE_MINUS_SRC_ALPHA );
gl.viewport( 0, 0, width as i32, height as i32 );
gl.clear_color( 0.0, 0.0, 0.0, 0.0 );
gl.clear( glow::COLOR_BUFFER_BIT );
( fbo, fbo_tex )
};
let ( atlas_internal, atlas_format ) = match version
{
GlesVersion::V3 => ( glow::R8 as i32, glow::RED ),
GlesVersion::V2 => ( glow::LUMINANCE as i32, glow::LUMINANCE ),
};
let atlas_texture = unsafe
{
let tex = gl.create_texture().unwrap();
gl.bind_texture( glow::TEXTURE_2D, Some( tex ) );
gl.pixel_store_i32( glow::UNPACK_ALIGNMENT, 1 );
gl.tex_image_2d(
glow::TEXTURE_2D, 0, atlas_internal,
super::ATLAS_SIZE as i32, super::ATLAS_SIZE as i32, 0,
atlas_format, glow::UNSIGNED_BYTE,
glow::PixelUnpackData::Slice( None ),
);
gl.pixel_store_i32( glow::UNPACK_ALIGNMENT, 4 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::NEAREST as i32 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::CLAMP_TO_EDGE as i32 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::CLAMP_TO_EDGE as i32 );
gl.bind_texture( glow::TEXTURE_2D, None );
tex
};
Self
{
gl,
version,
font,
font_bytes,
font_face,
font_registry: None,
dpi_scale: 1.0,
global_alpha: 1.0,
width,
height,
rect_program,
tex_program,
glyph_program,
blit_program,
sub_blit_program,
linear_gradient_program,
radial_gradient_program,
shadow_outer_program,
shadow_inset_program,
shadow_inset_overlay_program,
quad_vao,
_quad_vbo: quad_vbo,
u_rect_mvp,
u_rect_color,
u_rect_size,
u_rect_radii,
u_rect_stroke,
u_rect_pad,
u_tex_mvp,
u_tex_opacity,
u_tex_sampler,
u_glyph_mvp,
u_glyph_color,
u_glyph_opacity,
u_glyph_sampler,
u_glyph_uv_offset,
u_glyph_uv_scale,
glyph_batch_program,
u_glyph_batch_color,
u_glyph_batch_opacity,
u_glyph_batch_sampler,
glyph_batch_vao,
glyph_batch_vbo,
u_blit_sampler,
u_subblit_mvp,
u_subblit_sampler,
u_subblit_opacity,
u_subblit_fade_bottom,
u_subblit_height_px,
u_lingrad_mvp,
u_lingrad_lut,
u_lingrad_dir,
u_lingrad_size,
u_lingrad_line_length,
u_lingrad_radii,
u_lingrad_pad,
u_lingrad_lut_domain_min,
u_lingrad_lut_domain_span,
u_radgrad_mvp,
u_radgrad_lut,
u_radgrad_center,
u_radgrad_radius_frac,
u_radgrad_size,
u_radgrad_radii,
u_radgrad_pad,
u_radgrad_lut_domain_min,
u_radgrad_lut_domain_span,
u_shadow_mvp,
u_shadow_size,
u_shadow_padding,
u_shadow_radii,
u_shadow_spread,
u_shadow_sigma,
u_shadow_color,
u_inset_mvp,
u_inset_size,
u_inset_padding,
u_inset_radii,
u_inset_spread,
u_inset_sigma,
u_inset_offset,
u_inset_color,
u_inset_ov_mvp,
u_inset_ov_size,
u_inset_ov_padding,
u_inset_ov_radii,
u_inset_ov_spread,
u_inset_ov_sigma,
u_inset_ov_offset,
u_inset_ov_color,
u_inset_ov_snapshot,
u_inset_ov_canvas_size,
backdrop_blur_h_program,
u_bd_h_source,
u_bd_h_texel,
u_bd_h_canvas_size,
u_bd_h_sigma,
backdrop_composite_program,
u_bd_c_mvp,
u_bd_c_source,
u_bd_c_canvas_size,
u_bd_c_texel,
u_bd_c_sigma,
u_bd_c_size,
u_bd_c_padding,
u_bd_c_radii,
u_bd_c_tint,
backdrop_fast_blur_h_program,
u_bd_fh_source,
u_bd_fh_texel,
u_bd_fh_canvas_size,
u_bd_fh_sigma,
backdrop_fast_composite_program,
u_bd_fc_mvp,
u_bd_fc_source,
u_bd_fc_canvas_size,
u_bd_fc_texel,
u_bd_fc_sigma,
u_bd_fc_size,
u_bd_fc_padding,
u_bd_fc_radii,
u_bd_fc_tint,
atlas_texture,
atlas_format,
atlas_cursor_x: 0,
atlas_cursor_y: 0,
atlas_row_height: 0,
glyph_cache: HashMap::new(),
image_cache: HashMap::new(),
gradient_lut_cache: HashMap::new(),
clip_scissor: None,
fbo,
fbo_tex,
aux_a: None,
aux_b: None,
}
}
pub fn sub_canvas( &self, width: u32, height: u32 ) -> GlesCanvas
{
let gl = Arc::clone( &self.gl );
let ( fbo, fbo_tex ) = unsafe
{
let fbo = gl.create_framebuffer().expect( "create_framebuffer" );
let fbo_tex = alloc_fbo_tex( &gl, self.version, width, height );
gl.bind_framebuffer( glow::FRAMEBUFFER, Some( fbo ) );
gl.framebuffer_texture_2d(
glow::FRAMEBUFFER, glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D, Some( fbo_tex ), 0,
);
let status = gl.check_framebuffer_status( glow::FRAMEBUFFER );
assert_eq!( status, glow::FRAMEBUFFER_COMPLETE, "sub-FBO incomplete: 0x{status:x}" );
( fbo, fbo_tex )
};
let atlas_format = self.atlas_format;
let atlas_internal = match self.version
{
GlesVersion::V3 => glow::R8 as i32,
GlesVersion::V2 => glow::LUMINANCE as i32,
};
let atlas_texture = unsafe
{
let tex = gl.create_texture().unwrap();
gl.bind_texture( glow::TEXTURE_2D, Some( tex ) );
gl.pixel_store_i32( glow::UNPACK_ALIGNMENT, 1 );
gl.tex_image_2d(
glow::TEXTURE_2D, 0, atlas_internal,
super::ATLAS_SIZE as i32, super::ATLAS_SIZE as i32, 0,
atlas_format, glow::UNSIGNED_BYTE,
glow::PixelUnpackData::Slice( None ),
);
gl.pixel_store_i32( glow::UNPACK_ALIGNMENT, 4 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::NEAREST as i32 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::CLAMP_TO_EDGE as i32 );
gl.tex_parameter_i32( glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::CLAMP_TO_EDGE as i32 );
gl.bind_texture( glow::TEXTURE_2D, None );
tex
};
GlesCanvas
{
gl,
version: self.version,
font: Arc::clone( &self.font ),
font_bytes: Arc::clone( &self.font_bytes ),
font_face: self.font_face,
font_registry: self.font_registry.as_ref().map( Arc::clone ),
dpi_scale: self.dpi_scale,
global_alpha: self.global_alpha,
width,
height,
rect_program: self.rect_program,
tex_program: self.tex_program,
glyph_program: self.glyph_program,
blit_program: self.blit_program,
sub_blit_program: self.sub_blit_program,
linear_gradient_program: self.linear_gradient_program,
radial_gradient_program: self.radial_gradient_program,
shadow_outer_program: self.shadow_outer_program,
shadow_inset_program: self.shadow_inset_program,
shadow_inset_overlay_program: self.shadow_inset_overlay_program,
backdrop_blur_h_program: self.backdrop_blur_h_program,
backdrop_composite_program: self.backdrop_composite_program,
backdrop_fast_blur_h_program: self.backdrop_fast_blur_h_program,
backdrop_fast_composite_program: self.backdrop_fast_composite_program,
quad_vao: self.quad_vao,
_quad_vbo: self._quad_vbo,
u_rect_mvp: self.u_rect_mvp,
u_rect_color: self.u_rect_color,
u_rect_size: self.u_rect_size,
u_rect_radii: self.u_rect_radii,
u_rect_stroke: self.u_rect_stroke,
u_rect_pad: self.u_rect_pad,
u_tex_mvp: self.u_tex_mvp,
u_tex_opacity: self.u_tex_opacity,
u_tex_sampler: self.u_tex_sampler,
u_glyph_mvp: self.u_glyph_mvp,
u_glyph_color: self.u_glyph_color,
u_glyph_opacity: self.u_glyph_opacity,
u_glyph_sampler: self.u_glyph_sampler,
u_glyph_uv_offset: self.u_glyph_uv_offset,
u_glyph_uv_scale: self.u_glyph_uv_scale,
glyph_batch_program: self.glyph_batch_program,
u_glyph_batch_color: self.u_glyph_batch_color,
u_glyph_batch_opacity: self.u_glyph_batch_opacity,
u_glyph_batch_sampler: self.u_glyph_batch_sampler,
glyph_batch_vao: self.glyph_batch_vao,
glyph_batch_vbo: self.glyph_batch_vbo,
u_blit_sampler: self.u_blit_sampler,
u_subblit_mvp: self.u_subblit_mvp,
u_subblit_sampler: self.u_subblit_sampler,
u_subblit_opacity: self.u_subblit_opacity,
u_subblit_fade_bottom: self.u_subblit_fade_bottom,
u_subblit_height_px: self.u_subblit_height_px,
u_lingrad_mvp: self.u_lingrad_mvp,
u_lingrad_lut: self.u_lingrad_lut,
u_lingrad_dir: self.u_lingrad_dir,
u_lingrad_size: self.u_lingrad_size,
u_lingrad_line_length: self.u_lingrad_line_length,
u_lingrad_radii: self.u_lingrad_radii,
u_lingrad_pad: self.u_lingrad_pad,
u_lingrad_lut_domain_min: self.u_lingrad_lut_domain_min,
u_lingrad_lut_domain_span: self.u_lingrad_lut_domain_span,
u_radgrad_mvp: self.u_radgrad_mvp,
u_radgrad_lut: self.u_radgrad_lut,
u_radgrad_center: self.u_radgrad_center,
u_radgrad_radius_frac: self.u_radgrad_radius_frac,
u_radgrad_size: self.u_radgrad_size,
u_radgrad_radii: self.u_radgrad_radii,
u_radgrad_pad: self.u_radgrad_pad,
u_radgrad_lut_domain_min: self.u_radgrad_lut_domain_min,
u_radgrad_lut_domain_span: self.u_radgrad_lut_domain_span,
u_shadow_mvp: self.u_shadow_mvp,
u_shadow_size: self.u_shadow_size,
u_shadow_padding: self.u_shadow_padding,
u_shadow_radii: self.u_shadow_radii,
u_shadow_spread: self.u_shadow_spread,
u_shadow_sigma: self.u_shadow_sigma,
u_shadow_color: self.u_shadow_color,
u_inset_mvp: self.u_inset_mvp,
u_inset_size: self.u_inset_size,
u_inset_padding: self.u_inset_padding,
u_inset_radii: self.u_inset_radii,
u_inset_spread: self.u_inset_spread,
u_inset_sigma: self.u_inset_sigma,
u_inset_offset: self.u_inset_offset,
u_inset_color: self.u_inset_color,
u_inset_ov_mvp: self.u_inset_ov_mvp,
u_inset_ov_size: self.u_inset_ov_size,
u_inset_ov_padding: self.u_inset_ov_padding,
u_inset_ov_radii: self.u_inset_ov_radii,
u_inset_ov_spread: self.u_inset_ov_spread,
u_inset_ov_sigma: self.u_inset_ov_sigma,
u_inset_ov_offset: self.u_inset_ov_offset,
u_inset_ov_color: self.u_inset_ov_color,
u_inset_ov_snapshot: self.u_inset_ov_snapshot,
u_inset_ov_canvas_size: self.u_inset_ov_canvas_size,
u_bd_h_source: self.u_bd_h_source,
u_bd_h_texel: self.u_bd_h_texel,
u_bd_h_canvas_size: self.u_bd_h_canvas_size,
u_bd_h_sigma: self.u_bd_h_sigma,
u_bd_c_mvp: self.u_bd_c_mvp,
u_bd_c_source: self.u_bd_c_source,
u_bd_c_canvas_size: self.u_bd_c_canvas_size,
u_bd_c_texel: self.u_bd_c_texel,
u_bd_c_sigma: self.u_bd_c_sigma,
u_bd_c_size: self.u_bd_c_size,
u_bd_c_padding: self.u_bd_c_padding,
u_bd_c_radii: self.u_bd_c_radii,
u_bd_c_tint: self.u_bd_c_tint,
u_bd_fh_source: self.u_bd_fh_source,
u_bd_fh_texel: self.u_bd_fh_texel,
u_bd_fh_canvas_size: self.u_bd_fh_canvas_size,
u_bd_fh_sigma: self.u_bd_fh_sigma,
u_bd_fc_mvp: self.u_bd_fc_mvp,
u_bd_fc_source: self.u_bd_fc_source,
u_bd_fc_canvas_size: self.u_bd_fc_canvas_size,
u_bd_fc_texel: self.u_bd_fc_texel,
u_bd_fc_sigma: self.u_bd_fc_sigma,
u_bd_fc_size: self.u_bd_fc_size,
u_bd_fc_padding: self.u_bd_fc_padding,
u_bd_fc_radii: self.u_bd_fc_radii,
u_bd_fc_tint: self.u_bd_fc_tint,
atlas_texture,
atlas_format,
atlas_cursor_x: 0,
atlas_cursor_y: 0,
atlas_row_height: 0,
glyph_cache: HashMap::new(),
image_cache: HashMap::new(),
gradient_lut_cache: HashMap::new(),
clip_scissor: None,
fbo,
fbo_tex,
aux_a: None,
aux_b: None,
}
}
pub fn size( &self ) -> ( u32, u32 ) { ( self.width, self.height ) }
pub fn clear_gradient_cache( &mut self )
{
unsafe
{
for ( _, tex ) in self.gradient_lut_cache.drain()
{
self.gl.delete_texture( tex );
}
}
}
pub fn dpi_scale( &self ) -> f32 { self.dpi_scale }
pub fn set_dpi_scale( &mut self, s: f32 ) { self.dpi_scale = s; }
pub fn global_alpha( &self ) -> f32 { self.global_alpha }
pub fn set_global_alpha( &mut self, a: f32 ) { self.global_alpha = a; }
pub fn font( &self ) -> &Font { &self.font }
pub fn set_font_registry( &mut self, registry: Arc<FontRegistry> )
{
self.font_registry = Some( registry );
}
pub fn font_for( &self, family: &str, weight: u16, style: FontStyle ) -> Arc<Font>
{
self.font_registry
.as_ref()
.and_then( |r| r.resolve( family, weight, style ) )
.unwrap_or_else( || Arc::clone( &self.font ) )
}
pub fn font_for_char( &self, ch: char ) -> Arc<Font>
{
if self.font.lookup_glyph_index( ch ) != 0
{
return Arc::clone( &self.font );
}
crate::system_fonts::lookup( ch ).unwrap_or_else( || Arc::clone( &self.font ) )
}
pub fn font_metrics( &self, ch: char, size: f32 ) -> Metrics
{
self.font_for_char( ch ).metrics( ch, size * self.dpi_scale )
}
pub fn font_line_metrics( &self, size: f32 ) -> Option<LineMetrics>
{
self.font.horizontal_line_metrics( size )
}
pub fn resize( &mut self, width: u32, height: u32 )
{
if width == self.width && height == self.height { return; }
self.width = width;
self.height = height;
unsafe
{
self.gl.delete_texture( self.fbo_tex );
self.fbo_tex = alloc_fbo_tex( &self.gl, self.version, width, height );
self.gl.bind_framebuffer( glow::FRAMEBUFFER, Some( self.fbo ) );
self.gl.framebuffer_texture_2d(
glow::FRAMEBUFFER, glow::COLOR_ATTACHMENT0,
glow::TEXTURE_2D, Some( self.fbo_tex ), 0,
);
self.gl.viewport( 0, 0, width as i32, height as i32 );
self.gl.clear_color( 0.0, 0.0, 0.0, 0.0 );
self.gl.clear( glow::COLOR_BUFFER_BIT );
}
self.invalidate_aux();
}
}