171 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
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;
 | 
						|
}
 |