Java 10, 690 bytes
import java.awt.*;v->new Frame(){{add(new Panel(){RenderingHints R;Math M;public void paint(Graphics g){Graphics2D G=(Graphics2D)g;G.setRenderingHint(R.KEY_ANTIALIASING,R.VALUE_ANTIALIAS_ON);var v=new Font("Hei",0,8).createGlyphVector(G.getFontRenderContext(),"ICATION MEANS FASTER CODING MEANS FEWER CODERS MEANS EASIER COMMUN");int n=99,i=0;for(G.translate(n,0);i<66;){double p=M.PI/2,t=-6/1.1*i*p/90+p;v.setGlyphPosition(i,new Point(0,0));var a=java.awt.geom.AffineTransform.getTranslateInstance((int)(n*M.cos(t)+n),(int)(-n*M.sin(t)+n));a.rotate(t=4*p*i/66);a.translate(n*M.cos(p-t),n*M.sin(p-t));a.translate(-4,0);G.fill(a.createTransformedShape(v.getGlyphOutline(i++)));}}});show();}}
Result:
Explanation:
import java.awt.*; // Required import for almost everything
v-> // Method with empty unused parameter and Frame return-type
new Frame(){ // Create the Frame
{ // In an inner code-block:
add(new Panel(){ // Add a Panel we can draw on:
RenderingHints R; // RenderingHints null-instance on class-level, for static calls
Math M; // Math null-instance on class-level, for static calls
public void paint(Graphics g){
// Overwrite its paint method:
Graphics2D G=(Graphics2D)g;
// Cast Graphics to Graphics2D, to open up more methods
G.setRenderingHint(R.KEY_ANTIALIASING,R.VALUE_ANTIALIAS_ON);
// Apply a focus rendering, otherwise the text would be too vague
var v=new Font("Hei",0,// Create a "Hei"-Font (could alternatively be Kai)
// (note that a centered monospace font would look a lot better
// for letters like the 'I's)
8) // of font-size 8
.createGlyphVector(G.getFontRenderContext(),
// Create a GlyphVector using that Font
"ICATION MEANS FASTER CODING MEANS FEWER CODERS MEANS EASIER COMMUN");
// With this String as text (first character will be at the top)
int n=99, // Integer we'll use a bunch of times, radius of the circle 99
i=0; // Index integer, starting at 0
for(G.translate(n,0); // Set the starting coordinate at 99,0, otherwise the circle
// would be partially outside of the Frame boundaries
i<66;){ // Loop `i` in the range [0, 66):
// (66 is the amount of characters of the text)
double p=M.PI/2, // Temp-double `p`, set to PI/2
t= // Temp-double, which will start at:
-6/1.1 // -360 / 66
*i // multiplied by the current `i`
*p/90 // multiplied by PI/180
+p; // And add PI/2 to that
v.setGlyphPosition(i,new Point(0,0));
// Start the `i`'th Glyph position at 0,0
var a=java.awt.geom.AffineTransform.getTranslateInstance(
// Create an AffineTransform Translation instance, starting at:
(int)( // x-coordinate as casted integer:
n // 99
*M.cos(t) // multiplied by the cosine of `t`
+n), // Add 99 to that
(int)( // y-coordinate as casted integer:
-n // -99
*M.sin(t) // multiplied by the sinus of `t`
+n)); // Add 99 to that
a.rotate( // Then rotate the current letter by,
t= // and set `t` to it at the same time:
4*p // 2*PI
*i // multiplied by the current `i`
/66); // divided by the length 66
a.translate( // Then move the letter to the correct position:
// x-coordinate:
n // 99
*M.cos(p-t), // multiplied by the cosine of PI/2 - the new `t`
// y-coordinate:
n // 99
*M.sin(p-t)); // multiplied by the sinus of PI/2 - the new `t`
a.translate(-4,0); // Slightly adjust based on the font-size
G.fill( // Then add to the Panel through the Graphics2D:
a.createTransformedShape(
// The shape of:
v.getGlyphOutline(i++)));}}});
// The current `i`'th Glyph we just created
show();}} // And afterwards show the Frame
2/21
approximation error is small than 0.002. \$\endgroup\$