You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.3 KiB
170 lines
5.3 KiB
import BoundingRect from '../core/BoundingRect.js'; |
|
import LRU from '../core/LRU.js'; |
|
import { DEFAULT_FONT, platformApi } from '../core/platform.js'; |
|
var textWidthCache = {}; |
|
export function getWidth(text, font) { |
|
font = font || DEFAULT_FONT; |
|
var cacheOfFont = textWidthCache[font]; |
|
if (!cacheOfFont) { |
|
cacheOfFont = textWidthCache[font] = new LRU(500); |
|
} |
|
var width = cacheOfFont.get(text); |
|
if (width == null) { |
|
width = platformApi.measureText(text, font).width; |
|
cacheOfFont.put(text, width); |
|
} |
|
return width; |
|
} |
|
export function innerGetBoundingRect(text, font, textAlign, textBaseline) { |
|
var width = getWidth(text, font); |
|
var height = getLineHeight(font); |
|
var x = adjustTextX(0, width, textAlign); |
|
var y = adjustTextY(0, height, textBaseline); |
|
var rect = new BoundingRect(x, y, width, height); |
|
return rect; |
|
} |
|
export function getBoundingRect(text, font, textAlign, textBaseline) { |
|
var textLines = ((text || '') + '').split('\n'); |
|
var len = textLines.length; |
|
if (len === 1) { |
|
return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline); |
|
} |
|
else { |
|
var uniondRect = new BoundingRect(0, 0, 0, 0); |
|
for (var i = 0; i < textLines.length; i++) { |
|
var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline); |
|
i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect); |
|
} |
|
return uniondRect; |
|
} |
|
} |
|
export function adjustTextX(x, width, textAlign) { |
|
if (textAlign === 'right') { |
|
x -= width; |
|
} |
|
else if (textAlign === 'center') { |
|
x -= width / 2; |
|
} |
|
return x; |
|
} |
|
export function adjustTextY(y, height, verticalAlign) { |
|
if (verticalAlign === 'middle') { |
|
y -= height / 2; |
|
} |
|
else if (verticalAlign === 'bottom') { |
|
y -= height; |
|
} |
|
return y; |
|
} |
|
export function getLineHeight(font) { |
|
return getWidth('国', font); |
|
} |
|
export function measureText(text, font) { |
|
return platformApi.measureText(text, font); |
|
} |
|
export function parsePercent(value, maxValue) { |
|
if (typeof value === 'string') { |
|
if (value.lastIndexOf('%') >= 0) { |
|
return parseFloat(value) / 100 * maxValue; |
|
} |
|
return parseFloat(value); |
|
} |
|
return value; |
|
} |
|
export function calculateTextPosition(out, opts, rect) { |
|
var textPosition = opts.position || 'inside'; |
|
var distance = opts.distance != null ? opts.distance : 5; |
|
var height = rect.height; |
|
var width = rect.width; |
|
var halfHeight = height / 2; |
|
var x = rect.x; |
|
var y = rect.y; |
|
var textAlign = 'left'; |
|
var textVerticalAlign = 'top'; |
|
if (textPosition instanceof Array) { |
|
x += parsePercent(textPosition[0], rect.width); |
|
y += parsePercent(textPosition[1], rect.height); |
|
textAlign = null; |
|
textVerticalAlign = null; |
|
} |
|
else { |
|
switch (textPosition) { |
|
case 'left': |
|
x -= distance; |
|
y += halfHeight; |
|
textAlign = 'right'; |
|
textVerticalAlign = 'middle'; |
|
break; |
|
case 'right': |
|
x += distance + width; |
|
y += halfHeight; |
|
textVerticalAlign = 'middle'; |
|
break; |
|
case 'top': |
|
x += width / 2; |
|
y -= distance; |
|
textAlign = 'center'; |
|
textVerticalAlign = 'bottom'; |
|
break; |
|
case 'bottom': |
|
x += width / 2; |
|
y += height + distance; |
|
textAlign = 'center'; |
|
break; |
|
case 'inside': |
|
x += width / 2; |
|
y += halfHeight; |
|
textAlign = 'center'; |
|
textVerticalAlign = 'middle'; |
|
break; |
|
case 'insideLeft': |
|
x += distance; |
|
y += halfHeight; |
|
textVerticalAlign = 'middle'; |
|
break; |
|
case 'insideRight': |
|
x += width - distance; |
|
y += halfHeight; |
|
textAlign = 'right'; |
|
textVerticalAlign = 'middle'; |
|
break; |
|
case 'insideTop': |
|
x += width / 2; |
|
y += distance; |
|
textAlign = 'center'; |
|
break; |
|
case 'insideBottom': |
|
x += width / 2; |
|
y += height - distance; |
|
textAlign = 'center'; |
|
textVerticalAlign = 'bottom'; |
|
break; |
|
case 'insideTopLeft': |
|
x += distance; |
|
y += distance; |
|
break; |
|
case 'insideTopRight': |
|
x += width - distance; |
|
y += distance; |
|
textAlign = 'right'; |
|
break; |
|
case 'insideBottomLeft': |
|
x += distance; |
|
y += height - distance; |
|
textVerticalAlign = 'bottom'; |
|
break; |
|
case 'insideBottomRight': |
|
x += width - distance; |
|
y += height - distance; |
|
textAlign = 'right'; |
|
textVerticalAlign = 'bottom'; |
|
break; |
|
} |
|
} |
|
out = out || {}; |
|
out.x = x; |
|
out.y = y; |
|
out.align = textAlign; |
|
out.verticalAlign = textVerticalAlign; |
|
return out; |
|
}
|
|
|