Font.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Copyright (C) 2009-present, 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. #include <AnKi/Gr/ShaderProgram.h>
  14. namespace anki {
  15. Font::~Font()
  16. {
  17. m_imFontAtlas.destroy();
  18. }
  19. Error Font::init(CString filename, ConstWeakArray<U32> fontHeights)
  20. {
  21. m_imFontAtlas.construct();
  22. // Load font in memory
  23. ResourceFilePtr file;
  24. ANKI_CHECK(ResourceFilesystem::getSingleton().openFile(filename, file));
  25. m_fontData.resize(U32(file->getSize()));
  26. ANKI_CHECK(file->read(&m_fontData[0], file->getSize()));
  27. m_fonts.resize(fontHeights.getSize());
  28. // Bake font
  29. ImFontConfig cfg;
  30. cfg.FontDataOwnedByAtlas = false;
  31. U32 count = 0;
  32. for(U32 height : fontHeights)
  33. {
  34. height = U32(F32(height) * g_cvarUiGlobalFontScale) + g_cvarUiGlobalFontBias;
  35. cfg.SizePixels = F32(height);
  36. m_fonts[count].m_imFont = m_imFontAtlas->AddFontFromMemoryTTF(&m_fontData[0], I32(m_fontData.getSize()), F32(height), &cfg);
  37. m_fonts[count].m_height = height;
  38. ++count;
  39. }
  40. [[maybe_unused]] const Bool ok = m_imFontAtlas->Build();
  41. ANKI_ASSERT(ok);
  42. // Create the texture
  43. U8* img;
  44. int width, height;
  45. m_imFontAtlas->GetTexDataAsRGBA32(&img, &width, &height);
  46. createTexture(img, width, height);
  47. return Error::kNone;
  48. }
  49. void Font::createTexture(const void* data, U32 width, U32 height)
  50. {
  51. ANKI_ASSERT(data && width > 0 && height > 0);
  52. // Create and populate the buffer
  53. const U32 buffSize = width * height * 4;
  54. BufferPtr buff = GrManager::getSingleton().newBuffer(BufferInitInfo(buffSize, BufferUsageBit::kCopySource, BufferMapAccessBit::kWrite, "UI"));
  55. void* mapped = buff->map(0, buffSize, BufferMapAccessBit::kWrite);
  56. memcpy(mapped, data, buffSize);
  57. buff->flush(0, buffSize);
  58. buff->unmap();
  59. // Create the texture
  60. TextureInitInfo texInit("Font");
  61. texInit.m_width = width;
  62. texInit.m_height = height;
  63. texInit.m_format = Format::kR8G8B8A8_Unorm;
  64. texInit.m_usage = TextureUsageBit::kCopyDestination | TextureUsageBit::kSrvPixel;
  65. texInit.m_mipmapCount = 1; // No mips because it will appear blurry with trilinear filtering
  66. m_tex = GrManager::getSingleton().newTexture(texInit);
  67. // Create the whole texture view
  68. m_imgData.m_textureView = TextureView(m_tex.get(), TextureSubresourceDesc::all());
  69. m_imFontAtlas->SetTexID(UiImageId(&m_imgData));
  70. // Do the copy
  71. const TextureView firstMipView(m_tex.get(), TextureSubresourceDesc::firstSurface());
  72. CommandBufferInitInfo cmdbInit;
  73. cmdbInit.m_flags = CommandBufferFlag::kGeneralWork | CommandBufferFlag::kSmallBatch;
  74. CommandBufferPtr cmdb = GrManager::getSingleton().newCommandBuffer(cmdbInit);
  75. TextureBarrierInfo barrier = {firstMipView, TextureUsageBit::kNone, TextureUsageBit::kCopyDestination};
  76. cmdb->setPipelineBarrier({&barrier, 1}, {}, {});
  77. cmdb->copyBufferToTexture(BufferView(buff.get()), firstMipView);
  78. barrier.m_previousUsage = TextureUsageBit::kCopyDestination;
  79. barrier.m_nextUsage = TextureUsageBit::kSrvPixel;
  80. cmdb->setPipelineBarrier({&barrier, 1}, {}, {});
  81. cmdb->endRecording();
  82. GrManager::getSingleton().submit(cmdb.get());
  83. }
  84. } // end namespace anki