fix(color): only colour 7 swaps with the background; true colours draw as authored

Every near-white colour turned black on a light background (and near-black
white on a dark one), including true colours. A 255,255,255 solid used as a
white mask became a black block. Now only colour 7 swaps: true colours and
ACI 255 resolve a hair off pure white/black and keep their value on screen
and in plots.

Discussion #1500

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 5.5 committed 2026-09-29 06:16:18 +03:00
1 parent ac2a1e1166
commit 60f35e2b1d
7 files changed
+83 -30

No files matched your search

+8 -4
View File
@@ -794,10 +794,14 @@ fn tessellate_entity_inner(
a,
),
ProxyColor::Rgb(r, g, b) => (
view::render::adapt_to_bg(
[r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0, 1.0],
bg_color,
),
{
let [r, g, b] = convert::tess_util::authored_rgb([
r as f32 / 255.0,
g as f32 / 255.0,
b as f32 / 255.0,
]);
[r, g, b, 1.0]
},
0,
),
ProxyColor::Inherit => (entity_color, aci),
+29 -1
View File
@@ -31,8 +31,36 @@ pub type FallbackGeometry = (
/// Convert an opencadcodec Color (ACI index or true-color) to a GPU RGBA value.
pub fn aci_to_rgba(color: &AcadColor) -> [f32; 4] {
if let Some((r, g, b)) = color.rgb() {
[r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0, 1.0]
let rgb = [r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0];
// Only colour 7 swaps white/black with the background; any other
// colour — a true colour, or ACI 255 — is drawn as authored.
let [r, g, b] = if matches!(color, AcadColor::Index(7)) {
rgb
} else {
authored_rgb(rgb)
};
[r, g, b, 1.0]
} else {
WireModel::WHITE
}
}
/// Pure white and pure black are what the background adaptation swaps, and
/// only colour 7 may be swapped. A colour chosen as-is (255,255,255 used as a
/// white mask on a light sheet, say) is kept a hair off them so it is drawn
/// exactly as authored; the difference is below one display step.
pub fn authored_rgb(rgb: [f32; 3]) -> [f32; 3] {
const OFF: f32 = 1.0 / 1024.0;
if rgb == [1.0; 3] {
[1.0 - OFF; 3]
} else if rgb == [0.0; 3] {
[OFF; 3]
} else {
rgb
}
}
/// True for a colour [`authored_rgb`] moved off pure white.
pub fn is_authored_white(rgb: [f32; 3]) -> bool {
rgb == authored_rgb([1.0; 3])
}
+4 -6
View File
@@ -2868,12 +2868,10 @@ impl DimGeom {
/// `ByLayer` / `ByBlock` (assumes those are already resolved upstream).
pub(crate) fn color_or_inherit(c: &AcadColor, inherited: [f32; 4]) -> [f32; 4] {
match c.rgb() {
Some((r, g, b)) => [
r as f32 / 255.0,
g as f32 / 255.0,
b as f32 / 255.0,
inherited[3],
],
Some(_) => {
let [r, g, b, _] = crate::scene::convert::tess_util::aci_to_rgba(c);
[r, g, b, inherited[3]]
}
None => inherited,
}
}