Comparing version 20.0.0 to 20.1.0
# CHANGELOG | ||
## 20.1.0 | ||
Create dynamically colored sprites lazily only when used by `b.style`. Should make first start of big applications much faster. | ||
Maybe sprite speed up by remembering ImageData instead of Image. | ||
## 20.0.0 | ||
@@ -4,0 +9,0 @@ |
{ | ||
"name": "bobril", | ||
"version": "20.0.0", | ||
"version": "20.1.0", | ||
"description": "Component Oriented MVC Framework with virtual DOM and CSS", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -221,2 +221,3 @@ import { CSSStyles, CSSPseudoStyles, CSSStylesItem, CSSInlineStyles } from "./cssTypes"; | ||
lastUrl: string; | ||
used: boolean; | ||
} | ||
@@ -250,4 +251,5 @@ | ||
var svgSprites = new Map<string, ColorlessSprite>(); | ||
var unusedBundled = new Map<string, IResponsiveDynamicSprite>(); | ||
var bundledDynamicSprites: IResponsiveDynamicSprite[] = []; | ||
var imageCache: { [url: string]: HTMLImageElement | null } = newHashObj(); | ||
var imageCache: { [url: string]: ImageData | null } = newHashObj(); | ||
var injectedCss = ""; | ||
@@ -357,3 +359,3 @@ var rebuildStyles = false; | ||
loadImage(lastSpriteUrl, (image) => { | ||
imageCache[lastSpriteUrl] = image; | ||
imageCache[lastSpriteUrl] = getImageData(image); | ||
invalidateStyles(); | ||
@@ -365,2 +367,3 @@ }); | ||
let dynSprite = bundledDynamicSprites[i]!; | ||
if (!dynSprite.used) continue; | ||
let colorStr = dynSprite.color; | ||
@@ -548,2 +551,7 @@ if (!isString(colorStr)) colorStr = colorStr(); | ||
} else if (isString(s)) { | ||
if (unusedBundled.has(s)) { | ||
unusedBundled.get(s)!.used = true; | ||
unusedBundled.delete(s); | ||
rebuildStyles = true; | ||
} | ||
var sd = allStyles[s]; | ||
@@ -748,4 +756,19 @@ if (sd != undefined) { | ||
function createCanvas(width: number, height: number): [HTMLCanvasElement, CanvasRenderingContext2D] { | ||
var canvas = document.createElement("canvas"); | ||
canvas.width = width; | ||
canvas.height = height; | ||
return [canvas, <CanvasRenderingContext2D>canvas.getContext("2d")]; | ||
} | ||
function getImageData(image: HTMLImageElement): ImageData { | ||
let width = image.naturalWidth; | ||
let height = image.naturalHeight; | ||
let ctx = createCanvas(width, height)[1]; | ||
ctx.drawImage(image, 0, 0); | ||
return ctx.getImageData(0, 0, width, height); | ||
} | ||
function recolorAndClip( | ||
image: HTMLImageElement, | ||
imageData: ImageData, | ||
colorStr: string, | ||
@@ -757,9 +780,5 @@ width: number, | ||
): string { | ||
var canvas = document.createElement("canvas"); | ||
canvas.width = width; | ||
canvas.height = height; | ||
var ctx = <CanvasRenderingContext2D>canvas.getContext("2d"); | ||
ctx.drawImage(image, -left, -top); | ||
var imgData = ctx.getImageData(0, 0, width, height); | ||
var imgDataData = imgData.data; | ||
let [canvas, ctx] = createCanvas(width, height); | ||
let imgData = ctx.createImageData(width, height); | ||
let imgDataData = imgData.data; | ||
let rgba = rgbaRegex.exec(colorStr); | ||
@@ -773,9 +792,22 @@ let cRed: number, cGreen: number, cBlue: number, cAlpha: number; | ||
} else { | ||
cRed = parseInt(colorStr.substr(1, 2), 16); | ||
cGreen = parseInt(colorStr.substr(3, 2), 16); | ||
cBlue = parseInt(colorStr.substr(5, 2), 16); | ||
cAlpha = parseInt(colorStr.substr(7, 2), 16) || 0xff; | ||
cRed = parseInt(colorStr.slice(1, 3), 16); | ||
cGreen = parseInt(colorStr.slice(3, 5), 16); | ||
cBlue = parseInt(colorStr.slice(5, 7), 16); | ||
cAlpha = parseInt(colorStr.slice(7, 9), 16) || 0xff; | ||
} | ||
let targetOffset = 0; | ||
let targetStride = 4 * width; | ||
let sourceData = imageData.data; | ||
let sourceStride = 4 * imageData.width; | ||
let sourceOffset = left * 4 + top * sourceStride; | ||
for (let y = 0; y < height; y++) { | ||
imgDataData | ||
.subarray(targetOffset, targetOffset + targetStride) | ||
.set(sourceData.subarray(sourceOffset, sourceOffset + targetStride)); | ||
targetOffset += targetStride; | ||
sourceOffset += sourceStride; | ||
} | ||
if (cAlpha === 0xff) { | ||
for (var i = 0; i < imgDataData.length; i += 4) { | ||
for (let i = 0; i < imgDataData.length; i += 4) { | ||
// Horrible workaround for imprecisions due to browsers using premultiplied alpha internally for canvas | ||
@@ -794,3 +826,3 @@ let red = imgDataData[i]!; | ||
} else { | ||
for (var i = 0; i < imgDataData.length; i += 4) { | ||
for (let i = 0; i < imgDataData.length; i += 4) { | ||
let red = imgDataData[i]!; | ||
@@ -890,3 +922,3 @@ let alpha = imgDataData[i + 3]!; | ||
loadImage(url, (image) => { | ||
imageCache[url] = image; | ||
imageCache[url] = getImageData(image); | ||
invalidateStyles(); | ||
@@ -901,3 +933,10 @@ }); | ||
if (color != undefined) { | ||
spDef.url = recolorAndClip(image, <string>color, spDef.width, spDef.height, spDef.left, spDef.top); | ||
spDef.url = recolorAndClip( | ||
getImageData(image), | ||
color as string, | ||
spDef.width, | ||
spDef.height, | ||
spDef.left, | ||
spDef.top | ||
); | ||
spDef.left = 0; | ||
@@ -1059,3 +1098,3 @@ spDef.top = 0; | ||
var key = colorId + ":" + width + ":" + height + ":" + left + ":" + top; | ||
var spDef = bundledSprites[key]; | ||
var spDef = bundledSprites[key] as IResponsiveDynamicSprite; | ||
if (spDef) return spDef.styleId; | ||
@@ -1070,8 +1109,10 @@ hasBundledSprites = true; | ||
top, | ||
used: false, | ||
color, | ||
lastColor: "", | ||
lastUrl: "", | ||
}; | ||
(<IResponsiveDynamicSprite>spDef).color = color; | ||
(<IResponsiveDynamicSprite>spDef).lastColor = ""; | ||
(<IResponsiveDynamicSprite>spDef).lastUrl = ""; | ||
bundledDynamicSprites.push(<IResponsiveDynamicSprite>spDef); | ||
bundledDynamicSprites.push(spDef); | ||
bundledSprites[key] = spDef; | ||
unusedBundled.set(styleId, spDef); | ||
return styleId; | ||
@@ -1078,0 +1119,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
390505
9296