[feature-requests:#1571] Check monospaced and average character width
Status: open
Group: Initial
Labels: Scintilla font
Created: Wed Nov 19, 2025 12:18 PM UTC by Zufu Liu
Last Updated: Wed Nov 19, 2025 12:18 PM UTC
Owner: Neil Hodgson
While lookup into https://github.com/zufuliu/notepad4/issues/1118, I found some issues regarding checkMonospaced and aveCharWidth.
The mentioned bug is because I use aveCharWidth instead of monospaceCharacterWidth inside PositionCache::MeasureWidths(), unifont has an unusual tmAveCharWidth value (other than width of x):
1200:Unifont max=8.000000, min=8.000000, avg=16.000000, variance=0.000000
minWidth to calculate scaledVariance is better, the rational is that when (maxWidth - minWidth)/minWidth < Epsilon, rendering ASCII graphic characters with minWidth will have no visual differences, the calculation has nothing related to aveCharWidth. The calculation can be optimized to use multiplication:const XYPOSITION variance = maxWidth - minWidth;
constexpr XYPOSITION monospaceWidthEpsilon = 0.000001;
const XYPOSITION scaledVariance = monospaceWidthEpsilon * minWidth;
measurements.monospaceASCII = variance < scaledVariance;
aveCharWidth can be unified to average character with of ASCII graphic characters (same as PlatCocoa), this would reduce platform differences (e.g. between GDI and DirectWrite). currently, platforms other GDI and Qt given AverageCharWidth() with measured string width, they can be unified as follow:XYPOSITION aveCharWidth = positions.back() / allASCIIGraphic.length();
if (!surface.SupportsFeature(Supports::FractionalStrokeWidth)) {
aveCharWidth = std::round(aveCharWidth);
}
measurements.aveCharWidth = aveCharWidth;
aveCharWidth changed to average character with of ASCII graphic characters, using it inside PositionCache::MeasureWidths() is better than monospaceCharacterWidth.ListBoxX::GetDesiredRect(), the local averageCharWidth can be replaced with aveCharWidth field (set by ac.lb->SetAverageCharWidth(aveCharWidth); inside ScintillaBase::AutoCompleteStart()).Sent from sourceforge.net because scintill...@googlegroups.com is subscribed to https://sourceforge.net/p/scintilla/feature-requests/
To unsubscribe from further messages, a project admin can change settings at https://sourceforge.net/p/scintilla/admin/feature-requests/options. Or, if this is a mailing list, you can unsubscribe from the mailing list.
std::max_element() + std::min_element() can be merged into single std::minmax_element() as we don't care which one is min/max.
both are slow than a plain loop like following:
auto it = positions.begin();
XYPOSITION prev = *it;
XYPOSITION maxWidth = prev;
XYPOSITION minWidth = prev;
while (++it != positions.end()) {
const XYPOSITION current = *it;
const XYPOSITION value = current - prev;
prev = current;
maxWidth = std::max(maxWidth, value);
minWidth = std::min(minWidth, value);
}
[feature-requests:#1571] Check monospaced and average character width
Status: open
Group: Initial
Labels: Scintilla font
Created: Wed Nov 19, 2025 12:18 PM UTC by Zufu Liu
Last Updated: Thu Nov 20, 2025 12:21 AM UTC
Owner: Neil Hodgson
Including punctuation in the calculation of average character width will decrease the value and may lead to unexpected changes that are visible to users. Any change for Unifont should be narrow to avoid the possibility of regressions.
The mentioned bug is because I use aveCharWidth instead of monospaceCharacterWidth
That's a little strange. Are you trying to handle bi-width fonts where the Chinese characters should be exactly double the width of Roman characters?
Using std::minmax_element would be fine although there will have to be an std::abs to avoid a negative value. Its easier to determine the intent of std::max_element / std::min_element than an explicit loop so can afford a tiny speed decrease.
[feature-requests:#1571] Check monospaced and average character width
Status: open
Group: Initial
Labels: Scintilla font
Created: Wed Nov 19, 2025 12:18 PM UTC by Zufu Liu
Last Updated: Sat Nov 22, 2025 12:08 AM UTC
Owner: Neil Hodgson
will decrease the value and may lead to unexpected changes that are visible to users.
Only happens for proportional font, so does SurfaceImpl::AverageCharWidth() in PlatCocoa.mm.
That's a little strange. Are you trying to handle bi-width fonts where the Chinese characters should be exactly double the width of Roman characters?
Unifont is ASCII monospaced, but GDI SurfaceGDI::AverageCharWidth() value is 2x wider than ASCII letter, use it (instead of monospaceCharacterWidth) inside PositionCache::MeasureWidths() to compute positions for ASCII characters gives wrong caret position.
will have to be an std::abs to avoid a negative value.
positions are increased only (current >= prev).
than an explicit loop so can afford a tiny speed decrease.
it also saves code size for MSVC, see _Minmax_element_impl in
https://github.com/microsoft/STL/blob/main/stl/src/vector_algorithms.cpp#L2270
[feature-requests:#1571] Check monospaced and average character width
Status: open
Group: Initial
Labels: Scintilla font
Created: Wed Nov 19, 2025 12:18 PM UTC by Zufu Liu
Last Updated: Mon Nov 24, 2025 02:07 AM UTC
Owner: Neil Hodgson
Since it is GDI that is providing poor data, a change to just that platform layer will have less potential to cause unexpected results. Perhaps just limit the return of SurfaceGDI::AverageCharWidth to a maximum of tmMaxCharWidth.
[feature-requests:#1571] Check monospaced and average character width
Status: open
Group: Initial
Labels: Scintilla font
Created: Wed Nov 19, 2025 12:18 PM UTC by Zufu Liu
Last Updated: Mon Nov 24, 2025 11:12 AM UTC
Owner: Neil Hodgson
It looks a bug in the Unifont font itself, it's tmAveCharWidth is same as tmMaxCharWidth.
[feature-requests:#1571] Check monospaced and average character width
Status: open
Group: Initial
Labels: Scintilla font
Created: Wed Nov 19, 2025 12:18 PM UTC by Zufu Liu
Last Updated: Mon Nov 24, 2025 08:50 PM UTC
Owner: Neil Hodgson
If APIs or embedded font metadata are producing bad results then it is hard to fix sensibly. A bug report could be sent to Unifont or a particular version could be recommended if this is present only in some versions.
[feature-requests:#1571] Check monospaced and average character width
Status: open
Group: Initial
Labels: Scintilla font
Created: Wed Nov 19, 2025 12:18 PM UTC by Zufu Liu
Last Updated: Tue Nov 25, 2025 09:59 AM UTC
Owner: Neil Hodgson