font_resource.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright (c) 2012-2022 Daniele Bartolini et al.
  3. * License: https://github.com/crownengine/crown/blob/master/LICENSE
  4. */
  5. #include "config.h"
  6. #include "core/containers/array.inl"
  7. #include "core/filesystem/file.h"
  8. #include "core/filesystem/filesystem.h"
  9. #include "core/json/json_object.inl"
  10. #include "core/json/sjson.h"
  11. #include "core/memory/allocator.h"
  12. #include "core/memory/temp_allocator.inl"
  13. #include "core/strings/string.inl"
  14. #include "resource/compile_options.inl"
  15. #include "resource/font_resource.h"
  16. #include "resource/types.h"
  17. #include <algorithm>
  18. namespace crown
  19. {
  20. namespace font_resource
  21. {
  22. const GlyphData *glyph(const FontResource *fr, CodePoint cp)
  23. {
  24. CE_ASSERT(cp < fr->num_glyphs, "Index out of bounds");
  25. const CodePoint *pts = (CodePoint *)&fr[1];
  26. const GlyphData *data = (GlyphData *)(pts + fr->num_glyphs);
  27. // FIXME: Can do binary search
  28. for (u32 i = 0; i < fr->num_glyphs; ++i) {
  29. if (pts[i] == cp)
  30. return &data[i];
  31. }
  32. CE_FATAL("Glyph not found");
  33. return NULL;
  34. }
  35. } // namespace font_resource
  36. #if CROWN_CAN_COMPILE
  37. namespace font_resource_internal
  38. {
  39. struct GlyphInfo
  40. {
  41. CodePoint cp;
  42. GlyphData gd;
  43. bool operator<(const GlyphInfo &a) const
  44. {
  45. return cp < a.cp;
  46. }
  47. };
  48. s32 parse_glyphs(Array<GlyphInfo> &_glyphs, const JsonArray &glyphs)
  49. {
  50. for (u32 i = 0; i < array::size(glyphs); ++i) {
  51. TempAllocator512 ta;
  52. JsonObject obj(ta);
  53. sjson::parse(obj, glyphs[i]);
  54. GlyphInfo gi;
  55. gi.cp = sjson::parse_int (obj["id"]);
  56. gi.gd.x = sjson::parse_float(obj["x"]);
  57. gi.gd.y = sjson::parse_float(obj["y"]);
  58. gi.gd.width = sjson::parse_float(obj["width"]);
  59. gi.gd.height = sjson::parse_float(obj["height"]);
  60. gi.gd.x_offset = sjson::parse_float(obj["x_offset"]);
  61. gi.gd.y_offset = sjson::parse_float(obj["y_offset"]);
  62. gi.gd.x_advance = sjson::parse_float(obj["x_advance"]);
  63. array::push_back(_glyphs, gi);
  64. }
  65. return 0;
  66. }
  67. s32 compile(CompileOptions &opts)
  68. {
  69. Buffer buf = opts.read();
  70. TempAllocator4096 ta;
  71. JsonObject obj(ta);
  72. JsonArray glyphs(ta);
  73. sjson::parse(obj, buf);
  74. sjson::parse_array(glyphs, obj["glyphs"]);
  75. const u32 texture_size = sjson::parse_int(obj["size"]);
  76. const u32 font_size = sjson::parse_int(obj["font_size"]);
  77. DATA_COMPILER_ASSERT(font_size > 0
  78. , opts
  79. , "Font size must be > 0"
  80. );
  81. s32 err = 0;
  82. Array<GlyphInfo> _glyphs(default_allocator());
  83. err = parse_glyphs(_glyphs, glyphs);
  84. DATA_COMPILER_ENSURE(err == 0, opts);
  85. std::sort(array::begin(_glyphs), array::end(_glyphs));
  86. opts.write(RESOURCE_HEADER(RESOURCE_VERSION_FONT));
  87. opts.write(texture_size);
  88. opts.write(font_size);
  89. opts.write(array::size(_glyphs));
  90. for (u32 i = 0; i < array::size(_glyphs); ++i)
  91. opts.write(_glyphs[i].cp);
  92. for (u32 i = 0; i < array::size(_glyphs); ++i) {
  93. opts.write(_glyphs[i].gd.x);
  94. opts.write(_glyphs[i].gd.y);
  95. opts.write(_glyphs[i].gd.width);
  96. opts.write(_glyphs[i].gd.height);
  97. opts.write(_glyphs[i].gd.x_offset);
  98. opts.write(_glyphs[i].gd.y_offset);
  99. opts.write(_glyphs[i].gd.x_advance);
  100. }
  101. return 0;
  102. }
  103. } // namespace font_resource_internal
  104. #endif // if CROWN_CAN_COMPILE
  105. } // namespace crown