use api::{ExtendMode, GradientStop};
use api::units::*;
use crate::pattern::gradient::{conic_gradient_pattern};
use crate::pattern::{Pattern, PatternBuilder, PatternBuilderContext, PatternBuilderState};
use crate::scene_building::IsVisible;
use crate::intern::{Internable, InternDebug, Handle as InternHandle};
use crate::internal_types::LayoutPrimitiveInfo;
use crate::prim_store::{PrimitiveKind, PrimitiveOpacity};
use crate::prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
use crate::prim_store::{NinePatchDescriptor, PointKey, SizeKey, InternablePrimitive};
use std::{hash, ops::{Deref, DerefMut}};
use super::{stops_and_min_alpha, GradientStopKey};
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
pub struct ConicGradientParams {
pub angle: f32, pub start_offset: f32,
pub end_offset: f32,
}
impl Eq for ConicGradientParams {}
impl hash::Hash for ConicGradientParams {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.angle.to_bits().hash(state);
self.start_offset.to_bits().hash(state);
self.end_offset.to_bits().hash(state);
}
}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Debug, Clone, Eq, PartialEq, Hash, MallocSizeOf)]
pub struct ConicGradientKey {
pub common: PrimKeyCommonData,
pub extend_mode: ExtendMode,
pub center: PointKey,
pub params: ConicGradientParams,
pub stretch_ratio: SizeKey,
pub stops: Vec<GradientStopKey>,
pub tile_spacing: SizeKey,
pub nine_patch: Option<Box<NinePatchDescriptor>>,
}
impl ConicGradientKey {
pub fn new(
info: &LayoutPrimitiveInfo,
conic_grad: ConicGradient,
) -> Self {
ConicGradientKey {
common: info.into(),
extend_mode: conic_grad.extend_mode,
center: conic_grad.center,
params: conic_grad.params,
stretch_ratio: conic_grad.stretch_ratio,
stops: conic_grad.stops,
tile_spacing: conic_grad.tile_spacing,
nine_patch: conic_grad.nine_patch,
}
}
}
impl InternDebug for ConicGradientKey {}
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(MallocSizeOf)]
pub struct ConicGradientTemplate {
pub common: PrimTemplateCommonData,
pub extend_mode: ExtendMode,
pub center: LayoutPoint,
pub params: ConicGradientParams,
pub stretch_ratio: LayoutSize,
pub tile_spacing: LayoutSize,
pub border_nine_patch: Option<Box<NinePatchDescriptor>>,
pub stops_opacity: PrimitiveOpacity,
pub stops: Vec<GradientStop>,
}
impl PatternBuilder for ConicGradientTemplate {
fn build(
&self,
_sub_rect: Option<DeviceRect>,
offset: LayoutVector2D,
ctx: &PatternBuilderContext,
state: &mut PatternBuilderState,
) -> Pattern {
let no_scale = DeviceVector2D::one();
let center = self.center + ctx.prim_origin.to_vector() + offset;
conic_gradient_pattern(
center,
no_scale,
self.params.angle,
self.params.start_offset,
self.params.end_offset,
self.extend_mode,
&self.stops,
state.frame_gpu_data,
)
}
}
impl Deref for ConicGradientTemplate {
type Target = PrimTemplateCommonData;
fn deref(&self) -> &Self::Target {
&self.common
}
}
impl DerefMut for ConicGradientTemplate {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.common
}
}
impl From<ConicGradientKey> for ConicGradientTemplate {
fn from(item: ConicGradientKey) -> Self {
let common = PrimTemplateCommonData::with_key_common(item.common);
let (stops, min_alpha) = stops_and_min_alpha(&item.stops);
let stops_opacity = PrimitiveOpacity::from_alpha(min_alpha);
ConicGradientTemplate {
common,
center: item.center.into(),
extend_mode: item.extend_mode,
params: item.params,
stretch_ratio: item.stretch_ratio.into(),
tile_spacing: item.tile_spacing.into(),
border_nine_patch: item.nine_patch,
stops_opacity,
stops,
}
}
}
pub type ConicGradientDataHandle = InternHandle<ConicGradient>;
#[derive(Debug, MallocSizeOf)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct ConicGradient {
pub extend_mode: ExtendMode,
pub center: PointKey,
pub params: ConicGradientParams,
pub stretch_ratio: SizeKey,
pub stops: Vec<GradientStopKey>,
pub tile_spacing: SizeKey,
pub nine_patch: Option<Box<NinePatchDescriptor>>,
}
impl Internable for ConicGradient {
type Key = ConicGradientKey;
type StoreData = ConicGradientTemplate;
type InternData = ();
const PROFILE_COUNTER: usize = crate::profiler::INTERNED_CONIC_GRADIENTS;
}
impl InternablePrimitive for ConicGradient {
fn into_key(
self,
info: &LayoutPrimitiveInfo,
) -> ConicGradientKey {
ConicGradientKey::new(info, self)
}
fn make_instance_kind(
_key: ConicGradientKey,
data_handle: ConicGradientDataHandle,
_prim_store: &mut PrimitiveStore,
) -> PrimitiveKind {
PrimitiveKind::ConicGradient {
data_handle,
}
}
}
impl IsVisible for ConicGradient {
fn is_visible(&self) -> bool {
true
}
}