In ShapeJS 2.0 we support using custom fonts. The Text2D can now take a user provided font file. Here is an example. I'll try and get something more simple together but this shows the basic concept, select a ttf font for userfont and it will use that.
var depthMax = 1;
var depthMin = -1.5;
var uiParams = [
{
name: "userfont",
desc: "Font",
type: "uri"
},
{
name: "text",
desc: "Text",
type: "string",
defaultVal: "Shape"
},
{
name: "text",
desc: "Text",
type: "string",
defaultVal : "Shapeways"
},
{
name: "font",
desc: "Font Name",
type: "enum",
defaultVal : "HelveticaRounded LT Std Bd",
values : ["HelveticaRounded LT Std Bd","Cutive"]
},
{
name: "fontSize",
desc: "Font Size",
type: "enum",
defaultVal : "5",
values : ["2","3.4","5","6","8","12"]
},
{
name: "textpos0",
desc: "Text Pos1",
type: "location",
defaultVal : {"point":[-0.024,0,0],"normal":[0,0,1]}
},
{
name: "textpos1",
desc: "Text Pos2",
type: "location",
defaultVal: {"point":[0.024,0,0],"normal":[0,0,1]}
},
{
name: "labelpos0",
desc: "Image Pos1",
type: "location",
defaultVal : {"point":[-0.024,-0.01,0],"normal":[0,0,1]}
},
{
name: "labelpos1",
desc: "Image Pos2",
type: "location",
defaultVal : {"point":[0.024,-0.01,0],"normal":[0,0,1]}
},
{
name: "engraveDepth",
desc: "Engrave Depth",
type: "double",
rangeMin: depthMin,
rangeMax: depthMax,
step: 0.1,
defaultVal: 1.1
}
];
var vs = 0.1*MM;
function getRotation(from, to){
var a = new Vector3d();
a.cross(from, to);
var sina = a.length();
var cosa = to.dot(from);
var angle = Math.atan2(sina, cosa);
if(Math.abs(sina) < 1.e-8)
return new AxisAngle4d(1,0,0,0);
a.normalize();
return new AxisAngle4d(a.x,a.y,a.z,angle);
}
// calculates transformation of text to be placed between point p0 and p1 wih normals n0 and n1
function getTextTransform(p0, n0, p1, n1){
// calculation of text transform
var nn = new Vector3d();
nn.add(n0,n1);
nn.normalize();
var center = new Vector3d();
center.add(p0, p1);
center.scale(0.5);
var xdir = new Vector3d();
xdir.sub(p1,p0);
var len = xdir.length();
xdir.normalize();
var xaxis = new Vector3d(1,0,0);
var aa1 = getRotation(xaxis, xdir);
var m1 = new Matrix3d();
m1.set(aa1);
var zaxis = new Vector3d(0,0,1);
m1.transform(zaxis); // zaxis after first rotation
var aa2 = getRotation(zaxis, nn);
var trans = new CompositeTransform();
trans.add(new Rotation(aa1.x,aa1.y,aa1.z, aa1.angle));
trans.add(new Rotation(aa2.x,aa2.y,aa2.z, aa2.angle));
trans.add(new Translation(center));
return trans;
}
// cached data
var distData;
var bounds;
var embossing;
var shape;
var textBox;
var labelBox;
var stripBuffer = 1*MM;
var minDepth = 2*MM;
var loc = 0;
function createStrip(args,x,y,z,depth,size,sw) {
var width = sw;
var height = size + stripBuffer;
var boxDepth;
if (depth >= -minDepth) {
// embossing
boxDepth = minDepth;
} else {
boxDepth = -depth;
y -= boxDepth / 2 - minDepth / 2;
}
var base = new Box(x, y, z, width, height, boxDepth);
loc += height;
var tp0 = args.textpos0.point;
var tn0 = args.textpos0.normal;
var tp1 = args.textpos1.point;
var tn1 = args.textpos1.normal;
tp0 = new Vector3d(-0.024, y, 0);
tp1 = new Vector3d(0.024, y, 0);
tn0.normalize();
tn1.normalize();
var tp01 = new Vector3d();
tp01.sub(tp1, tp0);
var tbx;
var tby = size; // 12mm makes for ~1mm thick lines
var aspect = 0.52; // aspect guess from web sources
var spacing = 0;
tbx = tby * aspect * args.text.length;
var tbz = 35 * MM;
var text2d = new Text2D(args.text);
if (args.userfont !== undefined) {
var font = loadFont(args.userfont);
text2d.setFont(font);
} else {
text2d.setFontName(args.font);
}
text2d.setSpacing(spacing); // additional spacing between characters
text2d.setInset(0);
var tvs = 0.05*MM;
text2d.setVoxelSize(tvs); // hardcode this or scale by size?
textBox = new ImageMap(text2d, tbx, tby, tbz);
textBox.setBlurWidth(tby / 100);
// textBox.setBlurWidth(0.1 * MM);
textBox.setBlackDisplacement(depth);
textBox.setWhiteDisplacement(0*MM);
textBox.setTransform(getTextTransform(tp0,tn0,tp1,tn1));
var embossing = new Embossing(base, textBox);
embossing.setBlend(tby / 50);
if (depth < 0) {
embossing.setMinValue(depth);
embossing.setMaxValue(-depth);
} else {
embossing.setMinValue(-depth);
embossing.setMaxValue(depth);
}
return embossing;
}
function main(args) {
var size = args.fontSize * MM;
if (size / vs <= 20) {
vs = vs * 0.75;
}
var strips = 0;
var sw = args.text.length * size * 0.6;
var xresult = new Union();
var sdepth = 0.5 * MM;
var msratio = 1;
loc = 0;
if (size / sdepth > msratio) {
xresult.add(createStrip(args, 0, loc, 0, sdepth, size, sw));
strips++;
}
var width = sw * 1.1;
var height = strips * 2 * (size + stripBuffer);
var depth = 25 * MM;
var dr = Math.max(width,height) * 1.1;
var bounds = new Bounds(-width/2-2*vs, width/2+2*vs, -height/2-2*vs, height/2+2*vs, -depth/2-2*vs, depth/2+2*vs);
var result = new Union();
result.add(xresult);
shape = new Scene(result, bounds);
shape.setVoxelSize(vs);
shape.setMeshErrorFactor(0.05);
shape.setMaxPartsCount(1);
shape.setName("FontTest_" + "s:" + (size * 1000).toFixed(2) + "mm_vs:" + (vs * 1000).toFixed(4) + "mm");
return shape;
}