Skip to content

Commit 7b6627c

Browse files
committed
Rebase from latest dev branch
1 parent b5eb474 commit 7b6627c

File tree

9 files changed

+223
-96
lines changed

9 files changed

+223
-96
lines changed

examples/fonts/ttf/MPLUSRounded1c/MPLUSRounded1c-Regular.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
3.22 MB
Binary file not shown.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
2+
This license is copied below, and is also available with a FAQ at:
3+
https://openfontlicense.org
4+
5+
6+
-----------------------------------------------------------
7+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
8+
-----------------------------------------------------------
9+
10+
PREAMBLE
11+
The goals of the Open Font License (OFL) are to stimulate worldwide
12+
development of collaborative font projects, to support the font creation
13+
efforts of academic and linguistic communities, and to provide a free and
14+
open framework in which fonts may be shared and improved in partnership
15+
with others.
16+
17+
The OFL allows the licensed fonts to be used, studied, modified and
18+
redistributed freely as long as they are not sold by themselves. The
19+
fonts, including any derivative works, can be bundled, embedded,
20+
redistributed and/or sold with any software provided that any reserved
21+
names are not used by derivative works. The fonts and derivatives,
22+
however, cannot be released under any other type of license. The
23+
requirement for fonts to remain under this license does not apply
24+
to any document created using the fonts or their derivatives.
25+
26+
DEFINITIONS
27+
"Font Software" refers to the set of files released by the Copyright
28+
Holder(s) under this license and clearly marked as such. This may
29+
include source files, build scripts and documentation.
30+
31+
"Reserved Font Name" refers to any names specified as such after the
32+
copyright statement(s).
33+
34+
"Original Version" refers to the collection of Font Software components as
35+
distributed by the Copyright Holder(s).
36+
37+
"Modified Version" refers to any derivative made by adding to, deleting,
38+
or substituting -- in part or in whole -- any of the components of the
39+
Original Version, by changing formats or by porting the Font Software to a
40+
new environment.
41+
42+
"Author" refers to any designer, engineer, programmer, technical
43+
writer or other person who contributed to the Font Software.
44+
45+
PERMISSION & CONDITIONS
46+
Permission is hereby granted, free of charge, to any person obtaining
47+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
48+
redistribute, and sell modified and unmodified copies of the Font
49+
Software, subject to the following conditions:
50+
51+
1) Neither the Font Software nor any of its individual components,
52+
in Original or Modified Versions, may be sold by itself.
53+
54+
2) Original or Modified Versions of the Font Software may be bundled,
55+
redistributed and/or sold with any software, provided that each copy
56+
contains the above copyright notice and this license. These can be
57+
included either as stand-alone text files, human-readable headers or
58+
in the appropriate machine-readable metadata fields within text or
59+
binary files as long as those fields can be easily viewed by the user.
60+
61+
3) No Modified Version of the Font Software may use the Reserved Font
62+
Name(s) unless explicit written permission is granted by the corresponding
63+
Copyright Holder. This restriction only applies to the primary font name as
64+
presented to the users.
65+
66+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
67+
Software shall not be used to promote, endorse or advertise any
68+
Modified Version, except to acknowledge the contribution(s) of the
69+
Copyright Holder(s) and the Author(s) or with their explicit written
70+
permission.
71+
72+
5) The Font Software, modified or unmodified, in part or in whole,
73+
must be distributed entirely under this license, and must not be
74+
distributed under any other license. The requirement for fonts to
75+
remain under this license does not apply to any document created
76+
using the Font Software.
77+
78+
TERMINATION
79+
This license becomes null and void if any of the above conditions are
80+
not met.
81+
82+
DISCLAIMER
83+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
84+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
85+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
86+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
87+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
88+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
89+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
90+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
91+
OTHER DEALINGS IN THE FONT SOFTWARE.

examples/jsm/geometries/TextGeometry.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class TextGeometry extends ExtrudeGeometry {
4343

4444
} else {
4545

46-
const shapes = font.generateShapes( text, parameters.size );
46+
const shapes = font.generateShapes( text, parameters.size, parameters.direction );
4747

4848
// defaults
4949

examples/jsm/loaders/FontLoader.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,13 @@ class Font {
109109
*
110110
* @param {string} text - The text.
111111
* @param {number} [size=100] - The text size.
112+
* @param {string} direction - Char direction: ltr(left to right), rtl(right to left) & tb(top bottom).
112113
* @return {Array<Shape>} An array of shapes representing the text.
113114
*/
114-
generateShapes( text, size = 100 ) {
115+
generateShapes( text, size = 100, direction = 'ltr' ) {
115116

116117
const shapes = [];
117-
const paths = createPaths( text, size, this.data );
118+
const paths = createPaths( text, size, this.data, direction );
118119

119120
for ( let p = 0, pl = paths.length; p < pl; p ++ ) {
120121

@@ -128,7 +129,7 @@ class Font {
128129

129130
}
130131

131-
function createPaths( text, size, data ) {
132+
function createPaths( text, size, data, direction ) {
132133

133134
const chars = Array.from( text );
134135
const scale = size / data.resolution;
@@ -138,6 +139,12 @@ function createPaths( text, size, data ) {
138139

139140
let offsetX = 0, offsetY = 0;
140141

142+
if ( direction == 'rtl' || direction == 'tb' ) {
143+
144+
chars.reverse();
145+
146+
}
147+
141148
for ( let i = 0; i < chars.length; i ++ ) {
142149

143150
const char = chars[ i ];
@@ -150,7 +157,18 @@ function createPaths( text, size, data ) {
150157
} else {
151158

152159
const ret = createPath( char, scale, offsetX, offsetY, data );
153-
offsetX += ret.offsetX;
160+
161+
if ( direction == 'tb' ) {
162+
163+
offsetX = 0;
164+
offsetY += data.ascender * scale;
165+
166+
} else {
167+
168+
offsetX += ret.offsetX;
169+
170+
}
171+
154172
paths.push( ret.path );
155173

156174
}
17.6 KB
Loading
4 KB
Loading

examples/webgl_geometry_text_stroke.html

Lines changed: 78 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@
4444
function init( ) {
4545

4646
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
47-
camera.position.set( 0, - 400, 600 );
47+
camera.position.set( 0, - 400, 1000 );
4848

4949
scene = new THREE.Scene();
5050
scene.background = new THREE.Color( 0xf0f0f0 );
5151

5252
const loader = new FontLoader();
53-
loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {
53+
loader.load( 'fonts/ttf/MPLUSRounded1c/MPLUSRounded1c-Regular.json', function ( font ) {
5454

5555
const color = new THREE.Color( 0x006699 );
5656

@@ -66,86 +66,118 @@
6666
side: THREE.DoubleSide
6767
} );
6868

69-
const message = ' Three.js\nStroke text.';
69+
const material = {
70+
dark: matDark,
71+
lite: matLite,
72+
color: color
73+
};
7074

71-
const shapes = font.generateShapes( message, 100 );
75+
const english = ' Three.js\nStroke text.'; // Left to right
7276

73-
const geometry = new THREE.ShapeGeometry( shapes );
77+
const hebrew = 'טקסט קו'; // Right to left
7478

75-
geometry.computeBoundingBox();
79+
const chinese = '文字描邊'; // Top to bottom
7680

77-
const xMid = - 0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
81+
const message1 = generateStrokeText( font, material, english, 80, 'ltr' );
7882

79-
geometry.translate( xMid, 0, 0 );
83+
const message2 = generateStrokeText( font, material, hebrew, 80, 'rtl' );
8084

81-
// make shape ( N.B. edge view not visible )
85+
const message3 = generateStrokeText( font, material, chinese, 80, 'tb' );
8286

83-
const text = new THREE.Mesh( geometry, matLite );
84-
text.position.z = - 150;
85-
scene.add( text );
87+
message1.position.x = - 100;
8688

87-
// make line shape ( N.B. edge view remains visible )
89+
message2.position.x = - 100;
90+
message2.position.y = - 300;
8891

89-
const holeShapes = [];
92+
message3.position.x = 300;
93+
message3.position.y = - 300;
9094

91-
for ( let i = 0; i < shapes.length; i ++ ) {
95+
scene.add( message1, message2, message3 );
9296

93-
const shape = shapes[ i ];
97+
render();
9498

95-
if ( shape.holes && shape.holes.length > 0 ) {
99+
} ); //end load function
96100

97-
for ( let j = 0; j < shape.holes.length; j ++ ) {
101+
renderer = new THREE.WebGLRenderer( { antialias: true } );
102+
renderer.setPixelRatio( window.devicePixelRatio );
103+
renderer.setSize( window.innerWidth, window.innerHeight );
104+
document.body.appendChild( renderer.domElement );
98105

99-
const hole = shape.holes[ j ];
100-
holeShapes.push( hole );
106+
const controls = new OrbitControls( camera, renderer.domElement );
107+
controls.target.set( 0, 0, 0 );
108+
controls.update();
101109

102-
}
110+
controls.addEventListener( 'change', render );
103111

104-
}
112+
window.addEventListener( 'resize', onWindowResize );
105113

106-
}
114+
} // end init
115+
116+
function generateStrokeText(font, material, message, size, direction = 'ltr') {
117+
118+
const shapes = font.generateShapes( message, size, direction );
119+
120+
const geometry = new THREE.ShapeGeometry( shapes );
121+
122+
const strokeText = new THREE.Group();
123+
124+
geometry.computeBoundingBox();
125+
126+
const xMid = - 0.5 * ( geometry.boundingBox.max.x - geometry.boundingBox.min.x );
127+
128+
geometry.translate( xMid, 0, 0 );
129+
130+
// make shape ( N.B. edge view not visible )
107131

108-
shapes.push( ...holeShapes );
132+
const text = new THREE.Mesh( geometry, material.lite );
109133

110-
const style = SVGLoader.getStrokeStyle( 5, color.getStyle() );
134+
text.position.z = - 150;
111135

112-
const strokeText = new THREE.Group();
136+
strokeText.add(text);
113137

114-
for ( let i = 0; i < shapes.length; i ++ ) {
138+
// make line shape ( N.B. edge view remains visible )
115139

116-
const shape = shapes[ i ];
140+
const holeShapes = [];
117141

118-
const points = shape.getPoints();
142+
for ( let i = 0; i < shapes.length; i ++ ) {
119143

120-
const geometry = SVGLoader.pointsToStroke( points, style );
144+
const shape = shapes[ i ];
121145

122-
geometry.translate( xMid, 0, 0 );
146+
if ( shape.holes && shape.holes.length > 0 ) {
123147

124-
const strokeMesh = new THREE.Mesh( geometry, matDark );
125-
strokeText.add( strokeMesh );
148+
for ( let j = 0; j < shape.holes.length; j ++ ) {
149+
150+
const hole = shape.holes[ j ];
151+
holeShapes.push( hole );
152+
153+
}
126154

127155
}
128156

129-
scene.add( strokeText );
157+
}
130158

131-
render();
159+
shapes.push( ...holeShapes );
132160

133-
} ); //end load function
161+
const style = SVGLoader.getStrokeStyle( 5, material.color.getStyle() );
134162

135-
renderer = new THREE.WebGLRenderer( { antialias: true } );
136-
renderer.setPixelRatio( window.devicePixelRatio );
137-
renderer.setSize( window.innerWidth, window.innerHeight );
138-
document.body.appendChild( renderer.domElement );
163+
for ( let i = 0; i < shapes.length; i ++ ) {
139164

140-
const controls = new OrbitControls( camera, renderer.domElement );
141-
controls.target.set( 0, 0, 0 );
142-
controls.update();
165+
const shape = shapes[ i ];
143166

144-
controls.addEventListener( 'change', render );
167+
const points = shape.getPoints();
145168

146-
window.addEventListener( 'resize', onWindowResize );
169+
const geometry = SVGLoader.pointsToStroke( points, style );
147170

148-
} // end init
171+
geometry.translate( xMid, 0, 0 );
172+
173+
const strokeMesh = new THREE.Mesh( geometry, material.dark );
174+
strokeText.add( strokeMesh );
175+
176+
}
177+
178+
return strokeText;
179+
180+
}
149181

150182
function onWindowResize() {
151183

0 commit comments

Comments
 (0)