Пример #1
0
void Font::CalculateAdvances(ImageBuffer &image)
{
	// Get the format and size of the surface.
	int width = image.Width() / GLYPHS;
	height = image.Height();
	unsigned mask = 0xFF000000;
	unsigned half = 0xC0000000;
	int pitch = image.Width();
	
	// advance[previous * GLYPHS + next] is the x advance for each glyph pair.
	// There is no advance if the previous value is 0, i.e. we are at the very
	// start of a string.
	memset(advance, 0, GLYPHS * sizeof(advance[0]));
	for(int previous = 1; previous < GLYPHS; ++previous)
		for(int next = 0; next < GLYPHS; ++next)
		{
			int maxD = 0;
			int glyphWidth = 0;
			uint32_t *begin = image.Pixels();
			for(int y = 0; y < height; ++y)
			{
				// Find the last non-empty pixel in the previous glyph.
				uint32_t *pend = begin + previous * width;
				uint32_t *pit = pend + width;
				while(pit != pend && (*--pit & mask) < half) {}
				int distance = (pit - pend) + 1;
				glyphWidth = max(distance, glyphWidth);
				
				// Special case: if "next" is zero (i.e. end of line of text),
				// calculate the full width of this character. Otherwise:
				if(next)
				{
					// Find the first non-empty pixel in this glyph.
					uint32_t *nit = begin + next * width;
					uint32_t *nend = nit + width;
					while(nit != nend && (*nit++ & mask) < half) {}
					
					// How far apart do you want these glyphs drawn? If drawn at
					// an advance of "width", there would be:
					// pend + width - pit   <- pixels after the previous glyph.
					// nit - (nend - width) <- pixels before the next glyph.
					// So for zero kerning distance, you would want:
					distance += 1 - (nit - (nend - width));
				}
				maxD = max(maxD, distance);
				
				// Update the pointer to point to the beginning of the next row.
				begin += pitch;
			}
			// This is a fudge factor to avoid over-kerning, especially for the
			// underscore and for glyph combinations like AV.
			advance[previous * GLYPHS + next] = max(maxD, glyphWidth - 4) / 2;
		}
	
	// Set the space size based on the character width.
	width /= 2;
	height /= 2;
	space = (width + 3) / 6 + 1;
}
Пример #2
0
void FiltersVector::Gauss(ImageBuffer& Source, ImageBuffer& Dest, int Width)
{
   CheckCompatibility(Source, Dest);

   if (Width == 3)
   {
      Kernel(gaussian3, Source, Dest, Source.Step(), Dest.Step(), Source.Height());
      return;
   }

   if (Width == 5)
   {
      Kernel(gaussian5, Source, Dest, Source.Step(), Dest.Step(), Source.Height());
      return;
   }

   throw cl::Error(CL_INVALID_ARG_VALUE, "Invalid width used in Gauss - allowed : 3, 5");
}
Пример #3
0
void FiltersVector::Smooth(ImageBuffer& Source, ImageBuffer& Dest, int Width)
{
   CheckCompatibility(Source, Dest);

   if (Width < 3 || (Width & 1) == 0)
      throw cl::Error(CL_INVALID_ARG_VALUE, "Invalid width used in Smooth");

   Kernel(smooth, In(Source), Out(Dest), Source.Step(), Dest.Step(), Source.Height(), Width);
}
Пример #4
0
void FiltersVector::Sharpen(ImageBuffer& Source, ImageBuffer& Dest, int Width)
{
   CheckCompatibility(Source, Dest);

   if (Width != 3)
      throw cl::Error(CL_INVALID_ARG_VALUE, "Invalid width used in Sharpen - allowed : 3");

   Kernel(sharpen3, In(Source), Out(Dest), Source.Step(), Dest.Step(), Source.Height());
}
Пример #5
0
void Font::Load(const string &imagePath)
{
	// Load the texture.
	ImageBuffer image;
	if(!image.Read(imagePath))
		return;
	
	LoadTexture(image);
	CalculateAdvances(image);
	SetUpShader(image.Width() / GLYPHS, image.Height());
}
Пример #6
0
void FiltersVector::Scharr(ImageBuffer& Source, ImageBuffer& Dest, int Width)
{
   CheckCompatibility(Source, Dest);

   if (Width == 3)
   {
      Kernel(scharr3, Source, Dest, Source.Step(), Dest.Step(), Source.Height());
      return;
   }

   throw cl::Error(CL_INVALID_ARG_VALUE, "Invalid width used in Scharr - allowed : 3");
}
Пример #7
0
void Font::LoadTexture(ImageBuffer &image)
{
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.Width(), image.Height(), 0,
		GL_BGRA, GL_UNSIGNED_BYTE, image.Pixels());
}
void Font::Load(const string &imagePath)
{
	// Load the texture.
	ImageBuffer *image = ImageBuffer::Read(imagePath);
	if(!image)
		return;
	
	LoadTexture(image);
	CalculateAdvances(image);
	SetUpShader(image->Width() / GLYPHS, image->Height());
	
	delete image;
}
Пример #9
0
void FiltersVector::Median(ImageBuffer& Source, ImageBuffer& Dest, int Width)
{
   CheckCompatibility(Source, Dest);

   Source.SendIfNeeded();

   if (Width != 3 && Width != 5)
      throw cl::Error(CL_INVALID_ARG_VALUE, "Invalid width used in Median - allowed : 3 or 5");

   if (Width == 3)
   {
      /*if (RangeFit(Source, 16, 16))  // The cached version is slower on my GTX 680
      {
         Kernel_(*m_CL, SelectProgram(Source), median3_cached, cl::NDRange(16, 16, 1), Source, Dest, Source.Step(), Dest.Step(), Source.Height());
         return;
      }*/

      Kernel(median3, Source, Dest, Source.Step(), Dest.Step(), Source.Height());
      return;
   }

   Kernel(median5, Source, Dest, Source.Step(), Dest.Step(), Source.Height());
}
Пример #10
0
void FiltersVector::GaussianBlur(ImageBuffer& Source, ImageBuffer& Dest, float Sigma)
{
   CheckCompatibility(Source, Dest);

   // Prepare mask
   int MaskSize = int(ceil(3 * Sigma));

   if (Sigma <= 0 || MaskSize > 31)
      throw cl::Error(CL_INVALID_ARG_VALUE, "Invalid sigma used with GaussianBlur - allowed : 0.01-10");

   uint NbElements = (MaskSize * 2 + 1 ) * (MaskSize * 2 + 1 );

   std::vector<float> Mask(NbElements);

   GenerateBlurMask(Mask, Sigma, MaskSize);
   // NOTE : Maybe we should generate the mask in the device to prevent having to send that buffer


   // Send mask to device
   ReadBuffer MaskBuffer(*m_CL, Mask.data(), NbElements);

   // Execute kernel
   Kernel(gaussian_blur, In(Source), Out(Dest), Source.Step(), Dest.Step(), Source.Height(), MaskBuffer, MaskSize);
}