text_codepoints_loading.c 6.8 KB

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