using System; namespace codelanguage; public readonly record struct ScreenPixelPosition(double X, double Y); public static class ScreenLocLayout { public static bool TryResolve(string? screenLoc, double viewportWidth, double viewportHeight, double tileSize, out ScreenPixelPosition position) { if (ScreenLocParser.TryParse(screenLoc, out var parsed)) { position = Resolve(parsed, viewportWidth, viewportHeight, tileSize); return true; } position = default; return false; } public static ScreenPixelPosition Resolve(ScreenLocPosition location, double viewportWidth, double viewportHeight, double tileSize) { var width = Math.Max(0, viewportWidth); var height = Math.Max(0, viewportHeight); var x = ResolveAxis(location.XAnchor, location.XOffset, width, tileSize, horizontal: true); var y = ResolveAxis(location.YAnchor, location.YOffset, height, tileSize, horizontal: false); return new ScreenPixelPosition(x + location.XPixelOffset, y + location.YPixelOffset); } private static double ResolveAxis(string anchor, double offset, double extent, double tile, bool horizontal) { if (anchor == "NUMERIC") return Math.Max(0, offset * tile); if (anchor == "CENTER" || anchor == "MIDDLE") return extent / 2 + offset * tile; if (anchor.EndsWith("_PERCENT", StringComparison.Ordinal)) return extent * offset / 100.0; if (anchor.StartsWith("SCREEN_", StringComparison.Ordinal)) anchor = anchor[7..]; bool positive = anchor is "RIGHT" or "TOP" or "EAST" or "NORTH" or "NORTHEAST" or "NORTHWEST"; bool edge = anchor is "LEFT" or "RIGHT" or "TOP" or "BOTTOM"; if (horizontal) { if (anchor.Contains("EAST", StringComparison.Ordinal) || anchor == "RIGHT") return extent + offset * tile; if (anchor.Contains("WEST", StringComparison.Ordinal) || anchor == "LEFT") return offset * tile; } else { if (anchor.Contains("NORTH", StringComparison.Ordinal) || anchor == "TOP") return extent + offset * tile; if (anchor.Contains("SOUTH", StringComparison.Ordinal) || anchor == "BOTTOM") return offset * tile; } return (positive || edge) ? extent + offset * tile : offset * tile; } }