ImageRasterizer.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /**
  2. * Copyright (c) 2006-2013 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 "common/Exception.h"
  23. #include <string.h>
  24. namespace love
  25. {
  26. namespace font
  27. {
  28. inline bool equal(const love::image::pixel &a, const love::image::pixel &b)
  29. {
  30. return (a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a);
  31. }
  32. ImageRasterizer::ImageRasterizer(love::image::ImageData *data, unsigned int *glyphs, int numglyphs)
  33. : imageData(data)
  34. , glyphs(glyphs)
  35. , numglyphs(numglyphs)
  36. {
  37. imageData->retain();
  38. load();
  39. }
  40. ImageRasterizer::~ImageRasterizer()
  41. {
  42. imageData->release();
  43. }
  44. int ImageRasterizer::getLineHeight() const
  45. {
  46. return getHeight();
  47. }
  48. GlyphData *ImageRasterizer::getGlyphData(unsigned int glyph) const
  49. {
  50. GlyphMetrics gm;
  51. memset(&gm, 0, sizeof(GlyphMetrics));
  52. // Set relevant glyph metrics if the glyph is in this ImageFont
  53. std::map<unsigned int, ImageGlyphData>::const_iterator it = imageGlyphs.find(glyph);
  54. if (it != imageGlyphs.end())
  55. {
  56. gm.width = it->second.width;
  57. gm.advance = it->second.width + it->second.spacing;
  58. }
  59. gm.height = metrics.height;
  60. GlyphData *g = new GlyphData(glyph, gm, GlyphData::FORMAT_RGBA);
  61. if (gm.width == 0)
  62. return g;
  63. love::image::pixel *gdpixels = (love::image::pixel *) g->getData();
  64. love::image::pixel *imagepixels = (love::image::pixel *) imageData->getData();
  65. // copy glyph pixels from imagedata to glyphdata
  66. for (int i = 0; i < g->getWidth() * g->getHeight(); i++)
  67. {
  68. love::image::pixel p = imagepixels[ it->second.x + (i % gm.width) + (imageData->getWidth() * (i / gm.width)) ];
  69. // Use transparency instead of the spacer color
  70. if (equal(p, spacer))
  71. gdpixels[i].r = gdpixels[i].g = gdpixels[i].b = gdpixels[i].a = 0;
  72. else
  73. gdpixels[i] = p;
  74. }
  75. return g;
  76. }
  77. void ImageRasterizer::load()
  78. {
  79. love::image::pixel *pixels = (love::image::pixel *) imageData->getData();
  80. unsigned int imgw = (unsigned int) imageData->getWidth();
  81. unsigned int imgh = (unsigned int) imageData->getHeight();
  82. // Set the only metric that matters
  83. metrics.height = imgh;
  84. // Reading texture data begins
  85. spacer = pixels[0];
  86. unsigned int start = 0;
  87. unsigned int end = 0;
  88. for (unsigned int i = 0; i < numglyphs; ++i)
  89. {
  90. start = end;
  91. // Finds out where the first character starts
  92. while (start < imgw && equal(pixels[start], spacer))
  93. ++start;
  94. // set previous glyph's spacing
  95. if (i > 0 && imageGlyphs.size() > 0)
  96. imageGlyphs[glyphs[i - 1]].spacing = (start > end) ? (start - end) : 0;
  97. end = start;
  98. // Find where glyph ends.
  99. while (end < imgw && !equal(pixels[end], spacer))
  100. ++end;
  101. if (start >= end)
  102. break;
  103. ImageGlyphData imageGlyph;
  104. imageGlyph.x = start;
  105. imageGlyph.width = end - start;
  106. imageGlyphs[glyphs[i]] = imageGlyph;
  107. }
  108. // Find spacing of last glyph
  109. if (numglyphs > 0)
  110. {
  111. start = end;
  112. while (start < imgw && equal(pixels[start], spacer))
  113. ++start;
  114. imageGlyphs[glyphs[numglyphs - 1]].spacing = (start > end) ? (start - end) : 0;
  115. }
  116. }
  117. int ImageRasterizer::getGlyphCount() const
  118. {
  119. return numglyphs;
  120. }
  121. bool ImageRasterizer::hasGlyph(unsigned int glyph) const
  122. {
  123. return imageGlyphs.find(glyph) != imageGlyphs.end();
  124. }
  125. } // font
  126. } // love