All of WPF's measurement is in pixels (although not exactly screen pixels). Even when you specify the FontSize
of a TextRange
.
Internally, when you specify something like FontSize="14pt"
in XAML, WPF uses LengthConverter
and changes that qualified double based on a factor associated with the unit of measurement you give. So 11 gets multiplied by 1.3333333, approximately. So if you feed a plain double value to a FontSize
property, the unit is pixels.
However, if you use FontSize="14.0001pt"
, or multiply the points by 1.3333334, or maybe even just add 0.0001 to the pixel measurement, it offsets things just enough that you actually get \fs22 or \fs28 (rather than \fs21 or \fs27, respectively). This is for when you're setting a size in WPF.
The reason you have \fs22, Load(), Save(), and then have \fs21 has to do with the same thing. A parser takes the RTF and converts it into WPF objects. So 22 half-points become something like 14.666666666667 pixels. When you Save() again, those pixels get converted back to a different unit, but not very correctly. 14.666666666667 pixels become 21 half points, but 14.6666674 pixels become 22 half points, which is what you wanted.
Maybe this information will give you an idea how to get RTF differently. Maybe you can get XAML out instead and convert it. Maybe there's a nice free third-part XAML-to-RTF converter that doesn't have annoying rounding errors.
RichTextBox
; 2. Modify it by adding 0.001 to each font size; 3. Use code (easily found) to convert XAML to RTF with the built-in classes. That way you're tweaking the input so your output is what you want. – Cambium