Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add pixelRatio override for Text rendering #2294

Merged
merged 1 commit into from
Apr 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Added


- `ex.Engine` now support setting the pixel ratio in the constructor `new ex.Engine({pixelRatio: 2})`, this is useful for smooth `ex.Text` rendering when `antialiasing: false` and rendering pixel art type graphics
- `ex.TileMap` now supports per Tile custom colliders!
```typescript
const tileMap = new ex.TileMap(...);
Expand Down
2 changes: 1 addition & 1 deletion sandbox/src/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var game = new ex.Engine({
height: 600 / 2,
viewport: { width: 800, height: 600 },
canvasElementId: 'game',
suppressHiDPIScaling: false,
pixelRatio: 4,
suppressPlayButton: true,
pointerScope: ex.Input.PointerScope.Canvas,
displayMode: ex.DisplayMode.FitScreen,
Expand Down
14 changes: 13 additions & 1 deletion src/engine/Engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@ export interface EngineOptions {
*/
antialiasing?: boolean;

/**
* Optionally upscale the number of pixels in the canvas. Normally only useful if you need a smoother look to your assets, especially
* [[Text]].
*
* **WARNING** It is recommended you try using `antialiasing: true` before adjusting pixel ratio. Pixel ratio will consume more memory
* and on mobile may break if the internal size of the canvas exceeds 4k pixels in width or height.
*
* Default is based the display's pixel ratio, for example a HiDPI screen might have the value 2;
*/
pixelRatio?: number;

/**
* Optionally configure the native canvas transparent backdrop
*/
Expand Down Expand Up @@ -657,9 +668,10 @@ O|===|* >________________>\n\
resolution: options.resolution,
displayMode,
position: options.position,
pixelRatio: options.suppressHiDPIScaling ? 1 : null
pixelRatio: options.suppressHiDPIScaling ? 1 : (options.pixelRatio ?? null)
});

// Set default filtering based on antialiasing
TextureLoader.filtering = options.antialiasing ? ImageFiltering.Blended : ImageFiltering.Pixel;

if (options.backgroundColor) {
Expand Down
8 changes: 8 additions & 0 deletions src/engine/Graphics/Font.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,21 @@ export class Font extends Graphic implements FontRenderer {
this.clearCache();
}
this.checkAndClearCache();
// Get bitmap for rastering text, this is cached by raster properties
const bitmap = this._getTextBitmap(text, colorOverride);
const isNewBitmap = !this._bitmapUsage.get(bitmap);

// Bounds of the text
this._textBounds = this.measureText(text);

// TODO if the text is bigger than 4k we need to split it somehow

if (isNewBitmap) {
// Setting dimension is expensive because it invalidates the bitmap
this._setDimension(this._textBounds, bitmap);
}

// Apply affine transformations
this._preDraw(ex, x, y);

const lines = text.split('\n');
Expand All @@ -301,6 +308,7 @@ export class Font extends Graphic implements FontRenderer {
TextureLoader.load(bitmap.canvas, this.filtering, true);
}

// Send draw cal to the ex graphics context
ex.drawImage(
bitmap.canvas,
0,
Expand Down
4 changes: 2 additions & 2 deletions src/engine/Screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@ export class Screen {
if (!supported && !this._alreadyWarned) {
this._alreadyWarned = true; // warn once
this._logger.warn(
`The currently configured resolution (${this.resolution.width}x${this.resolution.height})` +
' is too large for the platform WebGL implementation, this may work but cause WebGL rendering to behave oddly.' +
`The currently configured resolution (${this.resolution.width}x${this.resolution.height}) and pixel ratio (${this.pixelRatio})` +
' are too large for the platform WebGL implementation, this may work but cause WebGL rendering to behave oddly.' +
' Try reducing the resolution or disabling Hi DPI scaling to avoid this' +
' (read more here https://excaliburjs.com/docs/screens#understanding-viewport--resolution).');
}
Expand Down
8 changes: 8 additions & 0 deletions src/spec/EngineSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ describe('The engine', () => {
expect(engine.graphicsContext.snapToPixel).toBeTrue();
});

it('can set pixelRatio', () => {
engine = TestUtils.engine({width: 100, height: 100, pixelRatio: 5, suppressHiDPIScaling: false});
expect(engine.pixelRatio).toBe(5);
expect(engine.screen.pixelRatio).toBe(5);
expect(engine.screen.scaledWidth).toBe(500);
expect(engine.screen.scaledHeight).toBe(500);
});

it('should emit a preframe event', () => {
const fired = jasmine.createSpy('fired');
engine.on('preframe', fired);
Expand Down
4 changes: 2 additions & 2 deletions src/spec/ScreenSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,8 +610,8 @@ describe('A Screen', () => {
sut.applyResolutionAndViewport();
expect(context.checkIfResolutionSupported).toHaveBeenCalled();
expect(logger.warn).toHaveBeenCalledOnceWith(
`The currently configured resolution (${sut.resolution.width}x${sut.resolution.height})` +
' is too large for the platform WebGL implementation, this may work but cause WebGL rendering to behave oddly.' +
`The currently configured resolution (${sut.resolution.width}x${sut.resolution.height}) and pixel ratio (${sut.pixelRatio})` +
' are too large for the platform WebGL implementation, this may work but cause WebGL rendering to behave oddly.' +
' Try reducing the resolution or disabling Hi DPI scaling to avoid this' +
' (read more here https://excaliburjs.com/docs/screens#understanding-viewport--resolution).'
);
Expand Down