Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.68 KB | None | 0 0
  1. package com.displee.render.font;
  2.  
  3. import lombok.AllArgsConstructor;
  4. import org.lwjgl.BufferUtils;
  5. import org.lwjgl.opengl.GL11;
  6.  
  7. import java.awt.*;
  8. import java.awt.image.BufferedImage;
  9. import java.awt.image.DataBuffer;
  10. import java.awt.image.DataBufferByte;
  11. import java.awt.image.DataBufferInt;
  12. import java.nio.ByteBuffer;
  13. import java.nio.ByteOrder;
  14. import java.nio.IntBuffer;
  15. import java.util.ArrayList;
  16. import java.util.HashMap;
  17. import java.util.Map;
  18.  
  19. /**
  20. * A TrueType font implementation originally for Slick, edited for Bobjob's Engine
  21. * @original author James Chambers (Jimmy)
  22. * @original author Jeremy Adams (elias4444)
  23. * @original author Kevin Glass (kevglass)
  24. * @original author Peter Korzuszek (genail)
  25. * @new version edited by David Aaron Muhar (bobjob)
  26. */
  27. public class TrueTypeFont {
  28.  
  29. public final static int ALIGN_LEFT = 0, ALIGN_RIGHT = 1, ALIGN_CENTER = 2;
  30. /**
  31. * Array that holds necessary information about the font characters
  32. */
  33. private IntObject[] charArray = new IntObject[256];
  34.  
  35. /**
  36. * Map of user defined font characters (Character <-> IntObject)
  37. */
  38. private Map customChars = new HashMap();
  39.  
  40. /**
  41. * Boolean flag on whether AntiAliasing is enabled or not
  42. */
  43. private boolean antiAlias;
  44.  
  45. /**
  46. * Font's size
  47. */
  48. private int fontSize = 0;
  49.  
  50. /**
  51. * Font's height
  52. */
  53. private int fontHeight = 0;
  54.  
  55. /**
  56. * Texture used to cache the font 0-255 characters
  57. */
  58. private int fontTextureID;
  59.  
  60. /**
  61. * Default font texture width
  62. */
  63. private int textureWidth = 512;
  64.  
  65. /**
  66. * Default font texture height
  67. */
  68. private int textureHeight = 512;
  69.  
  70. /**
  71. * A reference to Java's AWT Font that we create our font texture from
  72. */
  73. private Font font;
  74.  
  75. /**
  76. * The font metrics for our Java AWT font
  77. */
  78. private FontMetrics fontMetrics;
  79.  
  80.  
  81. private int correctL = 9, correctR = 8;
  82.  
  83. private class IntObject {
  84.  
  85. /**
  86. * Character's width
  87. */
  88. public int width;
  89.  
  90. /**
  91. * Character's height
  92. */
  93. public int height;
  94.  
  95. /**
  96. * Character's stored x position
  97. */
  98. public int storedX;
  99.  
  100. /**
  101. * Character's stored y position
  102. */
  103. public int storedY;
  104. }
  105.  
  106.  
  107. public TrueTypeFont(Font font, boolean antiAlias, char[] additionalChars) {
  108. this.font = font;
  109. this.fontSize = font.getSize() + 3;
  110. this.antiAlias = antiAlias;
  111.  
  112. createSet(additionalChars);
  113.  
  114. fontHeight -= 1;
  115. if (fontHeight <= 0) {
  116. fontHeight = 1;
  117. }
  118. }
  119.  
  120. public TrueTypeFont(Font font, boolean antiAlias) {
  121. this(font, antiAlias, null);
  122. }
  123.  
  124. public void setCorrection(boolean on) {
  125. if (on) {
  126. correctL = 2;
  127. correctR = 1;
  128. } else {
  129. correctL = 0;
  130. correctR = 0;
  131. }
  132. }
  133.  
  134. private BufferedImage getFontImage(char ch) {
  135. // Create a temporary image to extract the character's size
  136. BufferedImage tempfontImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
  137. Graphics2D g = (Graphics2D) tempfontImage.getGraphics();
  138. if (antiAlias == true) {
  139. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  140. }
  141. g.setFont(font);
  142. fontMetrics = g.getFontMetrics();
  143. int charwidth = fontMetrics.charWidth(ch) + 8;
  144.  
  145. if (charwidth <= 0) {
  146. charwidth = 7;
  147. }
  148. int charheight = fontMetrics.getHeight() + 3;
  149. if (charheight <= 0) {
  150. charheight = fontSize;
  151. }
  152.  
  153. // Create another image holding the character we are creating
  154. BufferedImage fontImage;
  155. fontImage = new BufferedImage(charwidth, charheight, BufferedImage.TYPE_INT_ARGB);
  156. Graphics2D gt = (Graphics2D) fontImage.getGraphics();
  157. if (antiAlias == true) {
  158. gt.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  159. }
  160. gt.setFont(font);
  161.  
  162. gt.setColor(Color.WHITE);
  163. int charx = 3;
  164. int chary = 1;
  165. gt.drawString(String.valueOf(ch), (charx), (chary) + fontMetrics.getAscent());
  166. //fontImage = ImageUtils.flipVertically(fontImage);
  167. //fontImage = ImageUtils.flipHorizontally(fontImage);
  168. //fontImage = ImageUtils.flipHorizontallyAndVertically(fontImage);
  169. return fontImage;
  170.  
  171. }
  172.  
  173. private void createSet(char[] customCharsArray) {
  174. // If there are custom chars then I expand the font texture twice
  175. if (customCharsArray != null && customCharsArray.length > 0) {
  176. textureWidth *= 2;
  177. }
  178.  
  179. // In any case this should be done in other way. Texture with size 512x512
  180. // can maintain only 256 characters with resolution of 32x32. The texture
  181. // size should be calculated dynamicaly by looking at character sizes.
  182.  
  183. try {
  184.  
  185. BufferedImage imgTemp = new BufferedImage(textureWidth, textureHeight, BufferedImage.TYPE_INT_ARGB);
  186. Graphics2D g = (Graphics2D) imgTemp.getGraphics();
  187.  
  188. g.setColor(new Color(0, 0, 0, 1));
  189. g.fillRect(0, 0, textureWidth, textureHeight);
  190.  
  191. int rowHeight = 0;
  192. int positionX = 0;
  193. int positionY = 0;
  194.  
  195. int customCharsLength = (customCharsArray != null) ? customCharsArray.length : 0;
  196.  
  197. for (int i = 0; i < 256 + customCharsLength; i++) {
  198.  
  199. // get 0-255 characters and then custom characters
  200. char ch = (i < 256) ? (char) i : customCharsArray[i - 256];
  201.  
  202. BufferedImage fontImage = getFontImage(ch);
  203.  
  204. IntObject newIntObject = new IntObject();
  205.  
  206. newIntObject.width = fontImage.getWidth();
  207. newIntObject.height = fontImage.getHeight();
  208.  
  209. if (positionX + newIntObject.width >= textureWidth) {
  210. positionX = 0;
  211. positionY += rowHeight;
  212. rowHeight = 0;
  213. }
  214.  
  215. newIntObject.storedX = positionX;
  216. newIntObject.storedY = positionY;
  217.  
  218. if (newIntObject.height > fontHeight) {
  219. fontHeight = newIntObject.height;
  220. }
  221.  
  222. if (newIntObject.height > rowHeight) {
  223. rowHeight = newIntObject.height;
  224. }
  225.  
  226. // Draw it here
  227. g.drawImage(fontImage, positionX, positionY, null);
  228.  
  229. positionX += newIntObject.width;
  230.  
  231. if (i < 256) { // standard characters
  232. charArray[i] = newIntObject;
  233. } else { // custom characters
  234. customChars.put(new Character(ch), newIntObject);
  235. }
  236.  
  237. fontImage = null;
  238. }
  239.  
  240. fontTextureID = loadImage(imgTemp);
  241.  
  242.  
  243. //.getTexture(font.toString(), imgTemp);
  244.  
  245. } catch (Exception e) {
  246. System.err.println("Failed to create font.");
  247. e.printStackTrace();
  248. }
  249. }
  250.  
  251. private void drawQuad(float drawX, float drawY, float drawX2, float drawY2, float srcX, float srcY, float srcX2, float srcY2, float z) {
  252. float DrawWidth = drawX2 - drawX;
  253. float DrawHeight = drawY2 - drawY;
  254. float TextureSrcX = srcX / textureWidth;
  255. float TextureSrcY = srcY / textureHeight;
  256. float SrcWidth = srcX2 - srcX;
  257. float SrcHeight = srcY2 - srcY;
  258. float RenderWidth = (SrcWidth / textureWidth);
  259. float RenderHeight = (SrcHeight / textureHeight);
  260.  
  261. GL11.glTexCoord2f(TextureSrcX, TextureSrcY);
  262. GL11.glVertex3f(drawX, drawY, z);
  263. GL11.glTexCoord2f(TextureSrcX, TextureSrcY + RenderHeight);
  264. GL11.glVertex3f(drawX, drawY + DrawHeight, z);
  265. GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY + RenderHeight);
  266. GL11.glVertex3f(drawX + DrawWidth, drawY + DrawHeight, z);
  267. GL11.glTexCoord2f(TextureSrcX + RenderWidth, TextureSrcY);
  268. GL11.glVertex3f(drawX + DrawWidth, drawY, z);
  269.  
  270. //GL11.glPopMatrix();
  271. }
  272.  
  273. public int getWidth(String whatchars) {
  274. int totalwidth = 0;
  275. IntObject intObject = null;
  276. int currentChar = 0;
  277. for (int i = 0; i < whatchars.length(); i++) {
  278. currentChar = whatchars.charAt(i);
  279. if (currentChar < 256) {
  280. intObject = charArray[currentChar];
  281. } else {
  282. intObject = (IntObject) customChars.get(new Character((char) currentChar));
  283. }
  284.  
  285. if (intObject != null) {
  286. totalwidth += intObject.width;
  287. }
  288. }
  289. return totalwidth;
  290. }
  291.  
  292. public int getHeight() {
  293. return fontHeight;
  294. }
  295.  
  296.  
  297. public int getHeight(String HeightString) {
  298. return fontHeight;
  299. }
  300.  
  301. public int getLineHeight() {
  302. return fontHeight;
  303. }
  304.  
  305. public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY) {
  306. drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, ALIGN_LEFT);
  307. }
  308.  
  309. public void drawString(float x, float y, float z, String whatchars, float scaleX, float scaleY, int format) {
  310. drawString(x, y, z, whatchars, 0, whatchars.length() - 1, scaleX, scaleY, format);
  311. }
  312.  
  313.  
  314. public void drawString(float x, float y, float z, String whatchars, int startIndex, int endIndex, float scaleX, float scaleY, int format) {
  315.  
  316. IntObject intObject = null;
  317. int charCurrent;
  318.  
  319.  
  320. int totalwidth = 0;
  321. int i = startIndex, d, c;
  322. float startY = 0;
  323.  
  324.  
  325. switch (format) {
  326. case ALIGN_RIGHT: {
  327. d = -1;
  328. c = correctR;
  329.  
  330. while (i < endIndex) {
  331. if (whatchars.charAt(i) == 'n') {
  332. startY -= fontHeight;
  333. }
  334. i++;
  335. }
  336. break;
  337. }
  338. case ALIGN_CENTER: {
  339. for (int l = startIndex; l <= endIndex; l++) {
  340. charCurrent = whatchars.charAt(l);
  341. if (charCurrent == 'n') {
  342. break;
  343. }
  344. if (charCurrent < 256) {
  345. intObject = charArray[charCurrent];
  346. } else {
  347. intObject = (IntObject) customChars.get(new Character((char) charCurrent));
  348. }
  349. totalwidth += intObject.width - correctL;
  350. }
  351. totalwidth /= -2;
  352. }
  353. case ALIGN_LEFT:
  354. default: {
  355. d = 1;
  356. c = correctL;
  357. break;
  358. }
  359.  
  360. }
  361.  
  362. java.util.List<QuadObject> list = new ArrayList<>(endIndex - startIndex);
  363.  
  364. while (i >= startIndex && i <= endIndex) {
  365.  
  366. charCurrent = whatchars.charAt(i);
  367. if (charCurrent < 256) {
  368. intObject = charArray[charCurrent];
  369. } else {
  370. intObject = (IntObject) customChars.get(new Character((char) charCurrent));
  371. }
  372.  
  373. if (intObject != null) {
  374. if (d < 0) {
  375. totalwidth += (intObject.width - c) * d;
  376. }
  377. if (charCurrent == 'n') {
  378. startY -= fontHeight * d;
  379. totalwidth = 0;
  380. if (format == ALIGN_CENTER) {
  381. for (int l = i + 1; l <= endIndex; l++) {
  382. charCurrent = whatchars.charAt(l);
  383. if (charCurrent == 'n') {
  384. break;
  385. }
  386. if (charCurrent < 256) {
  387. intObject = charArray[charCurrent];
  388. } else {
  389. intObject = (IntObject) customChars.get(new Character((char) charCurrent));
  390. }
  391. totalwidth += intObject.width - correctL;
  392. }
  393. totalwidth /= -2;
  394. }
  395. //if center get next lines total width/2;
  396. } else {
  397. QuadObject quad = new QuadObject((totalwidth + intObject.width) * scaleX + x, startY * scaleY + y, totalwidth * scaleX + x, (startY + intObject.height) * scaleY + y, intObject.storedX + intObject.width, intObject.storedY + intObject.height, intObject.storedX, intObject.storedY, z);
  398. list.add(quad);
  399. if (d > 0) {
  400. totalwidth += (intObject.width - c) * d;
  401. }
  402. }
  403. i += d;
  404.  
  405. }
  406. }
  407.  
  408. float centerX = 0;
  409. for(QuadObject quad : list) {
  410. centerX += quad.drawX + (quad.drawX2 - quad.drawX);
  411. }
  412. centerX /= 2.0f;
  413. float centerY = 0;
  414. for(QuadObject quad : list) {
  415. centerY += quad.drawY + (quad.drawY2 - quad.drawY);
  416. }
  417. centerY /= 2.0f;
  418.  
  419. GL11.glTranslatef(centerX, centerY, z); // M1 - 2nd translation
  420. //GL11.glRotatef(ModelEditorConstants.rotation, 0.0f, 0.0f, 1.0f); // M2
  421. GL11.glTranslatef( -centerX, -centerY, -z);
  422.  
  423. GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
  424. GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTextureID);
  425. GL11.glBegin(GL11.GL_QUADS);
  426. for(QuadObject quad : list) {
  427. drawQuad(quad.drawX, quad.drawY, quad.drawX2, quad.drawY2, quad.srcX, quad.srcY, quad.srcX2, quad.srcY2, quad.z);
  428. }
  429. GL11.glDisable(GL11.GL_TEXTURE_2D);
  430. GL11.glEnd();
  431. GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
  432. }
  433.  
  434. public static int loadImage(BufferedImage bufferedImage) {
  435. try {
  436. short width = (short) bufferedImage.getWidth();
  437. short height = (short) bufferedImage.getHeight();
  438. //textureLoader.bpp = bufferedImage.getColorModel().hasAlpha() ? (byte)32 : (byte)24;
  439. int bpp = (byte) bufferedImage.getColorModel().getPixelSize();
  440. ByteBuffer byteBuffer;
  441. DataBuffer db = bufferedImage.getData().getDataBuffer();
  442. if (db instanceof DataBufferInt) {
  443. int intI[] = ((DataBufferInt) (bufferedImage.getData().getDataBuffer())).getData();
  444. byte newI[] = new byte[intI.length * 4];
  445. for (int i = 0; i < intI.length; i++) {
  446. byte b[] = intToByteArray(intI[i]);
  447. int newIndex = i * 4;
  448.  
  449. newI[newIndex] = b[1];
  450. newI[newIndex + 1] = b[2];
  451. newI[newIndex + 2] = b[3];
  452. newI[newIndex + 3] = b[0];
  453. }
  454.  
  455. byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(newI);
  456. } else {
  457. byteBuffer = ByteBuffer.allocateDirect(width * height * (bpp / 8)).order(ByteOrder.nativeOrder()).put(((DataBufferByte) (bufferedImage.getData().getDataBuffer())).getData());
  458. }
  459. byteBuffer.flip();
  460.  
  461.  
  462. int internalFormat = GL11.GL_RGBA8, format = GL11.GL_RGBA;
  463. IntBuffer textureId = BufferUtils.createIntBuffer(1);
  464. ;
  465. GL11.glGenTextures(textureId);
  466. GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId.get(0));
  467.  
  468.  
  469. GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
  470. GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
  471.  
  472. GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
  473. GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
  474.  
  475. GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
  476.  
  477.  
  478. GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL11.GL_UNSIGNED_BYTE, byteBuffer.order(ByteOrder.nativeOrder()));
  479. return textureId.get(0);
  480.  
  481. } catch (Exception e) {
  482. e.printStackTrace();
  483. System.exit(-1);
  484. }
  485.  
  486. return -1;
  487. }
  488.  
  489. public static boolean isSupported(String fontname) {
  490. Font font[] = getFonts();
  491. for (int i = font.length - 1; i >= 0; i--) {
  492. if (font[i].getName().equalsIgnoreCase(fontname)) {
  493. return true;
  494. }
  495. }
  496. return false;
  497. }
  498.  
  499. public static Font[] getFonts() {
  500. return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
  501. }
  502.  
  503. public static byte[] intToByteArray(int value) {
  504. return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value};
  505. }
  506.  
  507. public void destroy() {
  508. IntBuffer scratch = BufferUtils.createIntBuffer(1);
  509. scratch.put(0, fontTextureID);
  510. GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
  511. GL11.glDeleteTextures(scratch);
  512. }
  513.  
  514. @AllArgsConstructor
  515. private class QuadObject {
  516. private float drawX;
  517. private float drawY;
  518. private float drawX2;
  519. private float drawY2;
  520. private float srcX;
  521. private float srcY;
  522. private float srcX2;
  523. private float srcY2;
  524. private float z;
  525. }
  526. }
  527.  
  528. import com.displee.render.font.TrueTypeFont;
  529. import org.lwjgl.LWJGLException;
  530. import org.lwjgl.input.Mouse;
  531. import org.lwjgl.opengl.Display;
  532. import org.lwjgl.opengl.DisplayMode;
  533. import org.lwjgl.util.vector.Vector3f;
  534.  
  535. import java.awt.*;
  536.  
  537. import static org.lwjgl.opengl.GL11.*;
  538. import static org.lwjgl.util.glu.GLU.gluPerspective;
  539.  
  540. public class Test3DFont {
  541.  
  542. private static final int WIDTH = 800;
  543. private static final int HEIGHT = 600;
  544.  
  545. private static final float FOV = 45f;
  546. private static final float NEAR = 0.1f;
  547. private static final float FAR = 1000f;
  548.  
  549. private static boolean mousePressed;
  550. private static Vector3f mousePressedVector = new Vector3f();
  551. private static float scale = 0.05f;
  552.  
  553. private static TrueTypeFont font;
  554.  
  555. private static boolean running = true;
  556.  
  557. public static void main(String[] args) throws Exception {
  558. initializeDisplay();
  559. font = new TrueTypeFont(new Font("serif", Font.PLAIN, 30), true);
  560. initializeGL();
  561. while(running) {
  562. glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  563. handleMouse();
  564. loadDefaultRotation();
  565. drawGrid();
  566. font.drawString(0, 0, 0, "Test", 0.1f, 0.1f);
  567. Display.sync(60);
  568. Display.update();
  569. }
  570. Display.destroy();
  571. }
  572.  
  573. private static void initializeDisplay() throws LWJGLException {
  574. Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
  575. Display.create();
  576. setViewport();
  577. }
  578.  
  579. private static void setViewport() {
  580. glViewport(0, 0, WIDTH, HEIGHT);
  581. glMatrixMode(GL_PROJECTION);
  582. glLoadIdentity();
  583. gluPerspective(FOV, (float) WIDTH / (float) HEIGHT, NEAR, FAR);
  584. glMatrixMode(GL_MODELVIEW);
  585. }
  586.  
  587. private static void initializeGL() {
  588. glShadeModel(GL_SMOOTH);
  589. glEnable(GL_NORMALIZE);
  590. glEnable(GL_BLEND);
  591. glCullFace(GL_BACK);
  592. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  593. }
  594.  
  595. private static void handleMouse() {
  596. scale += Mouse.getDWheel() > 0 ? 0.005f : Mouse.getDWheel() < 0 ? -0.005f : 0;
  597. int x = Mouse.getY();
  598. int y = Mouse.getX();
  599. if (!mousePressed) {
  600. mousePressed = Mouse.isButtonDown(0);
  601. if (mousePressed) {
  602. mousePressedVector.x = x;
  603. mousePressedVector.y = y;
  604. }
  605. } else if (!Mouse.isButtonDown(0)) {
  606. mousePressed = false;
  607. }
  608. if (!mousePressed) {
  609. return;
  610. }
  611. float xDifference = x - mousePressedVector.x;
  612. float yDifference = y - mousePressedVector.y;
  613. mousePressedVector.x += xDifference;
  614. mousePressedVector.y += yDifference;
  615. }
  616.  
  617. private static void loadDefaultRotation() {
  618. glLoadIdentity();
  619. Vector3f cameraPosition = new Vector3f();
  620. glTranslatef(cameraPosition.x, cameraPosition.y, -10);
  621. glRotatef(mousePressedVector.x, 1.0F, 0.0F, 0.0F);
  622. glRotatef(mousePressedVector.y, 0.0F, 1.0F, 0.0F);
  623. glRotatef(mousePressedVector.z, 0.0F, 0.0F, 1.0F);
  624. glScalef(scale, scale, scale);
  625. }
  626.  
  627. private static void drawGrid() {
  628. glColor4f(0.7176471f, 0.7176471f, 0.7176471f, 1.0f);
  629. glBegin(GL_LINES);
  630. float size = 50;
  631. float step = 10;
  632. for (float i = -size; i <= size; i += step) {
  633. glVertex3f(i, 0, size);
  634. glVertex3f(i, 0, -size);
  635. glVertex3f(size, 0, i);
  636. glVertex3f(-size, 0, i);
  637. }
  638. glEnd();
  639. }
  640.  
  641. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement