Font.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Ui/Font.h>
  6. #include <AnKi/Ui/UiManager.h>
  7. #include <AnKi/Resource/ResourceManager.h>
  8. #include <AnKi/Resource/ResourceFilesystem.h>
  9. #include <AnKi/Gr/GrManager.h>
  10. #include <AnKi/Gr/Buffer.h>
  11. #include <AnKi/Gr/Texture.h>
  12. #include <AnKi/Gr/CommandBuffer.h>
  13. namespace anki {
  14. Font::~Font()
  15. {
  16. setImAllocator();
  17. m_imFontAtlas.destroy();
  18. unsetImAllocator();
  19. m_fonts.destroy(getAllocator());
  20. m_fontData.destroy(getAllocator());
  21. }
  22. Error Font::init(const CString& filename, ConstWeakArray<U32> fontHeights)
  23. {
  24. setImAllocator();
  25. m_imFontAtlas.init();
  26. // Load font in memory
  27. ResourceFilePtr file;
  28. ANKI_CHECK(m_manager->getResourceManager().getFilesystem().openFile(filename, file));
  29. m_fontData.create(getAllocator(), U32(file->getSize()));
  30. ANKI_CHECK(file->read(&m_fontData[0], file->getSize()));
  31. m_fonts.create(getAllocator(), U32(fontHeights.getSize()));
  32. // Bake font
  33. ImFontConfig cfg;
  34. cfg.FontDataOwnedByAtlas = false;
  35. U32 count = 0;
  36. for(U32 height : fontHeights)
  37. {
  38. cfg.SizePixels = F32(height);
  39. m_fonts[count].m_imFont =
  40. m_imFontAtlas->AddFontFromMemoryTTF(&m_fontData[0], I32(m_fontData.getSize()), F32(height), &cfg);
  41. m_fonts[count].m_height = height;
  42. ++count;
  43. }
  44. const Bool ok = m_imFontAtlas->Build();
  45. ANKI_ASSERT(ok);
  46. (void)ok;
  47. // Create the texture
  48. U8* img;
  49. int width, height;
  50. m_imFontAtlas->GetTexDataAsRGBA32(&img, &width, &height);
  51. createTexture(img, width, height);
  52. unsetImAllocator();
  53. return Error::NONE;
  54. }
  55. void Font::createTexture(const void* data, U32 width, U32 height)
  56. {
  57. ANKI_ASSERT(data && width > 0 && height > 0);
  58. // Create and populate the buffer
  59. const U32 buffSize = width * height * 4;
  60. BufferPtr buff = m_manager->getGrManager().newBuffer(
  61. BufferInitInfo(buffSize, BufferUsageBit::TRANSFER_SOURCE, BufferMapAccessBit::WRITE, "UI"));
  62. void* mapped = buff->map(0, buffSize, BufferMapAccessBit::WRITE);
  63. memcpy(mapped, data, buffSize);
  64. buff->flush(0, buffSize);
  65. buff->unmap();
  66. // Create the texture
  67. TextureInitInfo texInit("Font");
  68. texInit.m_width = width;
  69. texInit.m_height = height;
  70. texInit.m_format = Format::R8G8B8A8_UNORM;
  71. texInit.m_usage =
  72. TextureUsageBit::TRANSFER_DESTINATION | TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::GENERATE_MIPMAPS;
  73. texInit.m_mipmapCount = 1; // No mips because it creates will appear blurry with trilinear filtering
  74. m_tex = m_manager->getGrManager().newTexture(texInit);
  75. // Create the whole texture view
  76. m_texView = m_manager->getGrManager().newTextureView(TextureViewInitInfo(m_tex, "Font"));
  77. m_imFontAtlas->SetTexID(UiImageId(m_texView));
  78. // Do the copy
  79. static const TextureSurfaceInfo surf(0, 0, 0, 0);
  80. CommandBufferInitInfo cmdbInit;
  81. cmdbInit.m_flags = CommandBufferFlag::GENERAL_WORK | CommandBufferFlag::SMALL_BATCH;
  82. CommandBufferPtr cmdb = m_manager->getGrManager().newCommandBuffer(cmdbInit);
  83. {
  84. TextureViewInitInfo viewInit(m_tex, surf, DepthStencilAspectBit::NONE, "TempFont");
  85. TextureViewPtr tmpView = m_manager->getGrManager().newTextureView(viewInit);
  86. cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION, surf);
  87. cmdb->copyBufferToTextureView(buff, 0, buffSize, tmpView);
  88. cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::TRANSFER_DESTINATION, TextureUsageBit::GENERATE_MIPMAPS,
  89. surf);
  90. }
  91. // Gen mips
  92. cmdb->generateMipmaps2d(m_texView);
  93. cmdb->setTextureSurfaceBarrier(m_tex, TextureUsageBit::GENERATE_MIPMAPS, TextureUsageBit::SAMPLED_FRAGMENT, surf);
  94. cmdb->flush();
  95. }
  96. } // end namespace anki