{"record":{"id":"531d3e364015c1b6","repo":"dotnet/wpf","slug":"sr-glyphsadvancewidthcannotbenegative","errorCode":null,"errorMessage":"SR.GlyphsAdvanceWidthCannotBeNegative","messagePattern":"SR\\.GlyphsAdvanceWidthCannotBeNegative","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs","lineNumber":598,"sourceCode":"                                        {\n                                            SetClusterMapEntry(clusterMap, ch, (ushort)parsedGlyphCount);\n                                        }\n                                    }\n                                    else\n                                    {\n                                        SetClusterMapEntry(clusterMap, parsedCharacterCount, (ushort)parsedGlyphCount);\n                                    }\n                                }\n                                parsedGlyphData.advanceWidth = GetAdvanceWidth(fontFace, parsedGlyphData.glyphIndex, sideways);\n                                break;\n\n                            case 1:\n                                // interpret glyph advance spec\n                                if (!IsEmpty(valueSpec))\n                                {\n                                    parsedGlyphData.advanceWidth = double.Parse(valueSpec, provider: CultureInfo.InvariantCulture);\n                                    if (parsedGlyphData.advanceWidth < 0)\n                                        throw new ArgumentException(SR.GlyphsAdvanceWidthCannotBeNegative);\n                                }\n                                break;\n\n                            case 2:\n                                // interpret glyph offset X\n                                if (!IsEmpty(valueSpec))\n                                    parsedGlyphData.offsetX = double.Parse(valueSpec, provider: CultureInfo.InvariantCulture);\n                                break;\n\n                            case 3:\n                                // interpret glyph offset Y\n                                if (!IsEmpty(valueSpec))\n                                    parsedGlyphData.offsetY = double.Parse(valueSpec, provider: CultureInfo.InvariantCulture);\n                                break;\n\n                            default:\n                                // too many commas; can't interpret\n                                throw new ArgumentException(SR.GlyphsTooManyCommas);","sourceCodeStart":580,"sourceCodeEnd":616,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs#L580-L616","documentation":"Thrown by Glyphs.ParseGlyphsProperty when a glyph's advance-width component in the GlyphIndices string (the first comma-separated value after the index) parses to a negative double. Advance widths measure horizontal distance and must be zero or positive, so the parser rejects negatives with ArgumentException.","triggerScenarios":"A GlyphIndices entry with a negative second field, e.g. \";41,-5\" or \";(2:1),-1.5\"; also computed widths from code that produced NaN/negative values from failed measurements.","commonSituations":"Programmatic width computation returning negative values for invisible/zero-width characters; typo'd minus sign in hand-written XAML; exporting glyph metrics from another tool with sign conventions differing from WPF.","solutions":["Change the advance-width value to a non-negative number (use 0 for zero-advance glyphs).","Clamp computed widths with Math.Max(0, width) before formatting them into GlyphIndices.","If a negative-looking value is really an offset, move it to the offset X/Y fields (3rd/4th values) instead."],"exampleFix":"// before\nglyphs.GlyphIndices = \";41,-12.5\";\n// after\nglyphs.GlyphIndices = \";41,12.5\"; // or 0 if the advance is intentionally empty","handlingStrategy":"validation","validationCode":"static string FormatGlyphEntry(int index, double advanceWidth, double offsetX = 0, double offsetY = 0)\n    => $\";{index},{Math.Max(0, advanceWidth)},{offsetX},{offsetY}\"; // clamp negative widths","typeGuard":"static bool HasNonNegativeAdvance(string entry) => !double.TryParse(entry.Split(',')[1], out double w) || w >= 0;","tryCatchPattern":"try { glyphs.GlyphIndices = built; }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"advance\")) { built = built.Replace(\",-\", \",0\"); glyphs.GlyphIndices = built; }","preventionTips":["Clamp all computed advance widths with Math.Max(0, w)","Never format unvalidated measurements into GlyphIndices","Review negative values in exporter output before ingestion"],"tags":["wpf","glyphs","parsing","value-out-of-range","advance-width"],"backgroundTag":"value-out-of-range","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}