text_codepoints_loading.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*******************************************************************************************
  2. *
  3. * raylib [text] example - Codepoints loading
  4. *
  5. * This example has been created using raylib 4.2 (www.raylib.com)
  6. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  7. *
  8. * Copyright (c) 2022 Ramon Santamaria (@raysan5)
  9. *
  10. ********************************************************************************************/
  11. #include "raylib.h"
  12. #include <stdlib.h> // Required for: calloc(), realloc(), free()
  13. #include <string.h> // Required for: memcpy()
  14. // Text to be displayed, must be UTF-8 (save this code file as UTF-8)
  15. // NOTE: It can contain all the required text for the game,
  16. // this text will be scanned to get all the required codepoints
  17. static char *text = "いろはにほへと ちりぬるを\nわかよたれそ つねならむ\nうゐのおくやま けふこえて\nあさきゆめみし ゑひもせす";
  18. // Remove codepoint duplicates if requested
  19. static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointResultCount);
  20. //------------------------------------------------------------------------------------
  21. // Program main entry point
  22. //------------------------------------------------------------------------------------
  23. int main(void)
  24. {
  25. // Initialization
  26. //--------------------------------------------------------------------------------------
  27. const int screenWidth = 800;
  28. const int screenHeight = 450;
  29. InitWindow(screenWidth, screenHeight, "raylib [text] example - codepoints loading");
  30. // Get codepoints from text
  31. int codepointCount = 0;
  32. int *codepoints = LoadCodepoints(text, &codepointCount);
  33. // Removed duplicate codepoints to generate smaller font atlas
  34. int codepointsNoDupsCount = 0;
  35. int *codepointsNoDups = CodepointRemoveDuplicates(codepoints, codepointCount, &codepointsNoDupsCount);
  36. UnloadCodepoints(codepoints);
  37. // Load font containing all the provided codepoint glyphs
  38. // A texture font atlas is automatically generated
  39. Font font = LoadFontEx("resources/DotGothic16-Regular.ttf", 36, codepointsNoDups, codepointsNoDupsCount);
  40. // Set bilinear scale filter for better font scaling
  41. SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR);
  42. // Free codepoints, atlas has already been generated
  43. free(codepointsNoDups);
  44. bool showFontAtlas = false;
  45. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  46. //--------------------------------------------------------------------------------------
  47. // Main game loop
  48. while (!WindowShouldClose()) // Detect window close button or ESC key
  49. {
  50. // Update
  51. //----------------------------------------------------------------------------------
  52. if (IsKeyPressed(KEY_SPACE)) showFontAtlas = !showFontAtlas;
  53. //----------------------------------------------------------------------------------
  54. // Draw
  55. //----------------------------------------------------------------------------------
  56. BeginDrawing();
  57. ClearBackground(RAYWHITE);
  58. DrawRectangle(0, 0, GetScreenWidth(), 70, BLACK);
  59. DrawText(TextFormat("Total codepoints contained in provided text: %i", codepointCount), 10, 10, 20, GREEN);
  60. DrawText(TextFormat("Total codepoints required for font atlas (duplicates excluded): %i", codepointsNoDupsCount), 10, 40, 20, GREEN);
  61. if (showFontAtlas)
  62. {
  63. // Draw generated font texture atlas containing provided codepoints
  64. DrawTexture(font.texture, 150, 100, BLACK);
  65. DrawRectangleLines(150, 100, font.texture.width, font.texture.height, BLACK);
  66. }
  67. else
  68. {
  69. // Draw provided text with laoded font, containing all required codepoint glyphs
  70. DrawTextEx(font, text, (Vector2) { 160, 110 }, 48, 5, BLACK);
  71. }
  72. DrawText("Press SPACE to toggle font atlas view!", 10, GetScreenHeight() - 30, 20, GRAY);
  73. EndDrawing();
  74. //----------------------------------------------------------------------------------
  75. }
  76. // De-Initialization
  77. //--------------------------------------------------------------------------------------
  78. UnloadFont(font); // Unload font
  79. CloseWindow(); // Close window and OpenGL context
  80. //--------------------------------------------------------------------------------------
  81. return 0;
  82. }
  83. // Remove codepoint duplicates if requested
  84. // WARNING: This process could be a bit slow if there text to process is very long
  85. static int *CodepointRemoveDuplicates(int *codepoints, int codepointCount, int *codepointsResultCount)
  86. {
  87. int codepointsNoDupsCount = codepointCount;
  88. int *codepointsNoDups = (int *)calloc(codepointCount, sizeof(int));
  89. memcpy(codepointsNoDups, codepoints, codepointCount*sizeof(int));
  90. // Remove duplicates
  91. for (int i = 0; i < codepointsNoDupsCount; i++)
  92. {
  93. for (int j = i + 1; j < codepointsNoDupsCount; j++)
  94. {
  95. if (codepointsNoDups[i] == codepointsNoDups[j])
  96. {
  97. for (int k = j; k < codepointsNoDupsCount; k++) codepointsNoDups[k] = codepointsNoDups[k + 1];
  98. codepointsNoDupsCount--;
  99. j--;
  100. }
  101. }
  102. }
  103. // NOTE: The size of codepointsNoDups is the same as original array but
  104. // only required positions are filled (codepointsNoDupsCount)
  105. *codepointsResultCount = codepointsNoDupsCount;
  106. return codepointsNoDups;
  107. }