You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 line
6.3 KiB

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