ImageRasterizer.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * Copyright (c) 2006-2023 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. // LOVE
  21. #include "ImageRasterizer.h"
  22. #include "GenericShaper.h"
  23. #include "common/Exception.h"
  24. #include <string.h>
  25. namespace love
  26. {
  27. namespace font
  28. {
  29. static_assert(sizeof(Color32) == 4, "sizeof(Color32) must equal 4 bytes!");
  30. ImageRasterizer::ImageRasterizer(love::image::ImageData *data, const uint32 *glyphs, int numglyphs, int extraspacing, float dpiscale)
  31. : imageData(data)
  32. , numglyphs(numglyphs + 1) // Always have a null glyph at the start of the array.
  33. , extraSpacing(extraspacing)
  34. {
  35. this->dpiScale = dpiscale;
  36. if (data->getFormat() != PIXELFORMAT_RGBA8_UNORM)
  37. throw love::Exception("Only 32-bit RGBA images are supported in Image Fonts!");
  38. load(glyphs, numglyphs);
  39. }
  40. ImageRasterizer::~ImageRasterizer()
  41. {
  42. }
  43. int ImageRasterizer::getLineHeight() const
  44. {
  45. return getHeight();
  46. }
  47. int ImageRasterizer::getGlyphSpacing(uint32 glyph) const
  48. {
  49. auto it = glyphIndices.find(glyph);
  50. if (it == glyphIndices.end())
  51. return 0;
  52. return imageGlyphs[it->second].width + extraSpacing;
  53. }
  54. int ImageRasterizer::getGlyphIndex(uint32 glyph) const
  55. {
  56. auto it = glyphIndices.find(glyph);
  57. if (it == glyphIndices.end())
  58. return 0;
  59. return it->second;
  60. }
  61. GlyphData *ImageRasterizer::getGlyphDataForIndex(int index) const
  62. {
  63. GlyphMetrics gm = {};
  64. uint32 glyph = 0;
  65. // Set relevant glyph metrics if the glyph is in this ImageFont
  66. if (index >= 0 && index < (int) imageGlyphs.size())
  67. {
  68. gm.width = imageGlyphs[index].width;
  69. gm.advance = imageGlyphs[index].width + extraSpacing;
  70. glyph = imageGlyphs[index].glyph;
  71. }
  72. gm.height = metrics.height;
  73. GlyphData *g = new GlyphData(glyph, gm, PIXELFORMAT_RGBA8_UNORM);
  74. if (gm.width == 0)
  75. return g;
  76. // We don't want another thread modifying our ImageData mid-copy.
  77. love::thread::Lock lock(imageData->getMutex());
  78. Color32 *gdpixels = (Color32 *) g->getData();
  79. const Color32 *imagepixels = (const Color32 *) imageData->getData();
  80. // copy glyph pixels from imagedata to glyphdata
  81. for (int i = 0; i < g->getWidth() * g->getHeight(); i++)
  82. {
  83. Color32 p = imagepixels[imageGlyphs[index].x + (i % gm.width) + (imageData->getWidth() * (i / gm.width))];
  84. // Use transparency instead of the spacer color
  85. if (p == spacer)
  86. gdpixels[i] = Color32(0, 0, 0, 0);
  87. else
  88. gdpixels[i] = p;
  89. }
  90. return g;
  91. }
  92. void ImageRasterizer::load(const uint32 *glyphs, int glyphcount)
  93. {
  94. auto pixels = (const Color32 *) imageData->getData();
  95. int imgw = imageData->getWidth();
  96. int imgh = imageData->getHeight();
  97. // We don't want another thread modifying our ImageData mid-parse.
  98. love::thread::Lock lock(imageData->getMutex());
  99. // Set the only metric that matters
  100. metrics.height = imgh;
  101. // Reading texture data begins
  102. spacer = pixels[0];
  103. int start = 0;
  104. int end = 0;
  105. {
  106. ImageGlyphData nullglyph;
  107. nullglyph.x = 0;
  108. nullglyph.width = 0;
  109. nullglyph.glyph = 0;
  110. imageGlyphs.push_back(nullglyph);
  111. glyphIndices[0] = (int) imageGlyphs.size() - 1;
  112. }
  113. for (int i = 0; i < glyphcount; ++i)
  114. {
  115. start = end;
  116. // Finds out where the first character starts
  117. while (start < imgw && pixels[start] == spacer)
  118. ++start;
  119. end = start;
  120. // Find where glyph ends.
  121. while (end < imgw && pixels[end] != spacer)
  122. ++end;
  123. if (start >= end)
  124. break;
  125. ImageGlyphData imageGlyph;
  126. imageGlyph.x = start;
  127. imageGlyph.width = end - start;
  128. imageGlyph.glyph = glyphs[i];
  129. imageGlyphs.push_back(imageGlyph);
  130. glyphIndices[glyphs[i]] = (int) imageGlyphs.size() - 1;
  131. }
  132. }
  133. int ImageRasterizer::getGlyphCount() const
  134. {
  135. return numglyphs;
  136. }
  137. bool ImageRasterizer::hasGlyph(uint32 glyph) const
  138. {
  139. return glyphIndices.find(glyph) != glyphIndices.end();
  140. }
  141. Rasterizer::DataType ImageRasterizer::getDataType() const
  142. {
  143. return DATA_IMAGE;
  144. }
  145. TextShaper *ImageRasterizer::newTextShaper()
  146. {
  147. return new GenericShaper(this);
  148. }
  149. } // font
  150. } // love