nativescript-toolbox-sw
Version:
Fork of nativescript-toolbox - A NativeScript module that is a composition of useful classes, tools and helpers.
541 lines (432 loc) • 16.4 kB
JavaScript
// The MIT License (MIT)
//
// Copyright (c) Marcel Joachim Kloubert <marcel.kloubert@gmx.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
var BitmapFactoryCommons = require('./BitmapFactory.commons');
var ImageSource = require('image-source');
var TypeUtils = require("utils/types");
// default options
var defaultOptions;
function getDefaultOpts() {
return defaultOptions;
}
exports.getDefaultOpts = getDefaultOpts;
function setDefaultOpts(opts) {
defaultOptions = opts;
}
exports.setDefaultOpts = setDefaultOpts;
function iOSImage(uiImage, opts) {
if (!(this instanceof iOSImage)) {
return new iOSImage(uiImage, opts);
}
this._isDisposed = false;
this._nativeObject = uiImage;
this._options = opts;
}
exports.BitmapClass = iOSImage;
// [iOS INTERNAL] __CGImage
Object.defineProperty(iOSImage.prototype, '__CGImage', {
get: function() { return this._nativeObject.CGImage; }
});
// [iOS INTERNAL] __doAutoRelease
Object.defineProperty(iOSImage.prototype, '__doAutoRelease', {
get: function() {
var autoRelease = true;
var opts = this._options || {};
if (!TypeUtils.isNullOrUndefined(opts.ios)) {
if (!TypeUtils.isNullOrUndefined(opts.ios.autoRelease)) {
autoRelease = !!opts.ios.autoRelease;
}
}
return autoRelease;
}
});
// [iOS INTERNAL] __onImageContext()
iOSImage.prototype.__onImageContext = function(action, tag) {
var oldImg = this._nativeObject;
UIGraphicsBeginImageContext(CGSizeMake(oldImg.size.width, oldImg.size.height));
var newImage;
var result;
try {
var context = UIGraphicsGetCurrentContext();
oldImg.drawInRect(CGRectMake(0, 0,
oldImg.size.width, oldImg.size.height));
result = action(context, tag, oldImg);
newImage = UIGraphicsGetImageFromCurrentImageContext();
}
finally {
UIGraphicsEndImageContext();
}
this._nativeObject = newImage;
// free memory of old image
try {
var cImg = oldImg.CGImage;
try {
if (!TypeUtils.isNullOrUndefined(cImg)) {
if (!this.__doAutoRelease) {
CGImageRelease(oldImg.CGImage); // invoke manually
}
}
}
finally {
cImg = null;
}
}
finally {
oldImg = null;
}
return result;
};
// [iOS INTERNAL] __toIOSColor()
iOSImage.prototype.__toIOSColor = function(color) {
if (TypeUtils.isNullOrUndefined(color)) {
return null;
}
return {
a: color.a / 255.0,
r: color.r / 255.0,
g: color.g / 255.0,
b: color.b / 255.0
};
};
// [INTERNAL] _clone()
iOSImage.prototype._clone = function() {
return new iOSImage(UIImage.imageWithData(UIImagePNGRepresentation(this._nativeObject)));
};
// [INTERNAL] _crop()
iOSImage.prototype._crop = function(leftTop, size) {
return this.__onImageContext(function(context, tag, oldImage) {
var rect = CGRectMake(leftTop.x, leftTop.y,
size.width, size.height);
var imageRef = CGImageCreateWithImageInRect(oldImage.CGImage, rect);
return UIImage(imageRef);
});
};
// _dispose()
iOSImage.prototype._dispose = function(action, tag) {
var nObj = this._nativeObject;
try {
if (!TypeUtils.isNullOrUndefined(nObj)) {
var cImg = nObj.CGImage;
try {
if (!TypeUtils.isNullOrUndefined(cImg)) {
if (!this.__doAutoRelease) {
CGImageRelease(cImg);
}
}
}
finally {
cImg = null;
}
}
}
finally {
this._nativeObject = null;
nObj = null;
}
};
// [INTERNAL] _drawLine()
iOSImage.prototype._drawLine = function(start, end, color) {
color = this.__toIOSColor(color);
this.__onImageContext(function(context, tag, oldImage) {
CGContextSetRGBStrokeColor(context,
color.r, color.g, color.b, color.a);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, start.x, start.y);
CGContextAddLineToPoint(context,
end.x, end.y);
CGContextStrokePath(context);
});
};
// [INTERNAL] _drawOval()
iOSImage.prototype._drawOval = function(size, leftTop, color, fillColor) {
color = this.__toIOSColor(color);
fillColor = this.__toIOSColor(fillColor);
this.__onImageContext(function(context, tag, oldImage) {
CGContextSetRGBStrokeColor(context,
color.r, color.g, color.b, color.a);
var rect = CGRectMake(leftTop.x, leftTop.y,
size.width, size.height);
if (null !== fillColor) {
CGContextSetRGBFillColor(context,
fillColor.r, fillColor.g, fillColor.b, fillColor.a);
CGContextFillEllipseInRect(context, rect);
}
CGContextStrokeEllipseInRect(context, rect);
});
};
// [INTERNAL] _drawArc()
iOSImage.prototype._drawArc = function(size, leftTop, startAngle, endAngle, color, fillColor) {
color = this.__toIOSColor(color);
fillColor = this.__toIOSColor(fillColor);
// Angles come in degrees, convert to radians for iOS
var iosStartAngle = startAngle*(Math.PI/180.0);
// We get a sweep angle, add to start angle to get iOS end angle
var iosEndAngle = iosStartAngle + endAngle*(Math.PI/180.0);
this.__onImageContext(function(context, tag, oldImage) {
CGContextSetRGBStrokeColor(context,
color.r, color.g, color.b, color.a);
var radius = Math.min(size.width, size.height)*0.5
if (null !== fillColor) {
CGContextSetRGBFillColor(context,
fillColor.r, fillColor.g, fillColor.b, fillColor.a);
}
CGContextMoveToPoint(context, (size.width*0.5)+leftTop.x, (size.height*0.5)+leftTop.y);
CGContextAddArc(context, (size.width*0.5)+leftTop.x, (size.height*0.5)+leftTop.y, radius, iosStartAngle, iosEndAngle, 0);
if (null !== fillColor) {
CGContextFillPath(context);
}
});
};
// [INTERNAL] _drawRect()
iOSImage.prototype._drawRect = function(size, leftTop, color, fillColor) {
color = this.__toIOSColor(color);
fillColor = this.__toIOSColor(fillColor);
this.__onImageContext(function(context, tag, oldImage) {
CGContextSetRGBStrokeColor(context,
color.r, color.g, color.b, color.a);
var rect = CGRectMake(leftTop.x, leftTop.y,
size.width, size.height);
if (null !== fillColor) {
CGContextSetRGBFillColor(context,
fillColor.r, fillColor.g, fillColor.b, fillColor.a);
CGContextFillRect(context, rect);
}
CGContextStrokeRect(context, rect);
});
};
// [INTERNAL] _getPoint()
iOSImage.prototype._getPoint = function(coordinates) {
var pixelData = CGDataProviderCopyData(CGImageGetDataProvider(this.__CGImage));
var data = CFDataGetBytePtr(pixelData);
var pixelInfo = ((this.width * coordinates.y) + coordinates.x) * 4;
var r = data[pixelInfo];
var g = data[pixelInfo + 1];
var b = data[pixelInfo + 2];
var a = data[pixelInfo + 3];
return (a << 24) | (r << 16) | (g << 8) | b;
};
// [INTERNAL] _insert()
iOSImage.prototype._insert = function(other, leftTop) {
var bmp = asBitmapObject(other);
if (false === bmp) {
throw "NO valid bitmap!";
}
this.__onImageContext(function(context, tag, oldImage) {
var left = leftTop.x;
var top = leftTop.y;
var width = Math.min(bmp.width,
oldImage.size.width - left);
var height = Math.min(bmp.height,
oldImage.size.height - top);
bmp._nativeObject
.drawInRect(CGRectMake(leftTop.x, leftTop.y,
width, height));
});
};
// [INTERNAL] _resize()
iOSImage.prototype._resize = function(newSize) {
var oldImg = this._nativeObject;
try {
var ns = CGSizeMake(newSize.width, newSize.height);
UIGraphicsBeginImageContextWithOptions(ns, false, 0.0);
oldImg.drawInRect(CGRectMake(0, 0,
ns.width, ns.height));
return new iOSImage(UIGraphicsGetImageFromCurrentImageContext());
}
finally {
UIGraphicsEndImageContext();
}
};
// [INTERNAL] _rotate()
iOSImage.prototype._rotate = function(degrees) {
radians = degrees * Math.PI / 180.0;
var oldImg = this._nativeObject;
try {
UIGraphicsBeginImageContext(oldImg.size);
var context = UIGraphicsGetCurrentContext();
CGContextRotateCTM(context, radians);
oldImg.drawAtPoint(CGPointMake(0, 0));
return UIGraphicsGetImageFromCurrentImageContext();
}
finally {
UIGraphicsEndImageContext();
}
};
// [INTERNAL] _setPoint()
iOSImage.prototype._setPoint = function(coordinates, color) {
color = this.__toIOSColor(color);
this.__onImageContext(function(context) {
CGContextSetRGBFillColor(context, color.r, color.g, color.b, color.a);
CGContextFillRect(context, CGRectMake(coordinates.x, coordinates.y,
1, 1));
});
};
// [INTERNAL] _toObject()
iOSImage.prototype._toObject = function(format, quality) {
var img = this._nativeObject;
var imageData = false;
var mime;
switch (format) {
case 1:
imageData = UIImagePNGRepresentation(img);
mime = 'image/png';
break;
case 2:
imageData = UIImageJPEGRepresentation(img, quality / 100.0);
mime = 'image/jpeg';
break;
}
if (false === imageData) {
throw "Format '" + format + "' is NOT supported!";
}
if (TypeUtils.isNullOrUndefined(imageData)) {
throw "Output image could not be created by iOS!";
}
var bitmapData = {};
var base64 = imageData.base64EncodedStringWithOptions(null);
// base64
Object.defineProperty(bitmapData, 'base64', {
get: function() { return base64; }
});
// mime
Object.defineProperty(bitmapData, 'mime', {
get: function() { return mime; }
});
return bitmapData;
}
// _writeText()
iOSImage.prototype._writeText = function(txt, leftTop, font) {
var antiAlias;
var fontColor;
var fontSize;
var fontName;
if (null !== font) {
fontColor = font.color;
fontSize = font.size;
fontName = font.name;
}
fontColor = this.normalizeColor(fontColor);
fontColor = this.__toIOSColor(fontColor);
if (TypeUtils.isNullOrUndefined(antiAlias)) {
antiAlias = true;
}
var settings = NSMutableAttributedString.alloc().initWithString(txt);
var settingsRange = NSMakeRange(0, settings.length);
if (null !== fontColor) {
var iosFontColor = UIColor.alloc()
.initWithRedGreenBlueAlpha(fontColor.r, fontColor.g, fontColor.b,
fontColor.a);
settings.addAttributeValueRange(NSForegroundColorAttributeName,
iosFontColor,
settingsRange);
}
if (TypeUtils.isNullOrUndefined(fontSize)) {
fontSize = 10;
}
var iosFont;
if (!TypeUtils.isNullOrUndefined(fontName)) {
fontName = ('' + fontName).trim();
if ('' !== fontName) {
iosFont = UIFont.fontWithNameSize(fontName, fontSize);
}
}
if (TypeUtils.isNullOrUndefined(iosFont)) {
iosFont = UIFont.systemFontOfSize(fontSize);
}
settings.addAttributeValueRange(NSFontAttributeName, iosFont,
settingsRange);
this.__onImageContext(function(context, tag, oldImage) {
if (antiAlias) {
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
}
var rect = CGRectMake(leftTop.x, leftTop.y,
oldImage.size.width, oldImage.size.height);
settings.drawInRect(CGRectIntegral(rect));
});
};
// height
Object.defineProperty(iOSImage.prototype, 'height', {
get: function() { return this._nativeObject.size.height; }
});
// isDisposed
Object.defineProperty(iOSImage.prototype, 'isDisposed', {
get: function() { return this._isDisposed; }
});
// nativeObject
Object.defineProperty(iOSImage.prototype, 'nativeObject', {
get: function() { return this._nativeObject; }
});
// width
Object.defineProperty(iOSImage.prototype, 'width', {
get: function() { return this._nativeObject.size.width; }
});
// setup common methods and properties
BitmapFactoryCommons.setupBitmapClass(iOSImage);
function asBitmapObject(v) {
var bmp = BitmapFactoryCommons.tryGetBitmapObject(iOSImage, v);
if (false !== bmp) {
return bmp;
}
var opts = defaultOptions;
if (!opts) {
opts = {};
}
if (typeof v === "string") {
var data = NSData.alloc()
.initWithBase64Encoding(v);
var img = UIImage.imageWithData(data);
return new iOSImage(img, opts);
}
else if (v instanceof UIImage) {
return new iOSImage(v, opts);
}
else if (v instanceof ImageSource.ImageSource) {
return new iOSImage(v.ios, opts);
}
return false;
}
exports.asBitmapObject = asBitmapObject;
iOSImage.asBitmap = asBitmapObject;
function createBitmap(width, height, opts) {
var img = new interop.Reference();
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), false, 0.0);
img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (TypeUtils.isNullOrUndefined(img)) {
throw "Could not create UIImage!";
}
return new iOSImage(img, opts);
}
exports.createBitmap = createBitmap;
function makeBitmapMutable(uiImg, opts) {
if (uiImg instanceof ImageSource.ImageSource) {
return new makeBitmapMutable(uiImg.ios, opts);
}
if (uiImg instanceof iOSImage) {
return new makeBitmapMutable(uiImg.nativeObject, opts);
}
if (!(uiImg instanceof UIImage)) {
throw "No valid image object!";
}
return UIImage.imageWithData(UIImagePNGRepresentation(uiImg));
}
exports.makeBitmapMutable = makeBitmapMutable;