Skip to content

Commit

Permalink
Merge pull request #448 from rdkcentral/release/2.9.0
Browse files Browse the repository at this point in the history
Release - v2.9.0
  • Loading branch information
michielvandergeest authored Feb 16, 2023
2 parents 3d2d7e3 + 5c21bb4 commit 59d6cee
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 82 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## v2.9.0
*16 feb 2023*

- Fixed issues related to package.json exports (#434)
- Added a warning about `strictNullChecks` option to the TypeScript docs (#433)
- Fixed an issue occurring while using `maxLinesSuffix` when `advancedRender` is set to `true` (#429)
- Fixed an alignment issue occurring when the advanced text renderer is used (#428)
- Added an example of basic subclassing to the TypeScript docs (#446)
- Fixed an issue related to an inconsistency in the handling of default fonts
- Added instant freeing up of text textures to prevent memory building up when text is being changed
- Updated docs to add `letterSpacing` property to `Text` texture

## v2.8.1

*31 oct 2022*
Expand Down
4 changes: 3 additions & 1 deletion docs/RenderEngine/Textures/Text.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ You can use various properties to control the way in which you want to render te
| `cutEx` | Integer | 0 | x coordinate of text cutting ending position |
| `cutSy` | Integer | 0 | y coordinate of text cutting starting position |
| `cutEy` | Integer | 0 | y coordinate of text cutting ending position |
| `letterSpacing` | Integer | 0 | Letter spacing of characters |




Expand Down Expand Up @@ -99,4 +101,4 @@ class TextDemo extends lng.Application {
const options = {stage: {w: window.innerWidth, h: window.innerHeight, useImageWorker: false}};
const App = new TextDemo(options);
document.body.appendChild(App.stage.getCanvas());
```
```
76 changes: 75 additions & 1 deletion docs/TypeScript/Components/SubclassableComponents.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,80 @@
# Subclassable Components

Usually, when creating a Lightning Component you do not need to specify your own generic parameters which are mixed into the ones passed further down into the Component base class. However, there are times when you want to make your Component type flexible and perhaps just as flexible as the Component base class which allows you to pass a [Template Spec](./TemplateSpecs.md) and [Type Config](./TypeConfig.md). Perhaps you want to create a `MyList<T>` component that accepts any child Component of type T. Or a completely flexible `MyBaseComponent<TemplateSpecType, TypeConfig>` which all of your App's Components extend. When doing this there are a few guidelines and gotchas you need to pay attention to that stem from some design choices in TypeScript.
Usually, when creating a Lightning Component you do not need to specify your own generic parameters which are mixed into the ones passed further down into the Component base class. However, there are times when you want to make your Component type flexible and perhaps just as flexible as the Component base class which allows you to pass a [Template Spec](./TemplateSpecs.md) and [Type Config](./TypeConfig.md). Perhaps you want to create a `PageBase<T>` component that accepts any child Component of type T. Or a completely flexible `MyBaseComponent<TemplateSpecType, TypeConfig>` which all of your App's Components extend. When doing this there are a few guidelines and gotchas you need to pay attention to that stem from some design choices in TypeScript.

## Basic Generic Ref Type

If we want to create an extendible base Component called `PageBase<T>`, where `T` is the type of Component used for the content of a page appearing with a static header component, we start by laying down the definition of its Template Spec like so:

```ts
export interface PageTemplateSpec<
T extends Lightning.Component.Constructor = Lightning.Component.Constructor,
> extends Lightning.Component.TemplateSpec {
Header: typeof Header
Content: T
}
```

`Lightning.Component.Constructor` represents a `typeof` any Lightning Component. For example, if there's a component called `List` you can use `typeof List` as the type argument for `T`.

Then we implement the `PageBase` class itself using the same generic type parameter passed down into the Template Spec:

```ts
export class PageBase<T extends Lightning.Component.Constructor = Lightning.Component.Constructor>
extends Lightning.Component<PageTemplateSpec<T>>
implements Lightning.Component.ImplementTemplateSpec<PageTemplateSpec<T>>
{
static override _template(): Lightning.Component.Template<PageTemplateSpec> {
return {
w: (w: number) => w,
h: (h: number) => h,
rect: true,
color: 0xff0e0e0e,

Header: {
type: Header,
},
Content: undefined,
};
}

Content = this.getByRef('Content')!;
}
```

We fill the base `_template()` out with how we want our base component to appear. Here a Header component is provided and we leave the Content component intentionally `undefined`. It will be provided by the subclass implementation. We also create a read-only property for `Content` which returns the result of `getByRef('Content')`.

Notice how the return type of `_template()` does not reference `T`. Due to how class generics work in TypeScript you are not allowed to pass the generic parameters from the class definition. By leaving it out we open it to be used for any Lightning Component type.

With this base we are ready to implement a subclass. Here we use a component called `List` as our Content component:

```ts
export class Discovery extends BasePage<typeof List> {
static override _template(): Lightning.Component.Template<IPageTemplateSpec<typeof List>> {
// Must assert the specific template type to the type of the template spec
// because `super._template()` isn't/can't be aware of List
const pageTemplate = super._template() as Lightning.Component.Template<
IPageTemplateSpec<typeof List>
>;

pageTemplate.Content = {
type: List,
w: (w: number) => w,
h: (h: number) => h,
};

return pageTemplate;
}

override _init() {
this.Content.someListSpecificProperty = false;
}
}
```

Here the `_template()` method calls the base component's `_template()` method, and then supplements it's Content ref with the `List` component. We must use `as` to assert the correct final type of the template object because of what we said above about class generic parameters and static methods. From here, you should be able to reference `this.Content` in your component's implementation and it will automatically be resolved to an instance of `List`.

## Extendible TemplateSpec / TypeConfig

If we wish to create our own `MyBaseComponent` that provides its own base Template Spec and Event Map. First we start by creating our own interfaces for Template Spec and Type Config that extend their respective base interfaces from Component. The wrapping namespace `MyBaseComponent` is used purely for convention and organization. It is recommended but not required.

Expand Down
2 changes: 2 additions & 0 deletions docs/TypeScript/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ TypeScript projects must include a [TSConfig file](https://www.typescriptlang.or
}
```

**Warning:** At a minimum, `strictNullChecks` [must be set to true](https://github.com/rdkcentral/Lightning-SDK/issues/358#issuecomment-1339321527) to avoid certain errors. This is done implicitly by setting `strict` to true as in the above configuration.

### Importing

Lightning should only be imported from a single import as such:
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"author": "Metrological, Bas van Meurs <[email protected]>",
"name": "@lightningjs/core",
"version": "2.8.1",
"version": "2.9.0",
"license": "Apache-2.0",
"main": "dist/lightning.js",
"module": "index.js",
Expand All @@ -13,10 +13,11 @@
"default": "./index.js"
},
"require": {
"types": "./dist/lightning.js",
"default": "./index.d.ts"
"types": "./index.d.ts",
"default": "./dist/lightning.js"
}
}
},
"./package.json": "./package.json"
},
"files": [
"tsconfig.json",
Expand Down Expand Up @@ -55,4 +56,4 @@
"tsd": "^0.21.0",
"typedoc": "^0.23.10"
}
}
}
5 changes: 0 additions & 5 deletions src/textures/TextTexture.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -534,11 +534,6 @@ export default class TextTexture extends Texture {
_getSourceLoader() {
const args = this.cloneArgs();

// Inherit font face from stage.
if (args.fontFace === null) {
args.fontFace = this.stage.getOption('defaultFontFace');
}

const gl = this.stage.gl;

return function (cb) {
Expand Down
38 changes: 16 additions & 22 deletions src/textures/TextTextureRenderer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import StageUtils from "../tree/StageUtils.mjs";
import Utils from "../tree/Utils.mjs";
import { getFontSetting } from "./TextTextureRendererUtils.mjs";

export default class TextTextureRenderer {

Expand All @@ -34,32 +35,25 @@ export default class TextTextureRenderer {
};

setFontProperties() {
this._context.font = Utils.isSpark ? this._stage.platform.getFontSetting(this) : this._getFontSetting();
this._context.font = getFontSetting(
this._settings.fontFace,
this._settings.fontStyle,
this._settings.fontSize,
this.getPrecision(),
this._stage.getOption('defaultFontFace'),
);
this._context.textBaseline = this._settings.textBaseline;
};

_getFontSetting() {
let ff = this._settings.fontFace;

if (!Array.isArray(ff)) {
ff = [ff];
}

let ffs = [];
for (let i = 0, n = ff.length; i < n; i++) {
if (ff[i] === "serif" || ff[i] === "sans-serif") {
ffs.push(ff[i]);
} else {
ffs.push(`"${ff[i]}"`);
}
}

return `${this._settings.fontStyle} ${this._settings.fontSize * this.getPrecision()}px ${ffs.join(",")}`
}

_load() {
if (Utils.isWeb && document.fonts) {
const fontSetting = this._getFontSetting();
const fontSetting = getFontSetting(
this._settings.fontFace,
this._settings.fontStyle,
this._settings.fontSize,
this.getPrecision(),
this._stage.getOption('defaultFontFace')
);
try {
if (!document.fonts.check(fontSetting, this._settings.text)) {
// Use a promise that waits for loading.
Expand Down Expand Up @@ -471,5 +465,5 @@ export default class TextTextureRenderer {
return acc + this._context.measureText(char).width + space;
}, 0);
}

}
Loading

0 comments on commit 59d6cee

Please sign in to comment.