Skip to content
This repository was archived by the owner on Apr 21, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 62 additions & 17 deletions src/app/services/nty.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ class Nty {
*/
constructor($localStorage, Wallet) {
'ngInject';


this.MULTILINE_MODE = {
MATCH: 0,
SPLIT: 1
}
/**
* Service dependencies
*/
Expand Down Expand Up @@ -117,6 +121,52 @@ class Nty {
return this._Wallet.ntyData;
}

/**
* Utility function for drawCertificate
*/
_fillTextMultiline (context, text, x, y, mode, re, lineHeight, maxX = undefined) {
let self = this;
let posY = y;
let maxWidth = (maxX===undefined ? -1 : maxX-x);
let tokens = (mode===this.MULTILINE_MODE.MATCH ? text.match(re) : text.split(re));
let line = "";
tokens.forEach(token => {
if (maxWidth > 0) {
if (mode===this.MULTILINE_MODE.MATCH) {//one token per line
if (context.measureText(token).width <= maxWidth) {//token fits in the line
context.fillText(token, x, posY);
posY += lineHeight;
} else {//token doesn't fit in the line - split it further - fallback to char-by-char, recurse
posY = self._fillTextMultiline(context, token, x, posY, this.MULTILINE_MODE.SPLIT, new RegExp(''), lineHeight, maxX);
}
} else {//mode===this.MULTILINE_MODE.SPLIT; possibly more tokens per line
if (context.measureText(line+token).width <= maxWidth) {//next token fits in the line
line+=token;
} else {//next token doesn't fit onto the line; output line and try it again
if (line.length > 0) {
context.fillText(line, x, posY);
posY += lineHeight;
line = "";
}
if (context.measureText(token).width <= maxWidth || token.length <= 1) {//it fits now
line = token;
} else {//it still doesn't fit, need to break it further - fallback to char-by-char; recurse
posY = self._fillTextMultiline(context, token, x, posY, this.MULTILINE_MODE.SPLIT, new RegExp(''), lineHeight, maxX);
}
}
}
} else {//one token per line
context.fillText(token, x, posY);
posY += lineHeight;
}
});
if (line.length > 0) {
context.fillText(line, x, posY);
posY += lineHeight;
}
return posY;
}

/**
* Draw an apostille certificate
*/
Expand All @@ -131,32 +181,27 @@ class Nty {
context.canvas.height = imageObj.height;
context.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
context.font = "38px Roboto Arial sans-serif";

let qrX = 1687;
let qrY = 688;

// Top part
context.fillText(filename, 541, 756);
// Wrap filename - do not conflict with generated QR
this._fillTextMultiline(context, filename, 541, 756, this.MULTILINE_MODE.SPLIT, new RegExp(''), 38+5, qrX-5);
context.fillText(dateCreated, 607, 873);
context.fillText(owner, 458, 989);
context.fillText(tags, 426, 1105);
// Wrap tags - do not conflict with generated QR
this._fillTextMultiline(context, tags, 426, 1105, this.MULTILINE_MODE.SPLIT, new RegExp('([ ])'), 38+5, qrX-5);

// bottom part
// Bottom part
context.font = "30px Roboto Arial sans-serif";
context.fillText(from, 345, 1550);
context.fillText(to, 345, 1690);
context.fillText(recipientPrivateKey, 345, 1846);
context.fillText(txHash, 345, 1994);

// Wrap file hash if too long
if (txHex.length > 70) {
let x = 345;
let y = 2137;
let lineHeight = 35;
let lines = txHex.match(/.{1,70}/g)
for (var i = 0; i < lines.length; ++i) {
context.fillText(lines[i], x, y);
y += lineHeight;
}
} else {
context.fillText(txHex, 345, 2137);
}
this._fillTextMultiline(context, txHex, 345, 2137, this.MULTILINE_MODE.MATCH, new RegExp('.{1,70}', 'g'), 30+5);
let qr = qrcode(10, 'H');
qr.addData(url);
qr.make();
Expand All @@ -167,7 +212,7 @@ class Nty {
context.fillStyle = qr.isDark(row, col) ? "#000000" : "#ffffff";
let w = (Math.ceil((col+1)*tileW) - Math.floor(col*tileW));
let h = (Math.ceil((row+1)*tileW) - Math.floor(row*tileW));
context.fillRect(Math.round(col*tileW)+1687,Math.round(row*tileH)+688, w, h);
context.fillRect(Math.round(col*tileW)+qrX,Math.round(row*tileH)+qrY, w, h);
}
}
return resolve(canvas.toDataURL());
Expand Down
79 changes: 79 additions & 0 deletions tests/specs/ntyService.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
describe('Nty service tests', function() {
let $controller, $rootscope, Wallet, Nty, $localStorage;

beforeEach(angular.mock.module('app'));

beforeEach(angular.mock.inject(function( _$controller_, _$rootScope_, _Wallet_, _Nty_, _$localStorage_) {
$controller = _$controller_;
$rootscope = _$rootScope_;
Wallet = _Wallet_;
Nty = _Nty_;
$localStorage = _$localStorage_;
$localStorage.$reset();
}));

function createDummyContext() {
let context = {};
context.filledText = [];
context.fillText = function(text, x, y) {
context.filledText.push([text, x, y]);
}
context.measureText = function(text) {
return {
width: 10*text.length
};
}
context.clear = function() {
context.filledText = [];
}
return context;
}

//_fillTextMultiline = (context, text, x, y, mode, re, lineHeight, maxX = undefined)

it("Checks _fillTextMultiline utility function", function() {
var context = createDummyContext();
var y;

context.clear();
y = Nty._fillTextMultiline(context, "", 0, 0, Nty.MULTILINE_MODE.SPLIT, new RegExp(''), 7, undefined);
expect(y).toBe(0);
expect(context.filledText).toEqual([ ]);

context.clear();
y = Nty._fillTextMultiline(context, "", 0, 0, Nty.MULTILINE_MODE.SPLIT, new RegExp(''), 7, 30);
expect(y).toBe(0);
expect(context.filledText).toEqual([ ]);

context.clear();
y = Nty._fillTextMultiline(context, "hello world", 0, 0, Nty.MULTILINE_MODE.SPLIT, new RegExp(' '), 7, 30);
expect(y).toBe(28);
expect(context.filledText).toEqual([ [ 'hel', 0, 0 ], [ 'lo' , 0, 7 ], [ 'wor', 0, 14 ], [ 'ld', 0, 21 ] ]);

context.clear();
y = Nty._fillTextMultiline(context, "hello", 0, 0, Nty.MULTILINE_MODE.SPLIT, new RegExp(''), 7, 30);
expect(y).toBe(14);
expect(context.filledText).toEqual([ [ 'hel', 0, 0 ], [ 'lo', 0, 7 ] ]);

context.clear();
y = Nty._fillTextMultiline(context, "hello", 0, 0, Nty.MULTILINE_MODE.SPLIT, new RegExp(''), 7, undefined);
expect(y).toBe(35);
expect(context.filledText).toEqual([ [ 'h', 0, 0 ], [ 'e', 0, 7 ], [ 'l', 0, 14 ], [ 'l', 0, 21 ], [ 'o', 0, 28 ] ]);

context.clear();
y = Nty._fillTextMultiline(context, "hello", 0, 0, Nty.MULTILINE_MODE.SPLIT, new RegExp(''), 7, 30);
expect(y).toBe(14);
expect(context.filledText).toEqual([ [ 'hel', 0, 0 ], [ 'lo', 0, 7 ] ]);

context.clear();
y = Nty._fillTextMultiline(context, "hellohellohelloh", 0, 0, Nty.MULTILINE_MODE.MATCH, new RegExp('.{1,6}', 'g'), 7, undefined);
expect(y).toBe(21);
expect(context.filledText).toEqual([ [ 'helloh', 0, 0 ], [ 'ellohe', 0, 7 ], [ 'lloh', 0, 14 ] ]);

context.clear();
y = Nty._fillTextMultiline(context, "hellohellohelloh", 0, 0, Nty.MULTILINE_MODE.MATCH, new RegExp('.{1,6}', 'g'), 7, 50);
expect(y).toBe(35);
expect(context.filledText).toEqual([ [ 'hello', 0, 0 ], [ 'h' , 0, 7 ], [ 'elloh', 0, 14 ], [ 'e', 0, 21 ], [ 'lloh' , 0, 28] ]);
});

});