Speed up painting by detecting the most common background color and using it as the overall background color on each paint event

This commit is contained in:
Kovid Goyal 2016-10-21 12:26:03 +05:30
parent 77eb005af1
commit fedfdf00a9
2 changed files with 28 additions and 3 deletions

View File

@ -145,6 +145,10 @@ class Line:
cols = self.color[pos] cols = self.color[pos]
return c & CHAR_MASK, c >> ATTRS_SHIFT, cols return c & CHAR_MASK, c >> ATTRS_SHIFT, cols
def bgcolor(self, pos: int) -> int:
cols = self.color[pos]
return cols >> COL_SHIFT
def __iter__(self): def __iter__(self):
for i in range(len(self)): for i in range(len(self)):
yield self.text_at(i) yield self.text_at(i)

View File

@ -4,6 +4,7 @@
from functools import lru_cache from functools import lru_cache
from itertools import product from itertools import product
from collections import Counter
from typing import Tuple, Iterator from typing import Tuple, Iterator
from PyQt5.QtCore import pyqtSignal, QTimer, QRect, Qt from PyQt5.QtCore import pyqtSignal, QTimer, QRect, Qt
@ -11,7 +12,7 @@ from PyQt5.QtGui import QColor, QPainter, QFont, QFontMetrics, QRegion, QPen, QP
from PyQt5.QtWidgets import QWidget, QApplication from PyQt5.QtWidgets import QWidget, QApplication
from .config import build_ansi_color_tables, Options, fg_color_table, bg_color_table from .config import build_ansi_color_tables, Options, fg_color_table, bg_color_table
from .data_types import Cursor, HAS_BG_MASK, COL_SHIFT, COL_MASK, as_color from .data_types import Cursor, COL_SHIFT, COL_MASK, as_color
from .utils import set_current_font_metrics from .utils import set_current_font_metrics
from .tracker import ChangeTracker from .tracker import ChangeTracker
from .screen import wrap_cursor_position from .screen import wrap_cursor_position
@ -54,6 +55,8 @@ class TerminalWidget(QWidget):
def __init__(self, opts: Options, parent: QWidget=None, dump_commands: bool=False): def __init__(self, opts: Options, parent: QWidget=None, dump_commands: bool=False):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
self.setAttribute(Qt.WA_OpaquePaintEvent, True)
self.setAutoFillBackground(False)
self.cursor = Cursor() self.cursor = Cursor()
self.tracker = ChangeTracker(self) self.tracker = ChangeTracker(self)
self.tracker.dirtied.connect(self.update_screen) self.tracker.dirtied.connect(self.update_screen)
@ -65,7 +68,6 @@ class TerminalWidget(QWidget):
self.feed = self.stream.feed self.feed = self.stream.feed
self.last_drew_cursor_at = (0, 0) self.last_drew_cursor_at = (0, 0)
self.setFocusPolicy(Qt.WheelFocus) self.setFocusPolicy(Qt.WheelFocus)
self.setAutoFillBackground(True)
self.apply_opts(opts) self.apply_opts(opts)
self.debounce_resize_timer = t = QTimer(self) self.debounce_resize_timer = t = QTimer(self)
t.setSingleShot(True) t.setSingleShot(True)
@ -173,11 +175,29 @@ class TerminalWidget(QWidget):
self.cell_positions[c], self.vmargin, self.cell_width, self.cell_height * self.lines_per_screen))) self.cell_positions[c], self.vmargin, self.cell_width, self.cell_height * self.lines_per_screen)))
return product(lines, cells) return product(lines, cells)
def common_bg_color(self):
c = Counter()
for rdiv in range(1, 4):
lnum = int(self.lines_per_screen * rdiv / 4)
for cdiv in range(1, 4):
cnum = int(self.cells_per_line * cdiv / 4)
bgcol = self.screen.line(lnum).bgcolor(cnum)
c[bgcol] += 1
return c.most_common(1)[0][0]
def paintEvent(self, ev): def paintEvent(self, ev):
if self.size() != self.layout_size: if self.size() != self.layout_size:
return return
r = ev.region() r = ev.region()
self.current_bgcol = self.common_bg_color()
bg = self.default_bg
if self.current_bgcol & 0xff:
cbg = as_color(self.current_bgcol, bg_color_table())
if cbg:
bg = QColor(*cbg)
p = QPainter(self) p = QPainter(self)
p.fillRect(self.rect(), bg)
for lnum, cnum in self.dirty_cells(r): for lnum, cnum in self.dirty_cells(r):
try: try:
@ -224,7 +244,8 @@ class TerminalWidget(QWidget):
line = self.screen.line(row) line = self.screen.line(row)
ch, attrs, colors = line.basic_cell_data(col) ch, attrs, colors = line.basic_cell_data(col)
x, y = self.cell_positions[col], self.line_positions[row] x, y = self.cell_positions[col], self.line_positions[row]
if colors & HAS_BG_MASK: bgcol = colors >> COL_SHIFT
if bgcol != self.current_bgcol:
bg = as_color(colors >> COL_SHIFT, bg_color_table()) bg = as_color(colors >> COL_SHIFT, bg_color_table())
if bg is not None: if bg is not None:
r = QRect(x, y, self.cell_width, self.cell_height) r = QRect(x, y, self.cell_width, self.cell_height)