Font.cpp 3.3 KB

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