|
|
@ -1,4 +1,7 @@
|
|
|
|
import { Font, ShapePath } from "three";
|
|
|
|
import { Font, Path, Shape, ShapePath, Vector2 } from "three";
|
|
|
|
|
|
|
|
import { arrayPushArray } from "../../Common/ArrayExt";
|
|
|
|
|
|
|
|
import { Area } from "../../Nest/Core/Path";
|
|
|
|
|
|
|
|
import { IsPointInPolygon } from "../PointInPolyline";
|
|
|
|
|
|
|
|
|
|
|
|
//修改threejs源代码,支持空格.
|
|
|
|
//修改threejs源代码,支持空格.
|
|
|
|
|
|
|
|
|
|
|
@ -6,12 +9,10 @@ export class FontExt extends Font
|
|
|
|
{
|
|
|
|
{
|
|
|
|
generateShapes(text: string, size: number = 100)
|
|
|
|
generateShapes(text: string, size: number = 100)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let shapes = [];
|
|
|
|
let shapes: Shape[] = [];
|
|
|
|
let paths = createPaths(text, size, this.data);
|
|
|
|
let paths = createPaths(text, size, this.data);
|
|
|
|
for (let p = 0, pl = paths.length; p < pl; p++)
|
|
|
|
for (let p of paths)
|
|
|
|
{
|
|
|
|
arrayPushArray(shapes, p.toShapes(false));
|
|
|
|
Array.prototype.push.apply(shapes, paths[p].toShapes());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return shapes;
|
|
|
|
return shapes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -20,7 +21,7 @@ function createPaths(text: string, size: number, data: any)
|
|
|
|
let scale = size / data.resolution;
|
|
|
|
let scale = size / data.resolution;
|
|
|
|
let line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
|
|
|
|
let line_height = (data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness) * scale;
|
|
|
|
|
|
|
|
|
|
|
|
let paths = [];
|
|
|
|
let paths: ShapePath[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
let offsetX = 0, offsetY = 0;
|
|
|
|
let offsetX = 0, offsetY = 0;
|
|
|
|
|
|
|
|
|
|
|
@ -47,13 +48,13 @@ function createPaths(text: string, size: number, data: any)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return paths;
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function createPath(char: string, scale: number, offsetX: number, offsetY: number, data: any)
|
|
|
|
function createPath(char: string, scale: number, offsetX: number, offsetY: number, data: any): { offsetX: number, path: ShapePath; }
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let glyph = data.glyphs[char] || data.glyphs['?'];
|
|
|
|
let glyph = data.glyphs[char] || data.glyphs['?'];
|
|
|
|
|
|
|
|
|
|
|
|
if (!glyph) return;
|
|
|
|
if (!glyph) return;
|
|
|
|
|
|
|
|
|
|
|
|
let path = new ShapePath();
|
|
|
|
let path = new ShapePathExt();
|
|
|
|
|
|
|
|
|
|
|
|
let x: number, y: number, cpx: number, cpy: number, cpx1: number, cpy1: number, cpx2: number, cpy2: number;
|
|
|
|
let x: number, y: number, cpx: number, cpy: number, cpx1: number, cpy1: number, cpx2: number, cpy2: number;
|
|
|
|
|
|
|
|
|
|
|
@ -120,3 +121,92 @@ function createPath(char: string, scale: number, offsetX: number, offsetY: numbe
|
|
|
|
|
|
|
|
|
|
|
|
return { offsetX: glyph.ha * scale, path: path };
|
|
|
|
return { offsetX: glyph.ha * scale, path: path };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PathData extends Path
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
area: number;
|
|
|
|
|
|
|
|
area2: number;//正
|
|
|
|
|
|
|
|
pts: Vector2[];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parent: PathData;
|
|
|
|
|
|
|
|
children: PathData[];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function GetPathDepth(p: PathData): number
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let depth = 0;
|
|
|
|
|
|
|
|
let parent = p.parent;
|
|
|
|
|
|
|
|
while (parent)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
depth++;
|
|
|
|
|
|
|
|
parent = parent.parent;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return depth;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function GetPathIsHole(p: PathData): boolean
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return GetPathDepth(p) % 2 === 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 重载这个类 以便我们能正确的分析层级关系 修复在yahei字体中 "图圆" 渲染错误的问题
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
class ShapePathExt extends ShapePath
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
toShapes(isCCW = false, noHoles = false): Shape[]
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let paths = this.subPaths as PathData[];
|
|
|
|
|
|
|
|
for (let path of paths)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let pts = path.getPoints();
|
|
|
|
|
|
|
|
let area = Area(pts);
|
|
|
|
|
|
|
|
let area2 = Math.abs(area);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
path.area = area;
|
|
|
|
|
|
|
|
path.area2 = area2;
|
|
|
|
|
|
|
|
path.pts = pts;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
paths.sort((p1, p2) => p1.area2 - p2.area2);//从小到大
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let count = paths.length;
|
|
|
|
|
|
|
|
for (let i = 0; i < count; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let p1 = paths[i];
|
|
|
|
|
|
|
|
for (let j = i + 1; j < count; j++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let p2 = paths[j];
|
|
|
|
|
|
|
|
if (IsPointInPolygon(p1.pts[0], p2.pts))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
p1.parent = p2;
|
|
|
|
|
|
|
|
if (!p2.children) p2.children = [];
|
|
|
|
|
|
|
|
p2.children.push(p1);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let shapes: Shape[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let p of paths)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (GetPathIsHole(p)) continue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let s = new Shape();
|
|
|
|
|
|
|
|
s.curves = p.curves;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (p.children)
|
|
|
|
|
|
|
|
for (let pc of p.children)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let sc = new Shape();
|
|
|
|
|
|
|
|
sc.curves = pc.curves;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s.holes.push(sc);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shapes.push(s);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return shapes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|