[Git][wxwidgets/wxwidgets][master] Avoid using very large wxDC origin offsets with wxGenericListCtrl

2 views
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Jun 20, 2026, 1:55:17 PM (5 days ago) Jun 20
to wx-commi...@googlegroups.com

Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets

Commits:

  • 0ec05189
    by paulcor at 2026-06-20T10:48:01-07:00
    Avoid using very large wxDC origin offsets with wxGenericListCtrl
    
    Using the wxDC origin to implement scrolled drawing can require very large
    origin offsets, which can exceed Cairo coordinate limits (2^23), and therefore
    currently wxGTK3 limits as well. Managing the scroll offsets turns out to be
    pretty simple in this case, avoiding any coordinate limitations.
    See #25365

2 changed files:

Changes:

  • include/wx/generic/private/listctrl.h
    ... ... @@ -275,13 +275,12 @@ public:
    275 275
         }
    
    276 276
     
    
    277 277
         // draw the line on the given DC in icon/list mode
    
    278
    -    void Draw( wxDC *dc, bool current );
    
    278
    +    void Draw( wxDC *dc, const wxPoint& origin, bool current );
    
    279 279
     
    
    280 280
         // the same in report mode: it needs more parameters as we don't store
    
    281 281
         // everything in the item in report mode
    
    282 282
         void DrawInReportMode( wxDC *dc,
    
    283 283
                                const wxRect& rect,
    
    284
    -                           const wxRect& rectHL,
    
    285 284
                                bool highlighted,
    
    286 285
                                bool current,
    
    287 286
                                bool checked );
    

  • src/generic/listctrl.cpp
    ... ... @@ -708,11 +708,14 @@ void wxListLineData::ApplyAttributes(wxDC *dc,
    708 708
     #endif
    
    709 709
     }
    
    710 710
     
    
    711
    -void wxListLineData::Draw(wxDC *dc, bool current)
    
    711
    +void wxListLineData::Draw(wxDC *dc, const wxPoint& origin, bool current)
    
    712 712
     {
    
    713 713
         wxCHECK_RET( !m_items.empty(), wxT("no subitems at all??") );
    
    714 714
     
    
    715
    -    ApplyAttributes(dc, m_gi->m_rectHighlight, IsHighlighted(), current);
    
    715
    +    wxRect rect(m_gi->m_rectHighlight);
    
    716
    +    rect.Offset(origin);
    
    717
    +
    
    718
    +    ApplyAttributes(dc, rect, IsHighlighted(), current);
    
    716 719
     
    
    717 720
         wxListItemData* const item = &m_items[0];
    
    718 721
         if (item->HasImage())
    
    ... ... @@ -720,13 +723,14 @@ void wxListLineData::Draw(wxDC *dc, bool current)
    720 723
             // centre the image inside our rectangle, this looks nicer when items
    
    721 724
             // ae aligned in a row
    
    722 725
             const wxRect& rectIcon = m_gi->m_rectIcon;
    
    723
    -
    
    724
    -        m_owner->DrawImage(item->GetImage(), dc, rectIcon.x, rectIcon.y);
    
    726
    +        m_owner->DrawImage(
    
    727
    +            item->GetImage(), dc, rectIcon.x + origin.x, rectIcon.y + origin.y);
    
    725 728
         }
    
    726 729
     
    
    727 730
         if (item->HasText())
    
    728 731
         {
    
    729
    -        const wxRect& rectLabel = m_gi->m_rectLabel;
    
    732
    +        wxRect rectLabel = m_gi->m_rectLabel;
    
    733
    +        rectLabel.Offset(origin);
    
    730 734
     
    
    731 735
             wxDCClipper clipper(*dc, rectLabel);
    
    732 736
             dc->DrawText(item->GetText(), rectLabel.x, rectLabel.y);
    
    ... ... @@ -735,7 +739,6 @@ void wxListLineData::Draw(wxDC *dc, bool current)
    735 739
     
    
    736 740
     void wxListLineData::DrawInReportMode( wxDC *dc,
    
    737 741
                                            const wxRect& rect,
    
    738
    -                                       const wxRect& rectHL,
    
    739 742
                                            bool highlighted,
    
    740 743
                                            bool current,
    
    741 744
                                            bool checked )
    
    ... ... @@ -746,7 +749,7 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
    746 749
     
    
    747 750
         // Note: GetSubItemRect() needs to be modified if the layout here changes.
    
    748 751
     
    
    749
    -    ApplyAttributes(dc, rectHL, highlighted, current);
    
    752
    +    ApplyAttributes(dc, rect, highlighted, current);
    
    750 753
     
    
    751 754
         wxCoord x = rect.x;
    
    752 755
         wxCoord yMid = rect.y + rect.height/2;
    
    ... ... @@ -2048,10 +2051,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2048 2051
             return;
    
    2049 2052
         }
    
    2050 2053
     
    
    2051
    -    GetListCtrl()->PrepareDC( dc );
    
    2052
    -
    
    2053
    -    int dev_x, dev_y;
    
    2054
    -    GetListCtrl()->CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
    
    2054
    +    const wxPoint origin(GetListCtrl()->CalcScrolledPosition(wxPoint(0, 0)));
    
    2055 2055
     
    
    2056 2056
         if ( InReportView() )
    
    2057 2057
         {
    
    ... ... @@ -2075,10 +2075,6 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2075 2075
                 visibleEnd = visibleTo;
    
    2076 2076
             }
    
    2077 2077
     
    
    2078
    -        wxRect rectLine;
    
    2079
    -        int xOrig = dc.LogicalToDeviceX( 0 );
    
    2080
    -        int yOrig = dc.LogicalToDeviceY( 0 );
    
    2081
    -
    
    2082 2078
             // tell the caller cache to cache the data
    
    2083 2079
             if ( IsVirtual() )
    
    2084 2080
             {
    
    ... ... @@ -2091,13 +2087,14 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2091 2087
                 GetParent()->GetEventHandler()->ProcessEvent( evCache );
    
    2092 2088
             }
    
    2093 2089
     
    
    2094
    -        for ( size_t line = visibleFrom; line <= visibleEnd; line++ )
    
    2095
    -        {
    
    2096
    -            rectLine = GetLineRect(line);
    
    2097
    -
    
    2090
    +        wxRect rectLine(GetLineRect(visibleFrom));
    
    2091
    +        rectLine.Offset(origin);
    
    2098 2092
     
    
    2099
    -            if ( !IsExposed(rectLine.x + xOrig, rectLine.y + yOrig,
    
    2100
    -                            rectLine.width, rectLine.height) )
    
    2093
    +        for (size_t line = visibleFrom;
    
    2094
    +            line <= visibleEnd;
    
    2095
    +            line++, rectLine.y += rectLine.height)
    
    2096
    +        {
    
    2097
    +            if ( !IsExposed(rectLine) )
    
    2101 2098
                 {
    
    2102 2099
                     // don't redraw unaffected lines to avoid flicker
    
    2103 2100
                     continue;
    
    ... ... @@ -2120,7 +2117,6 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2120 2117
     
    
    2121 2118
                 GetLine(line)->DrawInReportMode( &dc,
    
    2122 2119
                                                  rectLine,
    
    2123
    -                                             GetLineHighlightRect(line),
    
    2124 2120
                                                  IsHighlighted(line),
    
    2125 2121
                                                  line == m_current,
    
    2126 2122
                                                  IsItemChecked(line) );
    
    ... ... @@ -2133,12 +2129,13 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2133 2129
     
    
    2134 2130
                 size_t i = visibleFrom;
    
    2135 2131
                 if (i == 0) i = 1; // Don't draw the first one
    
    2136
    -            for ( ; i <= visibleEnd; i++ )
    
    2132
    +
    
    2133
    +            int y = (i - visibleFrom) * lineHeight;
    
    2134
    +            for ( ; i <= visibleEnd; i++, y += lineHeight )
    
    2137 2135
                 {
    
    2138 2136
                     dc.SetPen(pen);
    
    2139 2137
                     dc.SetBrush( *wxTRANSPARENT_BRUSH );
    
    2140
    -                dc.DrawLine(0 - dev_x, i * lineHeight,
    
    2141
    -                            clientSize.x - dev_x, i * lineHeight);
    
    2138
    +                dc.DrawLine(0, y, clientSize.x, y);
    
    2142 2139
                 }
    
    2143 2140
     
    
    2144 2141
                 // Draw last horizontal rule
    
    ... ... @@ -2146,8 +2143,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2146 2143
                 {
    
    2147 2144
                     dc.SetPen( pen );
    
    2148 2145
                     dc.SetBrush( *wxTRANSPARENT_BRUSH );
    
    2149
    -                dc.DrawLine(0 - dev_x, (m_lineTo + 1) * lineHeight,
    
    2150
    -                            clientSize.x - dev_x , (m_lineTo + 1) * lineHeight );
    
    2146
    +                dc.DrawLine(0, y, clientSize.x, y);
    
    2151 2147
                 }
    
    2152 2148
             }
    
    2153 2149
     
    
    ... ... @@ -2160,7 +2156,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2160 2156
     
    
    2161 2157
                 GetItemRect(visibleFrom, firstItemRect);
    
    2162 2158
                 GetItemRect(visibleTo, lastItemRect);
    
    2163
    -            int x = firstItemRect.GetX();
    
    2159
    +            int x = rectLine.x;
    
    2164 2160
                 dc.SetPen(pen);
    
    2165 2161
                 dc.SetBrush(* wxTRANSPARENT_BRUSH);
    
    2166 2162
     
    
    ... ... @@ -2171,15 +2167,14 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2171 2167
                 {
    
    2172 2168
                     int colWidth = GetColumnWidth(col);
    
    2173 2169
                     x += colWidth;
    
    2174
    -                int x_pos = x - dev_x;
    
    2170
    +                int x_pos = x;
    
    2175 2171
                     if (col < GetColumnCount()-1) x_pos -= 2;
    
    2176 2172
     
    
    2177 2173
                     int ruleHeight = m_extendRulesAndAlternateColour && visibleEnd > visibleTo
    
    2178 2174
                                         ? clientHeight
    
    2179
    -                                    : lastItemRect.GetBottom() + 1 - dev_y;
    
    2175
    +                                    : lastItemRect.GetBottom() + 1;
    
    2180 2176
     
    
    2181
    -                dc.DrawLine(x_pos, firstItemRect.GetY() - 1 - dev_y,
    
    2182
    -                            x_pos, ruleHeight);
    
    2177
    +                dc.DrawLine(x_pos, firstItemRect.GetY() - 1, x_pos, ruleHeight);
    
    2183 2178
                 }
    
    2184 2179
             }
    
    2185 2180
         }
    
    ... ... @@ -2188,7 +2183,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2188 2183
             size_t count = GetItemCount();
    
    2189 2184
             for ( size_t i = 0; i < count; i++ )
    
    2190 2185
             {
    
    2191
    -            GetLine(i)->Draw( &dc, i == m_current );
    
    2186
    +            GetLine(i)->Draw( &dc, origin, i == m_current );
    
    2192 2187
             }
    
    2193 2188
         }
    
    2194 2189
     
    
    ... ... @@ -2202,8 +2197,10 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
    2202 2197
             if ( IsHighlighted(m_current) )
    
    2203 2198
                 flags |= wxCONTROL_SELECTED;
    
    2204 2199
     
    
    2205
    -        wxRendererNative::Get().
    
    2206
    -            DrawFocusRect(this, dc, GetLineHighlightRect(m_current), flags);
    
    2200
    +        wxRect rect(GetLineHighlightRect(m_current));
    
    2201
    +        rect.Offset(origin);
    
    2202
    +
    
    2203
    +        wxRendererNative::Get().DrawFocusRect(this, dc, rect, flags);
    
    2207 2204
         }
    
    2208 2205
     #endif // !__WXMAC__
    
    2209 2206
     }
    


View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help Notification message regarding https://gitlab.com/wxwidgets/wxwidgets/-/commit/0ec0518993731403e52f7703be03e6b452f8c8a5 at 1781978110

Reply all
Reply to author
Forward
0 new messages