use ifc_lite_core::{DecodedEntity, EntityDecoder, IfcType};
pub(crate) fn extract_color_from_fill_area_style(
style: &DecodedEntity,
decoder: &mut EntityDecoder,
) -> Option<[f32; 4]> {
for fs_ref in style.get_refs(1)? {
let Ok(fs) = decoder.decode_by_id(fs_ref) else {
continue;
};
if fs.ifc_type == IfcType::IfcColourRgb {
if let (Some(r), Some(g), Some(b)) = (
fs.get(1).and_then(|v| v.as_float()),
fs.get(2).and_then(|v| v.as_float()),
fs.get(3).and_then(|v| v.as_float()),
) {
return Some([r as f32, g as f32, b as f32, 1.0]);
}
}
}
None
}
pub(crate) fn fill_style_from_styled_item(
styled: &DecodedEntity,
decoder: &mut EntityDecoder,
) -> Option<super::GeometryStyleInfo> {
let item = decoder.decode_by_id(styled.get_ref(0)?).ok()?;
if item.ifc_type != IfcType::IfcAnnotationFillArea {
return None;
}
let refs = styled.get_refs(1)?;
if refs.len() > 64 {
return None;
}
for style_ref in refs {
let Ok(style) = decoder.decode_by_id(style_ref) else { continue };
if decoder.get_raw_bytes(style.id).and_then(|raw| {
ifc_lite_core::EntityScanner::new(raw)
.next_entity()
.map(|(_, name, _, _)| ifc_lite_core::keyword_eq(name, "IFCPRESENTATIONSTYLEASSIGNMENT"))
}) == Some(true)
{
let Some(inner) = style.get_refs(0) else { continue };
if inner.len() > 64 {
return None;
}
for fill_ref in inner {
let Ok(fill) = decoder.decode_by_id(fill_ref) else { continue };
if let Some(info) = fill_info(&fill, decoder) {
return Some(info);
}
}
} else if let Some(info) = fill_info(&style, decoder) {
return Some(info);
}
}
None
}
fn fill_info(
style: &DecodedEntity,
decoder: &mut EntityDecoder,
) -> Option<super::GeometryStyleInfo> {
if style.ifc_type != IfcType::IfcFillAreaStyle {
return None;
}
Some(super::GeometryStyleInfo {
color: extract_color_from_fill_area_style(style, decoder)?,
shading_color: None,
material_name: style
.get_string(0)
.filter(|s| !s.trim().is_empty())
.map(str::to_owned),
})
}