ImageRasterizer.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /**
  2. * Copyright (c) 2006-2011 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 short * glyphs, int length)
  33. : imageData(data), glyphs(glyphs), length(length)
  34. {
  35. imageData->retain();
  36. positions = new unsigned int[MAX_CHARS];
  37. memset(positions, 0, MAX_CHARS*4);
  38. widths = new unsigned int[MAX_CHARS];
  39. memset(widths, 0, MAX_CHARS*4);
  40. spacing = new unsigned int[MAX_CHARS];
  41. memset(spacing, 0, MAX_CHARS*4);
  42. load();
  43. }
  44. ImageRasterizer::~ImageRasterizer()
  45. {
  46. imageData->release();
  47. delete[] positions;
  48. delete[] widths;
  49. delete[] spacing;
  50. }
  51. int ImageRasterizer::getLineHeight() const
  52. {
  53. return getHeight();
  54. }
  55. GlyphData * ImageRasterizer::getGlyphData(unsigned short glyph) const
  56. {
  57. GlyphMetrics gm;
  58. gm.height = metrics.height;
  59. gm.width = widths[glyph];
  60. gm.advance = spacing[glyph] + widths[glyph];
  61. gm.bearingX = 0;
  62. gm.bearingY = 0;
  63. GlyphData * g = new GlyphData(glyph, gm, GlyphData::FORMAT_RGBA);
  64. if (gm.width == 0) return g;
  65. unsigned char * gd = (unsigned char*)g->getData();
  66. love::image::pixel * pixels = (love::image::pixel *)(imageData->getData());
  67. for (unsigned int i = 0; i < widths[glyph]*getHeight(); i++) {
  68. love::image::pixel p = pixels[ positions[glyph] + (i % widths[glyph]) + (imageData->getWidth() * (i / widths[glyph])) ];
  69. gd[i*4] = p.r;
  70. gd[i*4+1] = p.g;
  71. gd[i*4+2] = p.b;
  72. gd[i*4+3] = p.a;
  73. }
  74. g->pad();
  75. return g;
  76. }
  77. void ImageRasterizer::load()
  78. {
  79. love::image::pixel * pixels = (love::image::pixel *)(imageData->getData());
  80. unsigned imgw = (unsigned)imageData->getWidth();
  81. unsigned imgh = (unsigned)imageData->getHeight();
  82. unsigned imgs = imgw*imgh;
  83. // Set the only metric that matters
  84. metrics.height = imgh;
  85. // Reading texture data begins
  86. love::image::pixel spacer = pixels[0];
  87. unsigned int start = 0;
  88. unsigned int end = 0;
  89. for(unsigned int i = 0; i < length; ++i)
  90. {
  91. if(i >= MAX_CHARS)
  92. break;
  93. start = end;
  94. // Finds out where the first character starts
  95. while(start < imgw && equal(pixels[start], spacer))
  96. ++start;
  97. if(i > 0)
  98. spacing[glyphs[i - 1]] = (start > end) ? (start - end) : 0;
  99. end = start;
  100. // Find where glyph ends.
  101. while(end < imgw && !equal(pixels[end], spacer))
  102. ++end;
  103. if(start >= end)
  104. break;
  105. unsigned c = glyphs[i];
  106. positions[c] = start;
  107. widths[c] = (end - start);
  108. }
  109. // Replace spacer color with an empty pixel
  110. for(unsigned int i = 0; i < imgs; ++i)
  111. {
  112. if(equal(pixels[i], spacer))
  113. {
  114. pixels[i].r = 0;
  115. pixels[i].g = 0;
  116. pixels[i].b = 0;
  117. pixels[i].a = 0;
  118. }
  119. }
  120. }
  121. int ImageRasterizer::getNumGlyphs() const
  122. {
  123. return length;
  124. }
  125. } // font
  126. } // love