var GetBitmapTextSize = function (src, round, updateOrigin, out){ if (updateOrigin === undefined) { updateOrigin = false ; } if (out === undefined) { out = { local: { x: 0, y: 0, width: 0, height: 0} , global: { x: 0, y: 0, width: 0, height: 0} , lines: { shortest: 0, longest: 0, lengths: null , height: 0} , wrappedText: '', words: [] , characters: [] , scaleX: 0, scaleY: 0} ; return out; } var text = src.text; var textLength = _AN_Read_length('length', text); var maxWidth = src.maxWidth; var wordWrapCharCode = src.wordWrapCharCode; var bx = Number.MAX_VALUE; var by = Number.MAX_VALUE; var bw = 0; var bh = 0; var chars = src.fontData.chars; var lineHeight = src.fontData.lineHeight; var letterSpacing = src.letterSpacing; var xAdvance = 0; var yAdvance = 0; var charCode = 0; var glyph = null ; var align = src._align; var x = 0; var y = 0; var scale = (src.fontSize / src.fontData.size); var sx = scale * src.scaleX; var sy = scale * src.scaleY; var lastGlyph = null ; var lastCharCode = 0; var lineWidths = [] ; var shortestLine = Number.MAX_VALUE; var longestLine = 0; var currentLine = 0; var currentLineWidth = 0; var i; var words = [] ; var characters = [] ; var current = null ; if (maxWidth > 0) { for (i = 0; i < textLength; i++ ){ charCode = text.charCodeAt(i); if (charCode === 10) { if (current !== null ) { words.push({ word: current.word, i: current.i, x: current.x * sx, y: current.y * sy, w: current.w * sx, h: current.h * sy, cr: true } ); current = null ; } xAdvance = 0; yAdvance += lineHeight; lastGlyph = null ; continue ; } glyph = chars[charCode]; if (!glyph) { continue ; } if (lastGlyph !== null ) { var glyphKerningOffset = glyph.kerning[lastCharCode]; } if (charCode === wordWrapCharCode) { if (current !== null ) { words.push({ word: current.word, i: current.i, x: current.x * sx, y: current.y * sy, w: current.w * sx, h: current.h * sy, cr: false } ); current = null ; } } else { if (current === null ) { current = { word: '', i: i, x: xAdvance, y: yAdvance, w: 0, h: lineHeight, cr: false } ; } current.word = current.word.concat(text[i]); current.w += glyph.xOffset + glyph.xAdvance + ((glyphKerningOffset !== undefined)? glyphKerningOffset: 0); } xAdvance += glyph.xAdvance + letterSpacing; lastGlyph = glyph; lastCharCode = charCode; } if (current !== null ) { words.push({ word: current.word, i: current.i, x: current.x * sx, y: current.y * sy, w: current.w * sx, h: current.h * sy, cr: false } ); } xAdvance = 0; yAdvance = 0; lastGlyph = null ; lastCharCode = 0; var prev; var offset = 0; var crs = [] ; for (i = 0; i < _AN_Read_length('length', words); i++ ){ var entry = words[i]; var left = entry.x; var right = entry.x + entry.w; if (prev) { var diff = left - (prev.x + prev.w); offset = left - (diff + prev.w); prev = null ; } var checkLeft = left - offset; var checkRight = right - offset; if (checkLeft > maxWidth || checkRight > maxWidth) { crs.push(entry.i - 1); if (entry.cr) { crs.push(entry.i + _AN_Read_length('length', entry.word)); offset = 0; prev = null ; } else { prev = entry; } } else if (entry.cr) { crs.push(entry.i + _AN_Read_length('length', entry.word)); offset = 0; prev = null ; } } var stringInsert = function (str, index, value){ return str.substr(0, index) + value + str.substr(index + 1); } ; for (i = _AN_Read_length('length', crs) - 1; i >= 0; i-- ){ text = stringInsert(text, crs[i], "\n"); } out.wrappedText = text; textLength = _AN_Read_length("length", text); words = [] ; current = null ; } var charIndex = 0; for (i = 0; i < textLength; i++ ){ charCode = text.charCodeAt(i); if (charCode === 10) { if (current !== null ) { words.push({ word: current.word, i: current.i, x: current.x * sx, y: current.y * sy, w: current.w * sx, h: current.h * sy} ); current = null ; } xAdvance = 0; yAdvance += lineHeight; lastGlyph = null ; lineWidths[currentLine] = currentLineWidth; if (currentLineWidth > longestLine) { longestLine = currentLineWidth; } if (currentLineWidth < shortestLine) { shortestLine = currentLineWidth; } currentLine++ ; currentLineWidth = 0; continue ; } glyph = chars[charCode]; if (!glyph) { continue ; } x = xAdvance; y = yAdvance; if (lastGlyph !== null ) { var kerningOffset = glyph.kerning[lastCharCode]; x += (kerningOffset !== undefined)? kerningOffset: 0; } if (bx > x) { bx = x; } if (by > y) { by = y; } var gw = x + glyph.xAdvance; var gh = y + lineHeight; if (bw < gw) { bw = gw; } if (bh < gh) { bh = gh; } var charWidth = glyph.xOffset + glyph.xAdvance + ((kerningOffset !== undefined)? kerningOffset: 0); if (charCode === wordWrapCharCode) { if (current !== null ) { words.push({ word: current.word, i: current.i, x: current.x * sx, y: current.y * sy, w: current.w * sx, h: current.h * sy} ); current = null ; } } else { if (current === null ) { current = { word: '', i: charIndex, x: xAdvance, y: yAdvance, w: 0, h: lineHeight} ; } current.word = current.word.concat(text[i]); current.w += charWidth; } characters.push({ i: charIndex, char: text[i], code: charCode, x: (glyph.xOffset + xAdvance) * scale, y: (glyph.yOffset + yAdvance) * scale, w: glyph.width * scale, h: glyph.height * scale, t: yAdvance * scale, r: gw * scale, b: lineHeight * scale, line: currentLine, glyph: glyph} ); xAdvance += glyph.xAdvance + letterSpacing; lastGlyph = glyph; lastCharCode = charCode; currentLineWidth = gw * scale; charIndex++ ; } if (current !== null ) { words.push({ word: current.word, i: current.i, x: current.x * sx, y: current.y * sy, w: current.w * sx, h: current.h * sy} ); } lineWidths[currentLine] = currentLineWidth; if (currentLineWidth > longestLine) { longestLine = currentLineWidth; } if (currentLineWidth < shortestLine) { shortestLine = currentLineWidth; } if (align > 0) { for (var c = 0; c < _AN_Read_length('length', characters); c++ ){ var currentChar = characters[c]; if (align === 1) { var ax1 = ((longestLine - lineWidths[currentChar.line]) / 2); currentChar.x += ax1; currentChar.r += ax1; } else if (align === 2) { var ax2 = (longestLine - lineWidths[currentChar.line]); currentChar.x += ax2; currentChar.r += ax2; } } } var local = out.local; var global = out.global; var lines = out.lines; local.x = bx * scale; local.y = by * scale; local.width = bw * scale; local.height = bh * scale; global.x = (src.x - src._displayOriginX) + (bx * sx); global.y = (src.y - src._displayOriginY) + (by * sy); global.width = bw * sx; global.height = bh * sy; lines.shortest = shortestLine; lines.longest = longestLine; lines.lengths = lineWidths; if (round) { local.x = Math.ceil(local.x); local.y = Math.ceil(local.y); local.width = Math.ceil(local.width); local.height = Math.ceil(local.height); global.x = Math.ceil(global.x); global.y = Math.ceil(global.y); global.width = Math.ceil(global.width); global.height = Math.ceil(global.height); lines.shortest = Math.ceil(shortestLine); lines.longest = Math.ceil(longestLine); } if (updateOrigin) { src._displayOriginX = (src.originX * local.width); src._displayOriginY = (src.originY * local.height); global.x = src.x - (src._displayOriginX * src.scaleX); global.y = src.y - (src._displayOriginY * src.scaleY); if (round) { global.x = Math.ceil(global.x); global.y = Math.ceil(global.y); } } out.words = words; out.characters = characters; out.lines.height = lineHeight; out.scale = scale; out.scaleX = src.scaleX; out.scaleY = src.scaleY; return out; } ; module.exports = GetBitmapTextSize;