Skip to content

Commit

Permalink
Adapt double buffering use cases for multi-zoom
Browse files Browse the repository at this point in the history
This commit replaces three use cases where GC together with Images where
used to draw double buffered images. With new multi-zoom-setting in
Windows this leads to desctructive scaling and fragments caused by the
double buffering of Images/GCs created with different zoom. The changes
utilize the newly added ImageGcDrawer to provide a dynamic callback to
draw on a correctly initialized GC on demand.
  • Loading branch information
akoch-yatta authored and HeikoKlare committed Jan 19, 2025
1 parent aff1ccc commit a2298c9
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageGcDrawer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
Expand Down Expand Up @@ -266,6 +267,13 @@ public Control createControl(CompositeRuler parentRuler, Composite parentControl
fCachedTextWidget= null;
});

fCanvas.addListener(SWT.ZoomChanged, e -> {
if (fBuffer != null) {
fBuffer.dispose();
fBuffer= null;
}
});

fMouseListener= new MouseListener() {
@Override
public void mouseUp(MouseEvent event) {
Expand Down Expand Up @@ -517,10 +525,18 @@ private void doubleBufferPaint(GC dest) {
fBuffer= null;
}
}
if (fBuffer == null)
fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
if (fBuffer == null) {
ImageGcDrawer imageGcDrawer= (gc, imageWidth, imageHeight) -> {
doPaint(gc, new Point(imageWidth, imageHeight));
};
fBuffer= new Image(fCanvas.getDisplay(), imageGcDrawer, size.x, size.y);
} else {
doPaint(new GC(fBuffer), size);
}
dest.drawImage(fBuffer, 0, 0);
}

GC gc= new GC(fBuffer);
private void doPaint(GC gc, Point size) {
gc.setFont(fCachedTextWidget.getFont());
try {
gc.setBackground(fCanvas.getBackground());
Expand All @@ -533,8 +549,6 @@ private void doubleBufferPaint(GC dest) {
} finally {
gc.dispose();
}

dest.drawImage(fBuffer, 0, 0);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageGcDrawer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
Expand Down Expand Up @@ -199,6 +200,13 @@ public Control createControl(CompositeRuler parentRuler, Composite parentControl
fCachedTextWidget= null;
});

fCanvas.addListener(SWT.ZoomChanged, e -> {
if (fBuffer != null) {
fBuffer.dispose();
fBuffer= null;
}
});

fCanvas.addMouseListener(fMouseHandler);
fCanvas.addMouseMoveListener(fMouseHandler);

Expand Down Expand Up @@ -249,19 +257,13 @@ private void doubleBufferPaint(GC dest) {
fBuffer= null;
}
}
if (fBuffer == null)
fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);

GC gc= new GC(fBuffer);
gc.setFont(fCanvas.getFont());

try {
gc.setBackground(getBackground());
gc.fillRectangle(0, 0, size.x, size.y);

doPaint(gc);
} finally {
gc.dispose();
if (fBuffer == null) {
ImageGcDrawer imageGcDrawer= (gc, imageWidth, imageHeight) -> {
doPaint(gc, new Point(imageWidth, imageHeight));
};
fBuffer= new Image(fCanvas.getDisplay(), imageGcDrawer, size.x, size.y);
} else {
doPaint(new GC(fBuffer), size);
}

dest.drawImage(fBuffer, 0, 0);
Expand Down Expand Up @@ -291,6 +293,19 @@ protected final boolean isViewerCompletelyShown() {
return JFaceTextUtil.isShowingEntireContents(fCachedTextWidget);
}

private void doPaint(GC gc, Point size) {
gc.setFont(fCanvas.getFont());

try {
gc.setBackground(getBackground());
gc.fillRectangle(0, 0, size.x, size.y);

doPaint(gc);
} finally {
gc.dispose();
}
}

/**
* Draws the ruler column.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageGcDrawer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
Expand Down Expand Up @@ -616,7 +617,13 @@ public void addMouseListener(MouseListener listener) {
fCachedTextWidget= null;
});

fCanvas.addListener(SWT.ZoomChanged, e -> computeIndentations());
fCanvas.addListener(SWT.ZoomChanged, e -> {
computeIndentations();
if (fBuffer != null) {
fBuffer.dispose();
fBuffer= null;
}
});

fMouseHandler= new MouseHandler();
fCanvas.addMouseListener(fMouseHandler);
Expand Down Expand Up @@ -681,8 +688,17 @@ private void doubleBufferPaint(GC dest) {

boolean bufferStillValid = fBuffer != null;
if (fBuffer == null) {
fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
}
ImageGcDrawer imageGcDrawer= (gc, imageWidth, imageHeight) -> {
ILineRange lines= JFaceTextUtil.getVisibleModelLines(fCachedTextViewer);
if (lines == null) {
return;
}
// We redraw everything; paint directly into the buffer
initializeGC(gc, 0, 0, imageWidth, imageHeight);
doPaint(gc, lines);
};
fBuffer= new Image(fCanvas.getDisplay(), imageGcDrawer, size.x, size.y);
} else {
GC bufferGC= new GC(fBuffer);
Image newBuffer= null;
try {
Expand Down Expand Up @@ -745,16 +761,7 @@ private void doubleBufferPaint(GC dest) {
fLastBottomModelLine= bottomModelLine;
fLastHeight= height;
if (dy != 0) {
// Some rulers may paint outside the line region. Let them paint in a new image,
// the copy the wanted bits.
newBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
GC localGC= new GC(newBuffer);
try {
initializeGC(localGC, 0, bufferY, size.x, bufferH);
doPaint(localGC, visibleLines);
} finally {
localGC.dispose();
}
newBuffer= newBufferImage(size, bufferY, bufferH, visibleLines);
bufferGC.drawImage(newBuffer, 0, bufferY, size.x, bufferH, 0, bufferY, size.x, bufferH);
if (dy > 0 && bufferY + bufferH < size.y) {
// Scrolled down in the text, but didn't use the full height of the Canvas: clear
Expand All @@ -774,9 +781,24 @@ private void doubleBufferPaint(GC dest) {
newBuffer.dispose();
}
}
}
dest.drawImage(fBuffer, 0, 0);
}

private Image newBufferImage(Point size, int bufferY, int bufferH, final ILineRange visibleLines) {
ImageGcDrawer imageGcDrawer= (localGC, imageWidth, imageHeight) -> {
// Some rulers may paint outside the line region. Let them paint in a new image,
// the copy the wanted bits.
try {
initializeGC(localGC, 0, bufferY, imageWidth, bufferH);
doPaint(localGC, visibleLines);
} finally {
localGC.dispose();
}
};
return new Image(fCanvas.getDisplay(), imageGcDrawer, size.x, size.y);
}

private void initializeGC(GC gc, int x, int y, int width, int height) {
gc.setFont(fCanvas.getFont());
if (fForeground != null) {
Expand Down

0 comments on commit a2298c9

Please sign in to comment.