FabricJS image filter with no fragmentSource? - fabricjs

I have a filter that isn't compatible with WebGL. Is there a way to skip writing a fragmentSource? I tried overriding fabric.Image.filters.BaseFilter applyTo on the filter subclass to only call this.applyTo2d(options); but I'm not getting any image data.
applyTo: function(options) {
if (options.webgl) {
if (options.passes > 1 && this.isNeutralState(options)) {
// avoid doing something that we do not need
return;
}
this._setupFrameBuffer(options);
this.applyToWebGL(options);
this._swapTextures(options);
}
else if (!this.isNeutralState()) {
this.applyTo2d(options);
}
},

I as able to accomplish this in a non-optimized way with minimal code in webgl_backend.class.js.
First, the webgl backend needs a fallback for non-webgl filters:
this.fallback2dBackend = new fabric.Canvas2dFilterBackend();
Then, instead of running all filters: fabric.filterBackend.applyFilters(filters, this._originalElement, sourceWidth, sourceHeight, this._element, this.cacheKey);
Do this:
var newSource = fabric.util.createCanvasElement();
newSource.width = sourceWidth;
newSource.height = sourceHeight;
var newSourceCtx = newSource.getContext('2d');
newSourceCtx.drawImage(this._originalElement, 0, 0, sourceWidth, sourceHeight);
filters.forEach(function(filter) {
if (!filter) {
return;
}
var backend = fabric.filterBackend;
if (filter.fragmentSource === null) {
backend = backend.fallback2dBackend;
}
backend.applyFilters(
[filter], newSource, sourceWidth, sourceHeight, this._element);
newSourceCtx.clearRect(0, 0, sourceWidth, sourceHeight);
newSourceCtx.drawImage(this._element, 0, 0, sourceWidth, sourceHeight);
}, this);
I've published a fork in case someone wants to refactor this into a PR.

Related

Best way to navigate throught a JSON in Node while validating the path

I'm trying to get some info out of a API call in Nodejs, structured something like a JSON:
{
"generated":"2019-11-04T09:34:11+00:00",
"event":{
"id":"19040956",
"start_":"2019-11-16T11:30:00+00:00",
"event_context":{
"sport":{
"id":"1",
"name":"Soccer"
}
}
}
}
I'm not sure about the presence of none of these fields(Json could be incomplete).
Is there a better way to get the value of "name" in JSON.event.event_context.sport.name without an ugly if to not get errors like "cannot get field 'sport' of undefined"?
Currently, I'm doing
if(json.event && json.event.event_context && json.event.event_context.sport) {
return json.event.event_context.sport.name;
}
Is there a better way?
Thank you!
what do you mean by saying "I'm not sure about the presence of none of these fields"?
i don't understand what your'e trying to achieve.
Looks like there is also an interesting package that will allow more conditions on searching json :
https://www.npmjs.com/package/jspath
let getNested = (path, obj) => {
return path.split(".").reduce( getPath, obj);
}
let getPath = (path, key) => {
return (path && path[key]) ? path[key] : null
}
let test = {
"foo": "bar",
"baz": { "one": 1, "two": ["to", "too", "two"] },
"event": { "event_context": { "sport": { "name": "soccer" } } }
}
console.log(getNested("none", test))
console.log(getNested("baz.one", test))
console.log(getNested("baz.two", test))
console.log(getNested("event.event_context.sport.name", test))
You can use lodash get to get a potentially deeply-nested value, and also specify a default in case it doesnt exist.
Example
const _ = require('lodash');
const my_object = {
"generated":"2019-11-04T09:34:11+00:00",
"event":{
"id":"19040956",
"start_":"2019-11-16T11:30:00+00:00",
"event_context":{
"sport":{
"id":"1",
"name":"Soccer"
}
}
};
_.get(my_object, 'event.event_context.sport.name'); // "Soccer"
_.get(my_object, 'event.event_context.sport.nonExistentField', 'default val'); // "default val"
Article: https://medium.com/#appi2393/lodash-get-or-result-f409e73e018b
You can check by using a function to check object keys like :
function checkProperty(checkObject, checkstring){
if(!checkstring)
return false;
var propertiesKeys = checkstring.split('.');
propertiesKeys.forEach(element => {
if(!checkObject|| !checkObject.hasOwnProperty(element)){
return false;
} else {
checkObject= checkObject[element];
}
})
return true;
};
var objectToCheck = {
"generated":"2019-11-04T09:34:11+00:00",
"event":{
"id":"19040956",
"start_":"2019-11-16T11:30:00+00:00",
"event_context":{
"sport":{
"id":"1",
"name":"Soccer"
}
}
}
}
if (checkProperty(objectToCheck ,'event.event_context.sport.name'))
console.log('object to find is : ', objectToCheck .event.event_context.sport.name;)
Yeah there are better ways!
For example, you could use lodash's get() method to reach a nested value.
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.get(object, 'a[0].b.c');
// => 3
But there is also a native solution.
Currently (11.2019) only Babel can handle this.
I am speaking of Optional chaining. It's new in the Ecmascript world.
Why I like it? Look here!
// Still checks for errors and is much more readable.
const nameLength = db?.user?.name?.length;
What happens when db, user, or name is undefined or null? With the optional chaining operator, JavaScript initializes nameLength to undefined instead of throwing an error.
If you are using Babel as a compiler then you could use it now.
Related link: https://v8.dev/features/optional-chaining

Getting a string from JSON object with args from another object

Say I have a JSON file like this:
{"ABCD":{
"1_99":{"type": 3, "serverPath": "http://some.website.com"}
},
"EFGH":{
"1_00":{"type": 2, "serverPath": "http://another.meme.website/"}
"1_01":{"type": 2, "serverPath": "http://yet.another.website.com/memes"}
},
etc..
}
and I want to reference one of the element in that file:
let appList = require('./config/appList.json');
...
var uri = appList.ABCD.1_99.serverPath;
where element name "ABCD" and "1_99" comes from another object and it's not always the same, say:
var uri = appList. [httpPOSTRequest.app_id] . [httpPOSTRequest.app_ver] . serverPath;
which I wonder if there's any way that can do so please.
You can loop through your appList or you can use other libraries like (https://lodash.com/). I have implemented it with simple loop
let appList = {
"ABCD": {
"1_99": {
"type": 3,
"serverPath": "http://some.website.com"
}
},
"EFGH": {
"1_00": {
"type": 2,
"serverPath": "http://another.meme.website/"
}
}
}
Object.keys(appList).map((d,i)=>{
Object.keys(appList[d]).map((data, index)=>{
console.log(`server path ${i} : ${appList[d][data].serverPath}`);
})
})
You can encapsulate your search properties in a search object, then use this to access your appList object using JavaScript bracket notation.
I've wrapped this up in a getServerPath function which also conveys the intent of the exercise.
We'll return null if we can't find the path in question.
Also, bear in mind, there is a very useful function in the lodash library _.get which can do an awful lot of this stuff for you, I've included an example below.
I hope this helps you!
// Get the required server path given the searchInput object
function getServerPath(appList, searchInput) {
if (!searchInput) return null;
if (!appList[searchInput.property1]) return null;
if (!appList[searchInput.property1][searchInput.property2]) return null;
return appList[searchInput.property1][searchInput.property2].serverPath;
}
// In Node.js we would use require('file.json') to define this.
let appList = {
"ABCD": {
"1_99": {
"type": 3,
"serverPath": "http://some.website.com"
}
},
"EFGH": {
"1_00": {
"type": 2,
"serverPath": "http://another.meme.website/"
}
}
}
// Search object input
let searchInput1 = { property1: "ABCD", property2: "1_99" };
let searchInput2 = { property1: "EFGH", property2: "1_00" };
let searchInput3 = { property1: "DOESNTEXIST", property2: "1_00" };
console.log("Server path 1:", getServerPath(appList, searchInput1));
console.log("Server path 2:", getServerPath(appList, searchInput2));
console.log("Server path 3:", getServerPath(appList, searchInput3));
// Using the very useful lodash _.get
console.log("Server path (using lodash _.get):", _.get(appList, "ABCD.1_99.serverPath"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

'keyboardDidHide' returns null instead of an object

I'm currently working on a react-native app and I'm trying to animate the layout of the login-screen when a keyboard is shown.
To track the state of the keyboard, I'm using this code:
componentDidMount() {
this.keyboardDidShowSub = Keyboard.addListener('keyboardDidShow', (event) => console.log(event));
this.keyboardDidHideSub = Keyboard.addListener('keyboardDidHide', (event) => console.log(event));
}
keyboardDidShow is working and returning:
Object {
"endCoordinates": Object {
"height": 286,
"screenX": 0,
"screenY": 354,
"width": 360,
},
}
However, keyboardDidHide is NOT working and returning null.
What could cause my problem? Thank you so much for your help!!
This is expected behaviour in Android. If you look at the underlying native code that is called when the keyboard is shown/hidden you can see what is sent back to the javascript side.
private void checkForKeyboardEvents() {
getRootView().getWindowVisibleDisplayFrame(mVisibleViewArea);
final int heightDiff =
DisplayMetricsHolder.getWindowDisplayMetrics().heightPixels - mVisibleViewArea.bottom;
if (mKeyboardHeight != heightDiff && heightDiff > mMinKeyboardHeightDetected) {
// keyboard is now showing, or the keyboard height has changed
mKeyboardHeight = heightDiff;
WritableMap params = Arguments.createMap();
WritableMap coordinates = Arguments.createMap();
coordinates.putDouble("screenY", PixelUtil.toDIPFromPixel(mVisibleViewArea.bottom));
coordinates.putDouble("screenX", PixelUtil.toDIPFromPixel(mVisibleViewArea.left));
coordinates.putDouble("width", PixelUtil.toDIPFromPixel(mVisibleViewArea.width()));
coordinates.putDouble("height", PixelUtil.toDIPFromPixel(mKeyboardHeight));
params.putMap("endCoordinates", coordinates);
sendEvent("keyboardDidShow", params);
} else if (mKeyboardHeight != 0 && heightDiff <= mMinKeyboardHeightDetected) {
// keyboard is now hidden
mKeyboardHeight = 0;
sendEvent("keyboardDidHide", null); // <- you can see here that when the keyboard is hidden it sends back null
}
}
It is worthwhile noting that in iOS that 'keyboardWillShow', 'keyboardDidShow', 'keyboardWillHide' and 'keyboardDidHide' will return an object.

adding an assign function as property to an object in NodeJs

for the sake of fun and exploring nodeJS I made an object
var f15c = {
fuel : 10000,
IRST: true,
AESA: true,
speed: 2500,
Ammo:
{
AMRAAM: 6,
Python5: 2,
Delilah: 3,
},
tailnumber : the question begins here.
}
The problem came when I wanted to add tailnumber that is not the same for every plane but should be assigned to the plane.
what is the methode?
var f15c = {
...
tailnumber = function (tn){"whats should i add here?"}
}
or
var f15c = {
...
tailnumber: ?? what should i place here?
SetTailNumber = function(tn)
{
tailnumber=tn;
}
}
or must I have the entire F15c as a function?
var f15c = function(tn) {
...
tailnumber = tn;
but then i cannot set the entire variables complex.
or perhaps I'm doing it wrong and should refer the variable as an individual F15 and use a different function to create it?
but then how do I make that field in a way it is unassigned and waiting to be assigned (and then saves the assigned number)?
would appreciate some heads up
The secret is to use this to refer to a property of the own object
var f15c = {
...
tailnumber: null,
setTailNumber : function(tn)
{
this.tailnumber=tn;
}
}
Then:
f15c.setTailNumber(1234);
console.log(f15c.tailnumber);
Do you mean you want to set a value to a property?
var f15c = {
_tailnumber: 0,
set tailnumber(newtailnumber) {
this._tailnumber = newtailnumber;
},
get tailnumber() {
return this._tailnumber
}
};
f15c.tailnumber = "304";
console.log(f15c.tailnumber);
console.log(f15c);

YUI, instantiable module that is not a widget?

If I want a module that is instantiable, let say, a module that handles storing preferences in a subcookies, and i want the main cookie to be configurable, but i don't want it to be a widget... what patterns should i use with YUI?
the end code should be something:
Y.use('my-pref-manager', function(Y){
var A = Y.my-pref-manager.prefStore('A"),
B = Y.my-pref-manager.prefStore('B");
// A and B are now loaded with the contents of cookies A and B, if they exist
A.set('xy', 123 );
});
So far i either found patterns that create widgets within my-module or i have to use methods directly in my-method which will be globals and lack initializers, etc.
There is a bunch of ways of doing this. You could do it using Y.Base.create, like below. The code might not be production ready, or even working properly, but hopefully it answers how you can create a module without it being a Widget.
The code below creates a module that extends Y.Base. This let us use Attributes and other cool things. Check the doc for Y.Base.
YUI.add('my-pref-manager', function (Y) {
var PrefManager = Y.Base.create('myPrefManager', Y.Base, [], {
initializer: function () {
this.after('prefsChange', this.changePref);
},
changePref: function (e) {
Y.Cookie.setSub(this.get('prefStore'), e.subAttrName, this.get(e.subAttrName));
},
setPref: function (name, val) {
this.set('prefs.'+name, val);
},
getPref: function (name) {
return this.get('prefs.'+name);
}
}, {
ATTRS: {
prefStore: {
value: null,
setter: function (val) {
return Y.Cookie.set(val, val);
}
},
prefs: {
value: {}
}
}
});
Y.namespace('My').PrefManager = PrefManager;
}, '0.0.1', {
requires: ['base', 'cookie']
});
YUI().use('my-pref-manager', function (Y) {
var A = new Y.My.PrefManager({prefStore: 'userPrefs'}),
B = new Y.My.PrefManager({prefStore: 'displayPrefs'});
A.setPref('x', 3);
A.setPref('y', 54);
B.setPref('tty', 7);
console.log(A.getPref('x')); // 3
});
Try it out: http://jsfiddle.net/B62nu/

Resources