Color preview

94 views
Skip to first unread message

seasoned_geek

unread,
Nov 15, 2022, 10:56:13 AM11/15/22
to scintilla-interest
All,

If someone could test this out on the Qt or other versions I would be appreciative. I think it is a bug in baseline Scintilla. Not that the code should matter, but here it is.

void EdtBaseWidget::printPrevDocBW()
{
    CsScintillaPrinter printer;

    printer.setScintillaColorMode( SC_PRINT_BLACKONWHITE );

    doPreview( printer );
}

void EdtBaseWidget::printPrevDocColor()
{
    CsScintillaPrinter printer;

    printer.setScintillaColorMode( SC_PRINT_NORMAL );

    doPreview( printer );
}

void EdtBaseWidget::doPreview( CsScintillaPrinter &printer )
{
    printer.setZoom( -2 );

    printer.setFooterLeftPattern( Overlord::getInstance()->printFooterLeftPattern() );
    printer.setFooterCenterPattern( Overlord::getInstance()->printFooterCenterPattern() );
    printer.setFooterRightPattern( Overlord::getInstance()->printFooterRightPattern() );
    printer.setFooterLineTwo( Overlord::getInstance()->printFooterLineTwo() );

    printer.setHeaderLeftPattern( Overlord::getInstance()->printHeaderLeftPattern() );
    printer.setHeaderCenterPattern( Overlord::getInstance()->printHeaderCenterPattern() );
    printer.setHeaderRightPattern( Overlord::getInstance()->printHeaderRightPattern() );
    printer.setHeaderLineTwo( Overlord::getInstance()->printHeaderLineTwo() );

    printer.setPrintPageHeader( true );
    printer.setPrintPageFooter( true );

    QPrintPreviewDialog *dialog = new QPrintPreviewDialog( &printer );

    connect( dialog, &QPrintPreviewDialog::paintRequested, this, [this]( QPrinter* prntr )
    {
        auto *sndr = dynamic_cast<CsScintillaPrinter *>( prntr );

        if ( sndr != nullptr )
        {
            sndr->printRange( this );
        }
    } );

    dialog->exec();
}

When multiple pages of content are rendered using black & white, all is right in the universe.

scintilla-prev-2.png
When color preview is chosen, not-so-much.
scintilla-prev-1.png
It's like something is getting set back to defaults for any page after the first.

Has anybody else seen this on other platforms?

dail8859

unread,
Nov 15, 2022, 11:21:27 AM11/15/22
to scintilla-interest
Using Scintilla v5.3.0 and Qt v5.15.2 on Windows appears to work as expected for each SC_PRINT_* option.


There's not a user-facing option to change it but it has a Lua console built-in, and manually modifying that flag works.

Thanks,
Justin

seasoned_geek

unread,
Nov 15, 2022, 1:08:41 PM11/15/22
to scintilla-interest
Thanks!

I guess I left off the important detail.

Ubuntu 20.04 LTS.

I would be happy to find out this is something I hosed, but it works perfectly when rendering to a physical printer.

Neil Hodgson

unread,
Nov 15, 2022, 4:00:20 PM11/15/22
to Scintilla mailing list
It looks like its just the background colour drawing wrong - I'd stick it in a debugger and examine the background colour in draw calls.

Neil

seasoned_geek

unread,
Nov 16, 2022, 6:15:08 PM11/16/22
to scintilla-interest
I haven't stuck this in the debugger yet, but I have been using the "default debugger." After a lot of qDebug() statements printing out I tried something.

print-prev-without-line-numbers.png
If I set margin 0 to zero width all things work. I had hoped it was a default lexer problem, but COBOL and FORTRAN had the same issue with print preview.

The background for Margin 0 appears to spill over but only when you print a range other than the first page. I will have to find some time tomorrow to try what dail8859 said. See if the preview is showing line numbers. Then need to poke around and see if it is using the default Lexilla lexers sans any tweaks.

seasoned_geek

unread,
Nov 17, 2022, 10:26:19 AM11/17/22
to scintilla-interest
Hello Justin,

I pulled down your appimage and poked around. How does one change the color theme to be a COBALT type theme with a dark background? You have a white background by default (many editors do) and the issue I'm seeing is the white background from Column 0 (line number) walking on the background for normal text.
print-prev-88.png

print-prev-89.png
If there is a simple way for me to spin up a COBALT (or other dark background color scheme/theme) while using the AppImage, I would like to conduct that test. If your editor has same problem then this is either a bug in Scintilla or an issue with the QPrintPreview widget. A very old issue since CopperSpice forked at 4.8.

Thanks!

On Tuesday, November 15, 2022 at 10:21:27 AM UTC-6 dail8859 wrote:

dail8859

unread,
Nov 17, 2022, 10:52:22 AM11/17/22
to scintilla-interest
Under the Help menu there is a "Language Inspector" option. For lexers that support the modern interface (such as cpp) you will be able to change all the style settings. It doesn't save these between application restarts, it is more of just a debugging tool I put in the application. There is also a Lua Console in the Help menu that provides access to the editor if you need more control (e.g, something like:   editor.StyleBack[32] = 0xaa0000) 

Thanks,
Justin

seasoned_geek

unread,
Nov 17, 2022, 5:27:30 PM11/17/22
to scintilla-interest
Thanks Justin,

I followed your instructions and changed the background for all of the named styles to #c7d1d3 as well as for style 32.

nn-print-prev-1.png
You don't appear to have the page 2 problem. 

nn-print-prev-2.png
So, if there was a problem with the QPrintPreview widget that causes the issue it was fixed in Qt prior to 5.x that you are using and still exists in CopperSpice due to fork from 4.8.

I'll have to run some more static analysis to see if there is something uninitialized that manages to walk on the settings. Nothing should be able to cause a problem in that tight little loop, but obviously there is something walking on the background only in print preview.

Thanks again for your assistance.

Roland

seasoned_geek

unread,
Nov 18, 2022, 9:14:11 AM11/18/22
to scintilla-interest
Justin,

Just so I can more accurately compare apples to zuccini, would it be possible for you to build an appimage using Scintilla 5.3.1? 

I did update my fork of Scintilla to 5.3.1. I know, statistically a low probability, but need to check all of the boxes. If you can't for whatever reason then I will have to back my stuff down to test. Either way, you've been most helpful.

Thanks again,
Roland

dail8859

unread,
Nov 18, 2022, 12:39:09 PM11/18/22
to scintilla-interest
When I get some free time (hopefully this weekend?) I will upgrade to Scintilla 5.3.1. The NotifyLexerChanged signal was removed so I need to quickly reimplement an alternative to that.

Thanks,
Justin

dail8859

unread,
Nov 18, 2022, 6:48:25 PM11/18/22
to scintilla-interest
Roland,
Got to it quicker than expected :) These are from the GitHub CI/CD builds, so if you previously tested with the AppImage on the release page just know there's been several commits since then. Nothing should affect what you are looking at, but just wanted to mention it. Think you'll need a GitHub account for these. They are zip files you'll have to unzip first (its annoying but that's what GitHub does):


Thanks,
Justin

seasoned_geek

unread,
Nov 19, 2022, 9:24:47 AM11/19/22
to scintilla-interest
Wow! You da man!

Will let you know in a bit. 

Btw, yes, you do have to have a GitHub account. I had one for some other projects.

seasoned_geek

unread,
Nov 19, 2022, 9:57:19 AM11/19/22
to scintilla-interest
You sir, now have the exact same problem.

nn-same-problem.png
We'll get T-shirts made!

After seeing that I changed the background colors for the following styles

36  #aa0000
37  #ff00ff
38  #55aa00
39  #ffaaff
40  #5500ff
41  #ffff00   yellow
42  #aaff00

It was a drowning man clutching at straws hope that one of the styles used for history tracking would reveal itself as the culprit.

I guess I need to roll my CsScintilla fork of Scintilla back to 5.3.0. Personally I won't be using the change tracking stuff as it is nor will anything the derives from my stuff. We have file versioning banked in and once the DIFF module is added we will be able to track changes against the timed cache, last N saves, or source repo.

Would you mind leaving your editor luggied up for a little while? I've got a few things to do today, but might get time to DIFF 5.3.0 and 5.3.1 to see if something jumps out. I don't mind changing the colors and being the testing grunt. I assume you don't want to change your default background to #c7d1d3 and the backgrounds for 36-42 as above (just so they are garrish) :):)

On Friday, November 18, 2022 at 5:48:25 PM UTC-6 dail8859 wrote:

seasoned_geek

unread,
Nov 19, 2022, 11:43:52 AM11/19/22
to scintilla-interest
All,

Just throwing out a silly-arsed-guess based on Meld differences.

scintilla-guess-1.png



scintilla-guess-2.png

scintilla-guess-3.png

scintilla-guess-4.png
Once I get back to a "testable" state with my own editor I will test out

scintilla-guess-5.png

Neil Hodgson

unread,
Nov 19, 2022, 4:11:11 PM11/19/22
to scintilla...@googlegroups.com
> Just throwing out a silly-arsed-guess based on Meld differences.

seasoned_geek

unread,
Nov 19, 2022, 4:18:16 PM11/19/22
to scintilla-interest
I'll get to that next. Currently cutting out

scintilla-print-8.png
My first silly-arse-guess was completely wrong. But I'm consistent, so was my second guess.

print-guess-9.png

seasoned_geek

unread,
Nov 19, 2022, 4:32:33 PM11/19/22
to scintilla-interest
Taking out clipline didn't fix it either. Ripping this out next.

scintilla-print-guess-11.png

I changed the colors with the NotepadNext test to try and rule this out, but . . . there is not much left that actually changes anything.

dail8859

unread,
Nov 19, 2022, 6:45:57 PM11/19/22
to scintilla-interest

>  You sir, now have the exact same problem. 

Indeed I do. :)

>  Would you mind leaving your editor luggied up for a little while?

This bug isn't something that someone would run into in normal usage in my application, so not worried about it currently. I'm fine leaving it as is.

All,
Bit of a side note...I also noticed that if EOL symbols are on, they only properly work on the first page. This may or may not point to some underlying issue. This also existed in v5.3.0

Screenshot 2022-11-19 184446.png

Thanks,
Justin

seasoned_geek

unread,
Nov 20, 2022, 12:44:32 PM11/20/22
to scintilla-interest
I give up! Either Sunday is not a good day for me to debug/fix code of others or I'm just plain stupid today.

Here is how the sausage was made

I have this in my CMakeLists.txt so had to make a few tweaks
   # lots of warnings and all warnings as errors
   add_compile_options(-Wall -Wextra -Wuninitialized -pedantic -Werror -Wredundant-decls -Wswitch-default -Wundef -Werror -Wno-unused)


Started with my code updated to 531 because that's what I had

ScintillaCall.cxx - reverted to 530

added default to switch statements found here:  
   
bool DBCSIsLeadByte(int codePage, char ch) noexcept {

void AddSymmetric(CaseConversion conversion, int lower,int upper) {
void SetupConversions(CaseConversion conversion) {
CaseConverter *ConverterForConversion(CaseConversion conversion) noexcept {

void CellBuffer::BasicInsertString(Sci::Position position, const char *s, Sci::Position insertLength)

void ScintillaBase::Command(int cmdId) {
void ScintillaBase::ListNotify(ListBoxEvent *plbe) {

size_t LineLayoutCache::EntryForLine(Sci::Line line) const noexcept {


bool Document::IsDBCSLeadByteNoExcept(char ch) const noexcept {
bool Document::IsDBCSTrailByteNoExcept(char ch) const noexcept {
CharacterClass Document::WordCharacterClass(unsigned int ch) const {

-- no luck

reverted CellBuffer.cxx
reverted indicator.cxx
reverted Geometry.cxx and .h

-- no luck

reverted EditView.cxx

-- no luck

reverted Editor.cxx and .h then re-instated removal of NotifyLexerChanged

-- no luck

reverted MarginView.cxx and .h

-- no luck

reverted Style.cxx and .h

-- no luck

reverted ScintillaBase.cxx and .h then re-instated removal of NotifyLexerChanged and adding of default for switches

-- no luck

reverted ScintillaGTK.cxx which should have absolutly nothing to do with this

-- no luck

reverted Scintilla.iface  - widgetgen is run as part of my default build
reverted Scintilla.h  ScintillaCall.h  ScintillaMessages.h  ScintillaTypes.h
manually ran the widgetgen just in case

-- no luck

There is nothing else left. Well, not true, there is the autogenerates stuff.

reverted CaseConvert.cxx and put back in default for switches
reverted CharacterCategoryMap.cxx

-- no luck

It appears that once you have gone to the wrong side of town you can't get back.

I may poke around using some of my earlier CsScintilla zip files and layering my own new stuff on to see if Lassie can find her way home but that won't help this conversation, just "fix" me.

If Justin wants to walk the above trail of tears slowly backleveling modules until "it works" the project would know what broke Qt.

Has nobody with a GTK (or other) based editor seen this? Granted you have to have a dark background set and a white/light background for the line numbers, but it shouldn't be just the Qt world.


seasoned_geek

unread,
Nov 20, 2022, 4:51:52 PM11/20/22
to scintilla-interest
Okay, I know where it broke, I don't know why.

Went back to my last know working commit
hg update -C -r 065115

# works with this CsScintilla revision
https://sourceforge.net/p/csscintilla/csscintilla/ci/0651159c9af25008211fe39d6f7ca2013e88b71e/

hg merge -r 028b1c
hg commit
hg merge -r 123ae5
hg commit

used meld to add in my CsScintilla stuff from saved directory

added default to switch statements that were missing

# will not compile because we need NotifyLexerChanged revision
hg commit

hg merge -r be5679
hg commit --message "merged in be5679"

hg merge -r 3ff43d
hg commit --message "merged in 3ff43d"

# manually removed notifyLexerChanged from Document.h

hg commit

hg merge -r 173135
hg commit --message "merged in NotifyLexerChange 173135"

# this broke it - we are broken here at least

seasoned_geek

unread,
Nov 21, 2022, 5:09:38 PM11/21/22
to scintilla-interest
Found it!

I've been enduring Mercurial. Got back to the last known good spot, extracted each commit one at a time, imported to that branch, built, and tested. It is this commit that busted things

cat commit-d9bdcc6.diff
# HG changeset patch
# User Neil 
# Date 1664069639 -36000
#      Sun Sep 25 11:33:59 2022 +1000
# Node ID d9bdcc6d6abbe68dc7b53c561f07c94acbcd156c
# Parent  136ec155aeeb187b31e07f56b6e7760984c26d3b
Draw lines more consistently in SC_PHASES_TWO and SC_PHASES_ONE modes by
clipping drawing to just the line rectangle.

diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -589,6 +589,12 @@
     and was exposed by ScintillaDocument in the Qt implementation of ScintillaEdit.
     </li>
     <li>
+    Draw lines more consistently in SC_PHASES_TWO and SC_PHASES_ONE modes by
+    clipping drawing to just the line rectangle.
+    This stops drawing some extreme ascenders, descenders and portions of indicators which
+    may appear and then disappear depending on which lines were drawn.
+    </li>
+    <li>
     On Win32 implement horizontal scrolling mouse wheel.
     <a href="https://sourceforge.net/p/scintilla/feature-requests/1450/">Feature #1450</a>.
     </li>
diff --git a/src/EditView.cxx b/src/EditView.cxx
--- a/src/EditView.cxx
+++ b/src/EditView.cxx
@@ -2354,6 +2354,11 @@
         return; // No further drawing
     }
 
+    const bool clipLine = !bufferedDraw && !LinesOverlap();
+    if (clipLine) {
+        surface->SetClip(rcLine);
+    }
+
     // See if something overrides the line background colour.
     const std::optional<ColourRGBA> background = vsDraw.Background(model.GetMark(line), model.caret.active, ll->containsCaret);
 
@@ -2429,6 +2434,10 @@
     if (FlagSet(phase, DrawPhase::lineTranslucent)) {
         DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine, subLine, Layer::OverText);
     }
+
+    if (clipLine) {
+        surface->PopClip();
+    }
 }
 
 static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,

I believe Neil said he thought this would be the most likely culprit.

I don't know enough about the internals of Scintilla to wade in fixing this. I do have a branch now where I can back this out and test whatever is provided to replace this. Looking at just the patch text I would suspect this:

     // See if something overrides the line background colour.
     const std::optional<ColourRGBA> background = vsDraw.Background(model.GetMark(line), model.caret.active, ll->containsCaret);

But I don't know enough about this codebase to make such a call or wade into fixing this. I can be a test grunt though

Neil Hodgson

unread,
Nov 22, 2022, 2:22:54 AM11/22/22
to scintilla...@googlegroups.com
seasoned_geek:

> I've been enduring Mercurial. Got back to the last known good spot, extracted each commit one at a time, imported to that branch, built, and tested.

An easier way to work through the repo looking for a bug is to use
the hg 'update' command to set the files to their state at each
commit. 'Update' is the first item on the context menu for a commit in
TortoiseHg.

'hg bisect' can make this faster
https://www.mercurial-scm.org/repo/hg/help/bisect

> It is this commit that busted things
> ...
> Draw lines more consistently in SC_PHASES_TWO and SC_PHASES_ONE modes by
> clipping drawing to just the line rectangle.
> ...
> + const bool clipLine = !bufferedDraw && !LinesOverlap();
> + if (clipLine) {
> + surface->SetClip(rcLine);
> + }

The other pieces of interesting information are that
1) it doesn't happen on the first page, just subsequent pages
2) "but it works perfectly when rendering to a physical printer"

It could be due to coordinate problems like drawing in logical
coordinates but clipping in device coordinates or similar. Or possibly
nested clipping isn't supported or runs out of resources on some
devices.

Looking at the clipping code in PlatQt.cpp, SurfaceImpl::SetClip
the call being used doesn't behave as I would expect:
QPainter::setClipRect replaces the clip region instead of intersecting
(and thus reducing) the current clip region. That could lead to nested
clipping expanding the region and drawing past the desired area. It
should probably be replaced with Qt::IntersectClip:

void SurfaceImpl::SetClip(PRectangle rc)
{
GetPainter()->save();
GetPainter()->setClipRect(QRectFFromPRect(rc), Qt::IntersectClip);
}

If clipping is misbehaving then it will be affecting more features.
Clipping has been used more often since version 5 as it produces
better graphics than alternative approaches. For example, when drawing
semi-circles for fold structures in the margin, using arc-drawing
functions often leaves extra or missing pixels at the ends that don't
line up with other elements - it's better to draw a whole circle and
clip out the unwanted pixels.

The clipping above only occurs for unbuffered drawing with
SC_PHASES_TWO and SC_PHASES_ONE so it should be possible to avoid
clipping with SCI_SETPHASESDRAW(SC_PHASES_MULTIPLE) for printing.
SC_PHASES_MULTIPLE is the 'best' mode as it allows tall characters to
be fully seen in more cases and I'd recommend its use whenever
possible. It may be slower on some platforms and circumstances but
that shouldn't matter when printing.

Neil

seasoned_geek

unread,
Nov 22, 2022, 3:05:42 PM11/22/22
to scintilla-interest
> An easier way to work through the repo looking for a bug is to use 
the hg 'update' command to set the files to their state at each 
commit. 'Update' is the first item on the context menu for a commit in 
TortoiseHg. 

'hg bisect' can make this faster 
https://www.mercurial-scm.org/repo/hg/help/bisect 

Be that as it may, I don't actually like Mercurial  ... and ... it wasn't just your changes I had to roll back to, I had to mush them in with the demo/example programs CsScintilla has. The Modifiers change and a few others required me to do things the way I did. Got a really good blog post out of it so not a total waste of time. :)

>The other pieces of interesting information are that 
1) it doesn't happen on the first page, just subsequent pages 
2) "but it works perfectly when rendering to a physical printer" 

Perhaps not all subsequent pages. Taking the painful road of tears had me looking into things I wouldn't otherwise look into.

    // Exposing the FORMATRANGE api with both underscore & qt style names
    long format_range(bool draw, QPaintDevice* target, QPaintDevice* measure,
               const QRect& print_rect, const QRect& page_rect,
                          long range_start, long range_end);
    long formatRange(bool draw, QPaintDevice* target, QPaintDevice* measure,
                         const QRect& print_rect, const QRect& page_rect,
                         long range_start, long range_end) {
        return format_range(draw, target, measure, print_rect, page_rect,
                            range_start, range_end);

CopperSpice has different underlying graphics engines than Qt . . . mostly. They just hand rolled their own Vulkan stuff and are busy creating their own graphics interfaces for Wayland and other display tech.  I haven't paid attention to the disccusions about this on the Qt lists, but they've admitted they went the wrong way (without actually admitting it) and started following CopperSpice's lead in many areas.

QRect only exists for legacy compatibility. QRectF is used for all graphics stuff including printer rendering, even in the demo Diamond editor. I noticed that even Justin was using toRect() when calling the Scintilla API. I dug down into a few of these to find that Scintilla is using a struct of four ints. QRect of int are legacy from the DOS VGA only days. If Scintilla is going to use clipping and such it really needs to use structs of four qreal.

typedef qreal

Typedef for double unless Qt is configured with the -qreal float option.


I don't pay attention to the details of how the metal works until I have to. Side effect of working in the medical device world. There is some physical reason this is all moving/has moved to QRectF. I don't remember if it was 2K monitors, 4K monitors, or trying to blend 2D with 3D, I just know there is a reason. It might be time to bite the bullet and change Scintilla to use QRectF instead of QRect. There isn't a whole lot of VGA-Only stuff left.

Working on the printers doesn't surprise me. I have very old printes. 

Lexmark CS310dn is a circa 2014 printer that was supposed to only have a 5 year lifespan. The tail end of a time when all high-end printers were Postscript.
HP Officejet Pro 8100 is a circa 2011 printer. New enough to have built in wifi and not one bit newer.

The point is way back then everything, including your desktop computer BIOS supported the VGA standard. Not the case today. Everyone pursuing UEFI has been pushing hard to dump VGA, and PS/2 support.

It is my completely baseless yet firm belief that the reason the issue doesn't manifest until after the first page is the call to newPage() tweaks the coordinates in such a manner as to require qreal.

I will try your suggested changes in my CopperSpice fork and post stuff here in case Justin wants to try tweaking . . .  assuming I succeed.

seasoned_geek

unread,
Nov 22, 2022, 4:07:59 PM11/22/22
to scintilla-interest
I took the belt & suspenders approach.

// PlatCS.cpp

void SurfaceImpl::SetClip( PRectangle rc )
{
    GetPainter()->save();
    GetPainter()->setClipRect( QRectFFromPRect( rc ), Qt::IntersectClip );
}

// CsScintillaEdit.cpp

CsScintillaEdit::CsScintillaEdit( QWidget *parent ) : CsScintillaEditBase( parent )
{
    setPhasesDraw( SC_PHASES_MULTIPLE );
    setBufferedDraw( false );
    setLayoutCache( SC_CACHE_DOCUMENT );
}

Then I layered on the offending DIFF and walla!

print-preview-success.png

I'm going to continue layering on the change sets one by one to ensure nothing else knocks over the apple cart, but that seems to work. Before I release the next version of RedDiamond I will also be testing it on a gen-3 i5 and an old AMD 6-core that uses an AM3+ socket and an NVidia card you can only find Linux drivers for now. If it runs okay there it runs okay. I don't notice any of the slowness mentioned in the doc on this gen-4 i7 with whatever HP stuck in for default video on an EliteDesk.

I suppose I can dust off my dual-core Netbook (Acer Aspire One) for a real low-end test.

seasoned_geek

unread,
Nov 23, 2022, 8:51:19 AM11/23/22
to scintilla-interest
Once I got everything layered on and started testing with other files, the problem came back ... randomly. Sometimes it works fine, other times second page, sometimes one or more in the middle.

print-prev-100.png
This one worked all the way to the 5th page.
The same document, if I change from Monospace font to Liberation Mono regular at the same point size works just fine.

Justin,

Can you make the changes to your PlatQt.cpp and the Qt ScintillaEdit template, use the python gen, do a full build and either A) confirm it is now random or B) gen another AppImage for me to be test monkey?

I think I'm going to have to back out that clipping change set, at least until Scintilla gets all floating point rectangles. It looks like the mixing and matching is where the problem is.


Neil Hodgson

unread,
Nov 23, 2022, 4:32:21 PM11/23/22
to scintilla...@googlegroups.com
seasoned_geek:
 
I think I'm going to have to back out that clipping change set, at least until Scintilla gets all floating point rectangles. It looks like the mixing and matching is where the problem is.

   I do not understand what is being proposed here. Sci_RangeToFormat can't change as that would be an ABI break. It is defined to be exactly the same as Win32's FORMATRANGE.

   Neil

seasoned_geek

unread,
Nov 23, 2022, 6:04:36 PM11/23/22
to scintilla-interest
Neil,

Right now I'm just thinking out loud. An ABI break is innevitable due to the fact win32 doesn't support high resolution.

https://learn.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
https://www.ghacks.net/2020/01/02/the-perils-of-running-windows-10-on-a-4k-monitor/

Desktop applications using older Windows programming technologies (raw Win32 programming, Windows Forms, Windows Presentation Framework (WPF), etc.) are unable to automatically handle DPI scaling without additional developer work. 

The nagging in the back of my mind is that the precision lost moving QRectF to QRect is causing this problem. If I have time tomorrow I will comment that clipping update out to see if this problem goes away. The nagging voice in my head tells me the precision munging is causing the "overlap" test to erroneously determine there is overlap.

At any rate, my brain is mush right now. Need to sleep on this.

To those who celebrate have a Happy-Happy tomorrow!

seasoned_geek

unread,
Nov 26, 2022, 3:01:30 PM11/26/22
to scintilla-interest
All (well probably just Neil),

Warning! This is still in sausage grinding mode!

I have not gotten to the bottom of this, but I have gotten closer I believe. It's just so hard to debug with the templated entity that is std::vector<Styles>. Can't examine in GDB via Gede. Might have to resort to debuggin in Emacs where I have access to the gdb terminal.

I "believe" this is where the trail is leading.

background-bug-001.png
model.caret.active is true
ll->containsCaret is false

model.GetMark() is a bit of a "how could this ever work?" problem for my brain right now. Maybe I need more caffeine or more rest, I don't know.

vsDraw contains the override of history marker (unless I missed something, it never tweaked the value in model). The clip below is from EditModel.h

background-bug-002.png

This reaches out to the document 
background-bug-003.png
background-bug-004.png

I just can't see what comes back.

background-bug-006.png

Stepping further in

background-bug-009.png

marksOfLine = 0
maskInLine definitely not

background-bug-010.png

It does fall through and return empty

background-bug-011.png

...
much debugging cussing and long walk
...

Inexplicably, when this problem happens styleMain is 0
background-bug-018.png


After I get back to EditView::DrawBackground

background-bug-019.png

I take a look and notice

background-bug-020.png

I cannot look at the styles in the debugger

background-bug-022.png

it looks like when the screw up happens it is when LineLayout is being built. The styles are simply set to 0 instead of being 32 as they would be all across the line in Example6

seasoned_geek

unread,
Nov 26, 2022, 4:42:37 PM11/26/22
to scintilla-interest
Additional data point. Might be useless, might be something. If you set the default font to 

background-bug-030.png

Which looks pretty good on the screen and works well in the editor, choosing print preview (either color or B&W) dies after a brief flicker of the preview window. 

background-bug-031.png

Seem to be able to use the font all day in the editor but print preview self destructs with it.

background-bug-036.png

I apologize if everyone believes this to be a Red Herring. There has to be something walking on the style copy with LineLayout. Feels like a stale data problem. Something got left lying around from the previous page that should have been reset for the start of the current page.

I tried setting Style 0 to match STYLE_DEFAULT in my example program. Tried the same thing with NotepadNext. Print Preview still gets munged up background. The style data is just not there and under Ubuntu 20.04 LTS, the "default" background is white for most things.

Neil Hodgson

unread,
Nov 26, 2022, 5:31:54 PM11/26/22
to Scintilla mailing list
seasoned_geek:

> It does fall through and return empty

A background colour hasn't been found yet so the style colour will be used.

> it looks like when the screw up happens it is when LineLayout is being built. The styles are simply set to 0 instead of being 32 as they would be all across the line in Example6

In general, lexed text doesn't use the default style but the explicit styles set by the lexer.

Neil

Neil Hodgson

unread,
Nov 26, 2022, 5:31:55 PM11/26/22
to Scintilla mailing list
seasoned_geek

> <background-bug-031.png>

This is a different location to earlier debugging: its drawing the line numbers.

The stack trace end is inside memory allocation so a memory bug would be a likely cause. It also involves QClipData so a memory bug in clip handling which, combined with sensitivity to the SetClip in Scintilla, could be something like a fixed depth clipping stack.

> I tried setting Style 0 to match STYLE_DEFAULT in my example program. Tried the same thing with NotepadNext. Print Preview still gets munged up background. The style data is just not there and under Ubuntu 20.04 LTS, the "default" background is white for most things.

After setting STYLE_DEFAULT, call SCI_STYLECLEARALL to set all the styles to be the same as STYLE_DEFAULT.

Neil

Roland Hughes

unread,
Nov 27, 2022, 5:26:19 AM11/27/22
to scintilla...@googlegroups.com
Neil:

>> it looks like when the screw up happens it is when LineLayout is being built. The styles are simply set to 0 instead of being 32 as they would be all across the line in Example6
> In general, lexed text doesn't use the default style but the explicit styles set by the lexer.
>
>
The fly in that ointment is that Example6 deliberately does not use
Lexers. It uses just the hard coded STYLE_DEFAULT, STYLE_LINENUMBER,
STYLE_BRACELIGHT, STYLE_BRACEBAD, and STYLE_INDENTGUIDE. Lexers are
supposed to be optional according to the doc.

--
Roland Hughes, President
Logikal Solutions
(630)-205-1593 (cell)
http://www.theminimumyouneedtoknow.com
http://www.infiniteexposure.net
http://www.johnsmith-book.com

seasoned_geek

unread,
Nov 30, 2022, 2:22:03 PM11/30/22
to scintilla-interest
Basically just a status update. From my notes


EditView.cxx line 2131

   // Does not take margin into account but not significant

   const XYPOSITION xStartVisible = static_cast<XYPOSITION>(subLineStart-xStart);


   // Foreground drawing loop

   const BreakFinder::BreakFor breakFor = (((phasesDraw == PhasesDraw::One) && selBackDrawn) || vsDraw.SelectionTextDrawn())


(gdb) print xStartVisible

$42 = -52

(gdb) print subLineStart

$43 = 0

(gdb) print xStart

$44 = 52

(gdb) print phasesDraw

$45 = Scintilla::PhasesDraw::Multiple

(gdb) print vsDraw.SelectionTextDrawn()

$46 = false

(gdb) print selBackDrawn

$47 = true

(gdb)


(gdb) print breakFor

$49 = Scintilla::Internal::BreakFinder::BreakFor::Foreground


(gdb) print i

$51 = 63

(gdb)

(gdb) print ts

$50 = {start = 0, length = 64, representation = 0x0}


the rcSegment.Intersects(rcLine) returns true. i == 63 and ll->styles[i] comes back 0


(gdb) p/x textFore

$54 = {co = 0xfff8f8f8} #F8F8F8 which is an almost white color


Can someone confirm the "Intersects" logic plase? I have been chasing my tail here thinking something was walking on the background color of the style. That is completely wrong.

What appears to happen

That "not significant" margin comment causes a negative value and once we get down to tis rcSegment.Intersects(rcLine) test, drawing of the background is skipped. The "default" printPreview widget background color is white.

Are we supposed to skip drawing the background when the Intersects() test returns true?

The "hack" test for me to prove this is what is happening will be to set the palette property for the QPrintPreviewWidget 

https://www.copperspice.com/docs/cs_api/class_qwidget.html#a3d57b947664f73f09abcf9a3721e2f0c

so the background color matches the style. If that "fixes" the problem then it is the Intersects() test that is failing somewhere and this should impact every editor that has non-white background __and__ print preview.

Neil Hodgson

unread,
Nov 30, 2022, 5:21:16 PM11/30/22
to scintilla...@googlegroups.com
seasoned_geek:

> EditView.cxx line 2131

This is in DrawForeground. The background should be drawn in
DrawBackground unless in single phase drawing mode when foreground and
background are drawn in a single call to the platform's
DrawTextNoClip.

> (gdb) print phasesDraw
> $45 = Scintilla::PhasesDraw::Multiple

> Can someone confirm the "Intersects" logic plase? I have been chasing my tail here thinking something was walking on the background color of the style. That is completely wrong.
>
> What appears to happen
>
> That "not significant" margin comment causes a negative value and once we get down to tis rcSegment.Intersects(rcLine) test, drawing of the background is skipped. The "default" printPreview widget background color is white.

This particular code is not drawing the background but the
equivalent DrawBackground should be for this situation.

> Are we supposed to skip drawing the background when the Intersects() test returns true?

When the rectangle being drawn is completely outside the surface
(window or paper page), then it should skip drawing as it would not be
visible and it takes time to perform additional processing. It's an
early cull.

> so the background color matches the style. If that "fixes" the problem then it is the Intersects() test that is failing somewhere and this should impact every editor that has non-white background __and__ print preview.

Since rcSegment copies the top & bottom from rcLine, this is a test
that its horizontal span is visible. Failure would be most likely if
the printing page's left or right is incorrect. See if removing the
Intersects test helps as the platform should still cull any off-page
drawing although very old platforms had issues with 16-bit coordinate
spaces.

Neil

seasoned_geek

unread,
Nov 30, 2022, 5:39:42 PM11/30/22
to scintilla-interest
Thanks for the reply!

I haven't tried your suggestion yet, but wanted to let you know that I had turned line wrap off testing this (mistakenly believing this was due to a wrap indicator)

margin-bug-1.png

The right margin means nothing. Looks like it did stop before the closing ";" but that is the only missing character. Might get around to trying your suggestion after supper.

seasoned_geek

unread,
Nov 30, 2022, 7:40:03 PM11/30/22
to scintilla-interest
Well,

I've been distracted the past hour or so, but . . .

that-was-wrong-2.png
that-was-definitely-wrong-1.png

On the plus side, page 2 used to be just white bars when printed.

that-was-wrong-3.png
You will note the end of line hashes that show up only when condensed ot this tiny scale are all there. The problem appears to be in this tiny segment of code.
At this point I think we both need to give up on the "background color getting walked on" train of thought. My hack to set the WindowColor for the widget did not work and I have not removed it in this test. 

Given all of the data points . . . it DrawForeground() has to be choosing to draw a white bar instead of (or with) text and that can't possibly be the case. Somehow there is a FillRect() happening within the boundaries of that if.

I need to get away from this for tonight. 

Actually just took my background hack out and page 2 still looks like above. Will sleep on this and hope for inspiration. Yes, I could choose to only allow Black & White print preview, but I hate broken ()&()*&.

seasoned_geek

unread,
Dec 2, 2022, 6:25:05 PM12/2/22
to scintilla-interest
I need another set of eyes. I set breakpoints in every draw fill method in PlatCS.cpp to try and track this down. I have one file which will reliably produce the problem on the second page. I changed the line number color background to be black so I could see things. I even changed to SCREENCOLOURS in case it was a problem only found with normal print. I know for a fact it is a problem that only happens when line numbers are printed.

scintilla-bug-2001.png

===========

=========== First line of First page

===========



DrawTextNoClip()

(gdb) print/x fore

$1 = {co = 0xffa9a9a9}

(gdb) print text

$2 = "1 "

(gdb) print/x back

$3 = {co = 0xff000000}

(gdb)


FillRectangleAligned()

(gdb) print/x fill

$4 = {colour = {co = 0xff3f2209}}

(gdb) print rc

$5 = {left = 52, top = 0, right = 541.09375, bottom = 15}

(gdb)


FillRectagle()

(gdb) print rc

$6 = {left = 52, top = 0, right = 541, bottom = 15}

(gdb) print/x fill

$7 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangleAligned()

(gdb) print rc

$8 = {left = 541.09375, top = 0, right = 547.71875, bottom = 15}

(gdb) print/x fill

$9 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangle()

(gdb) print rc

$10 = {left = 541, top = 0, right = 548, bottom = 15}

(gdb) print/x fill

$11 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangleAligned()

(gdb) print rc

$12 = {left = 547.71875, top = 0, right = 782, bottom = 15}

(gdb) print/x fill

$13 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangle()

(gdb) print rc

$14 = {left = 548, top = 0, right = 782, bottom = 15}

(gdb) print/x fill

$15 = {colour = {co = 0xff3f2209}}

(gdb)


then we hit 2151 Intersects() break


DrawTextTransparent()

(gdb) print rc

$16 = {left = 52, top = 0, right = 541.09375, bottom = 15}

(gdb) print/x fore

$17 = {co = 0xfff8f8f8}

(gdb) print text

$18 = "/", '*' <repeats 73 times>

(gdb)


===========

=========== First line second page

===========


DrawTextNoClip() -- line number 69

(gdb) print rc

$21 = {left = 18.953125, top = 0, right = 52, bottom = 15}

(gdb) print/x fore

$22 = {co = 0xffa9a9a9}

(gdb) print/x back

$23 = {co = 0xff000000}

(gdb) print text

$24 = "69 "

(gdb)



FillRectangleAligned()

gdb) print rc

$25 = {left = 52, top = 0, right = 475, bottom = 15}

(gdb) print/x fill

$26 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangle()

(gdb) print rc

$27 = {left = 52, top = 0, right = 475, bottom = 15}

(gdb) print/x fill

$28 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangleAligned()

(gdb) print rc

$29 = {left = 475, top = 0, right = 481.625, bottom = 15}

(gdb) print/x fill

$30 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangle()

(gdb) print rc

$31 = {left = 475, top = 0, right = 482, bottom = 15}

(gdb) print/x fill

$32 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangleAligned()

(gdb) print rc

$33 = {left = 481.625, top = 0, right = 782, bottom = 15}

(gdb) print/x fill

$34 = {colour = {co = 0xff3f2209}}

(gdb)


FillRectangle()

(gdb) print rc

$35 = {left = 482, top = 0, right = 782, bottom = 15}

(gdb) print/x fill

$36 = {colour = {co = 0xff3f2209}}

(gdb)



hit 2151 Intersects() break


DrawTextTransparent()

(gdb) print rc

$38 = {left = 52, top = 0, right = 475, bottom = 15}

(gdb) print/x fore

$39 = {co = 0xfff8f8f8}

(gdb) print text

$40 = " // remaining methods must be done after json_Read for config"

(gdb)


Am I missing something obvious???

I even went through and changed how the brush was cleared because I didn't like that code. I even forceably clear the brush now in DrawTextTransparent()

Thanks, I needed to rant.

Hopefully someone see something in the values from the debugger.


Neil Hodgson

unread,
Dec 3, 2022, 2:01:37 AM12/3/22
to scintilla...@googlegroups.com
seasoned_geek:

DrawTextNoClip()

(gdb) print/x fore

$1 = {co = 0xffa9a9a9}

(gdb) print text

$2 = "1 "

(gdb) print/x back

$3 = {co = 0xff000000}


Maybe SurfaceImpl::DrawTextNoClip should be calling the version of QPainter::drawText that takes a rectangle instead of a point to limit where the background is drawn. Although I'd expect the subsequent document text background to override the line numbers using that.

QPainter::drawText(const QRectF &rectangle, const QString &text, ...
   instead of
QPainter::drawText(const QPointF &position, const QString &text)


   Neil

seasoned_geek

unread,
Dec 3, 2022, 12:19:17 PM12/3/22
to scintilla-interest
Nope. I found it though. Here is the diff between what I have in source control and what works with CopperSpice platform. You will probably want to snip bits for Qt. If this exists in both Qt and CopperSpice, it is a __very__ old bug.

diff -r 83c09324b1fe copperspice/CsScintillaEditBase/PlatCS.cpp
--- a/copperspice/CsScintillaEditBase/PlatCS.cpp    Sat Nov 26 16:08:55 2022 -0600
+++ b/copperspice/CsScintillaEditBase/PlatCS.cpp    Sat Dec 03 10:58:01 2022 -0600
@@ -390,8 +390,7 @@
 void SurfaceImpl::RectangleFrame( PRectangle rc, Stroke stroke )
 {
     PenColourWidth( stroke.colour, stroke.width );
-    // Default QBrush is Qt::NoBrush so does not fill
-    GetPainter()->setBrush( QBrush() );
+    GetPainter()->setBrush( Qt::NoBrush );
     const QRectF rect = QRectFFromPRect( rc.Inset( stroke.width / 2 ) );
     GetPainter()->drawRect( rect );
 }
@@ -631,6 +630,10 @@
     GetPainter()->setBackgroundMode( Qt::OpaqueMode );
     QString su = UnicodeFromText( codec, text );
     GetPainter()->drawText( QPointF( rc.left, ybase ), su );
+
+    // stop random background bleed over
+    GetPainter()->setBackgroundMode( Qt::TransparentMode );
+
 }
 
 void SurfaceImpl::DrawTextClipped( PRectangle rc,
@@ -651,9 +654,9 @@
                                        std::string_view text,
                                        ColourRGBA fore )
 {
+    GetPainter()->setBrush( Qt::NoBrush );
     SetFont( font );
     PenColour( fore );
-
     GetPainter()->setBackgroundMode( Qt::TransparentMode );
     QString su = UnicodeFromText( codec, text );
     GetPainter()->drawText( QPointF( rc.left, ybase ), su );
@@ -769,6 +772,10 @@
     GetPainter()->setBackgroundMode( Qt::OpaqueMode );
     QString su = QString::fromUtf8( text.data(), static_cast<int>( text.length() ) );
     GetPainter()->drawText( QPointF( rc.left, ybase ), su );
+
+    // help stop random background bleed over
+    GetPainter()->setBackgroundMode( Qt::TransparentMode );
+
 }
 
 void SurfaceImpl::DrawTextClippedUTF8( PRectangle rc,
@@ -887,8 +894,8 @@
 {
     if ( device->paintingActive() )
     {
-        GetPainter()->setPen( QPen() );
-        GetPainter()->setBrush( QBrush() );
+        GetPainter()->setPen( Qt::NoPen );
+        GetPainter()->setBrush( Qt::NoBrush );
     }
 }
 
Basically, at the time you switch to Opaque, you have to switch back to Transparent before existing the method. This bug has something to do with the QPrintPreviewWidget and signals. Once you have set a brush and turned on Opaque, going back to Transparent appears to get treated as a mere suggestion. Everything I did in the "transparent" routine should have fixed the issue but it appears we don't directly communicate with the painter actually doing the painting. The coding change that was the straw to break the camel's back just made the problem worse.

The Seg fault which turned up debugging this another landmine that appears to have been in place since the early Qt 4 (if not earlier) days as well. Gotta love undocumented internal classes!

static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer,

int x, int y, quint32 color,

const uchar *map,

int mapWidth, int mapHeight, int mapStride,

const QClipData *clip)

{

const quint32 c = color;

You will note clip is const. Then at line 6302 (in the CopperSpice version, different for Qt)

const_cast<QClipData *>(clip)->initialize();

They cast away const and call the initialize() method.

void QClipData::initialize()

{

if (m_spans) {

return;

}


if (!m_clipLines) {

m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);

}


Q_CHECK_PTR(m_clipLines);


And that will generate a segmentation fault in malloc_consolidate, not all of the time, just some of the time, mainly if something in the clip really was in a PSECT tagged NOWRT, or RONLY because it just can't be consolidated with newly allocated memory. Yes, I've reported the bug, but any time you deal with clipping you can trigger it. This is especially true if you add page header/footer to your print preview.


Reply all
Reply to author
Forward
0 new messages