@lightningtv/renderer
Version:
Lightning 3 Renderer
178 lines • 5.54 kB
JavaScript
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2023 Comcast Cable Communications Management, LLC.
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const trPropSetterDefaults = {
x: (state, value) => {
state.props.x = value;
},
y: (state, value) => {
state.props.y = value;
},
width: (state, value) => {
state.props.width = value;
},
height: (state, value) => {
state.props.height = value;
},
color: (state, value) => {
state.props.color = value;
},
zIndex: (state, value) => {
state.props.zIndex = value;
},
fontFamily: (state, value) => {
state.props.fontFamily = value;
},
fontWeight: (state, value) => {
state.props.fontWeight = value;
},
fontStyle: (state, value) => {
state.props.fontStyle = value;
},
fontStretch: (state, value) => {
state.props.fontStretch = value;
},
fontSize: (state, value) => {
state.props.fontSize = value;
},
text: (state, value) => {
state.props.text = value;
},
textAlign: (state, value) => {
state.props.textAlign = value;
},
contain: (state, value) => {
state.props.contain = value;
},
offsetY: (state, value) => {
state.props.offsetY = value;
},
scrollable: (state, value) => {
state.props.scrollable = value;
},
scrollY: (state, value) => {
state.props.scrollY = value;
},
letterSpacing: (state, value) => {
state.props.letterSpacing = value;
},
lineHeight: (state, value) => {
state.props.lineHeight = value;
},
maxLines: (state, value) => {
state.props.maxLines = value;
},
textBaseline: (state, value) => {
state.props.textBaseline = value;
},
verticalAlign: (state, value) => {
state.props.verticalAlign = value;
},
overflowSuffix: (state, value) => {
state.props.overflowSuffix = value;
},
debug: (state, value) => {
state.props.debug = value;
},
};
export class TextRenderer {
stage;
set;
constructor(stage) {
this.stage = stage;
const propSetters = {
...trPropSetterDefaults,
...this.getPropertySetters(),
};
// For each prop setter add a wrapper method that checks if the prop is
// different before calling the setter
const propSet = {};
Object.keys(propSetters).forEach((key) => {
Object.defineProperty(propSet, key, {
value: (state, value) => {
// Check if the current prop value is different before calling the setter
if (state.props[key] !== value) {
propSetters[key](state, value);
// Assume any prop change will require a render
// This ensures that renders are triggered appropriately even with RAF paused
this.stage.requestRender();
}
},
writable: false, // Prevents property from being changed
configurable: false, // Prevents property from being deleted
});
});
this.set = propSet;
}
setStatus(state, status, error) {
// Don't emit the same status twice
if (state.status === status) {
return;
}
state.status = status;
state.emitter.emit(status, error);
}
/**
* Allows the CoreTextNode to communicate changes to the isRenderable state of
* the itself.
*
* @param state
* @param renderable
*/
setIsRenderable(state, renderable) {
state.isRenderable = renderable;
}
/**
* Destroy/Clean up the state object
*
* @remarks
* Opposite of createState(). Frees any event listeners / resources held by
* the state that may not reliably get garbage collected.
*
* @param state
*/
destroyState(state) {
this.setStatus(state, 'destroyed');
state.emitter.removeAllListeners();
}
/**
* Schedule a state update via queueMicrotask
*
* @remarks
* This method is used to schedule a state update via queueMicrotask. This
* method should be called whenever a state update is needed, and it will
* ensure that the state is only updated once per microtask.
* @param state
* @returns
*/
scheduleUpdateState(state) {
if (state.updateScheduled) {
return;
}
state.updateScheduled = true;
queueMicrotask(() => {
// If the state has been destroyed, don't update it
if (state.status === 'destroyed') {
return;
}
state.updateScheduled = false;
this.updateState(state);
});
}
}
//# sourceMappingURL=TextRenderer.js.map