/* pygame - Python Game Library Copyright (C) 2009 Vicent Marti This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define PYGAME_FREETYPE_INTERNAL #define NO_PYGAME_C_API #include "ft_wrap.h" #include FT_MODULE_H #if defined (PGFT_PYGAME1_COMPAT) # include "ft_pixel.h" #elif defined (HAVE_PYGAME_SDL_VIDEO) # include "surface.h" #endif void __render_glyph_GRAY1(int x, int y, FontSurface *surface, const FT_Bitmap *bitmap, const FontColor *fg_color) { FT_Byte *dst = ((FT_Byte *)surface->buffer) + x + (y * surface->pitch); FT_Byte *dst_cpy; const FT_Byte *src = bitmap->buffer; const FT_Byte *src_cpy; FT_Byte src_byte; unsigned int j, i; #ifndef NDEBUG const FT_Byte *src_end = src + (bitmap->rows * bitmap->pitch); const FT_Byte *dst_end = ((FT_Byte *)surface->buffer + (surface->height * surface->pitch)); #endif assert(dst >= (FT_Byte *)surface->buffer && dst < dst_end); /* * Assumption, target buffer was filled with zeros before any rendering. */ for (j = 0; j < bitmap->rows; ++j) { src_cpy = src; dst_cpy = dst; for (i = 0; i < bitmap->width; ++i) { assert(src_cpy < src_end); src_byte = *src_cpy; if (src_byte) { assert(dst_cpy < dst_end); *dst_cpy = src_byte + *dst_cpy - src_byte * *dst_cpy / 255; } ++src_cpy; ++dst_cpy; } dst += surface->pitch; src += bitmap->pitch; } } void __render_glyph_MONO_as_GRAY1(int x, int y, FontSurface *surface, const FT_Bitmap *bitmap, const FontColor *fg_color) { const int off_x = (x < 0) ? -x : 0; const int off_y = (y < 0) ? -y : 0; const int max_x = MIN(x + bitmap->width, surface->width); const int max_y = MIN(y + bitmap->rows, surface->height); const int rx = MAX(0, x); const int ry = MAX(0, y); int i, j, shift; const unsigned char* src; unsigned char* dst; const unsigned char* src_cpy; unsigned char* dst_cpy; FT_UInt32 val; FT_Byte shade = fg_color->a; src = bitmap->buffer + (off_y * bitmap->pitch) + (off_x >> 3); dst = (unsigned char *)surface->buffer + rx + (ry * surface->pitch); shift = off_x & 7; for (j = ry; j < max_y; ++j) { src_cpy = src; dst_cpy = dst; val = (FT_UInt32)(*src_cpy++ | 0x100) << shift; for (i = rx; i < max_x; ++i, ++dst_cpy) { if (val & 0x10000) { val = (FT_UInt32)(*src_cpy++ | 0x100); } if (val & 0x80) { *dst_cpy = shade; } val <<= 1; } src += bitmap->pitch; dst += surface->pitch; } } void __render_glyph_GRAY_as_MONO1(int x, int y, FontSurface *surface, const FT_Bitmap *bitmap, const FontColor *fg_color) { FT_Byte *dst = ((FT_Byte *)surface->buffer) + x + (y * surface->pitch); FT_Byte *dst_cpy; FT_Byte shade = fg_color->a; const FT_Byte *src = bitmap->buffer; const FT_Byte *src_cpy; unsigned int j, i; /* * Assumption, target buffer was filled with the background color before * any rendering. */ for (j = 0; j < bitmap->rows; ++j) { src_cpy = src; dst_cpy = dst; for (i = 0; i < bitmap->width; ++i) { if (*src_cpy & '\200') /* Round up on 128 */ { *dst_cpy = shade; } ++src_cpy; ++dst_cpy; } dst += surface->pitch; src += bitmap->pitch; } } void __fill_glyph_GRAY1(FT_Fixed x, FT_Fixed y, FT_Fixed w, FT_Fixed h, FontSurface *surface, const FontColor *color) { int i, j; FT_Byte *dst; FT_Byte *dst_cpy; FT_Byte shade = color->a; FT_Byte edge_shade; #ifndef NDEBUG FT_Byte *dst_end = ((FT_Byte *)surface->buffer + (surface->height * surface->pitch)); #endif x = MAX(0, x); y = MAX(0, y); if (x + w > INT_TO_FX6(surface->width)) { w = INT_TO_FX6(surface->width) - x; } if (y + h > INT_TO_FX6(surface->height)) { h = INT_TO_FX6(surface->height) - y; } dst = ((FT_Byte *)surface->buffer + FX6_TRUNC(FX6_CEIL(x)) + FX6_TRUNC(FX6_CEIL(y)) * surface->pitch); if (y < FX6_CEIL(y)) { dst_cpy = dst - surface->pitch; edge_shade = FX6_TRUNC(FX6_ROUND(shade * (FX6_CEIL(y) - y))); for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, ++dst_cpy) { assert(dst_cpy < dst_end); *dst_cpy = edge_shade; } } for (j = 0; j < FX6_TRUNC(FX6_FLOOR(h + y) - FX6_CEIL(y)); ++j) { dst_cpy = dst; for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, ++dst_cpy) { assert(dst_cpy < dst_end); *dst_cpy = shade; } dst += surface->pitch; } if (h > FX6_FLOOR(h + y) - y) { dst_cpy = dst; edge_shade = FX6_TRUNC(FX6_ROUND(shade * (y + y - FX6_FLOOR(h + y)))); for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, ++dst_cpy) { assert(dst_cpy < dst_end); *dst_cpy = edge_shade; } } } void __render_glyph_INT(int x, int y, FontSurface *surface, const FT_Bitmap *bitmap, const FontColor *fg_color) { FT_Byte *dst = ((FT_Byte *)surface->buffer + x * surface->item_stride + y * surface->pitch); int item_size = surface->format->BytesPerPixel; int item_stride = surface->item_stride; FT_Byte *dst_cpy; const FT_Byte *src = bitmap->buffer; const FT_Byte *src_cpy; FT_Byte src_byte; FT_Byte mask = ~fg_color->a; unsigned int j, i; /* * Assumption, target buffer was filled with the background color before * any rendering. */ if (item_size == 1) { for (j = 0; j < bitmap->rows; ++j) { src_cpy = src; dst_cpy = dst; for (i = 0; i < bitmap->width; ++i) { src_byte = *src_cpy; if (src_byte) { *dst_cpy = ((src_byte + *dst_cpy - src_byte * *dst_cpy / 255) ^ mask); } ++src_cpy; dst_cpy += item_stride; } dst += surface->pitch; src += bitmap->pitch; } } else { FT_Byte dst_byte; int b, int_offset = surface->format->Ashift / 8; for (j = 0; j < bitmap->rows; ++j) { src_cpy = src; dst_cpy = dst; for (i = 0; i < bitmap->width; ++i) { dst_byte = dst_cpy[int_offset]; for (b = 0; b < item_size; ++b) { dst_cpy[b] = 0; } src_byte = *src_cpy; if (src_byte) { dst_cpy[int_offset] = ((src_byte + dst_byte - src_byte * dst_byte / 255) ^ mask); } ++src_cpy; dst_cpy += item_stride; } dst += surface->pitch; src += bitmap->pitch; } } } void __render_glyph_MONO_as_INT(int x, int y, FontSurface *surface, const FT_Bitmap *bitmap, const FontColor *fg_color) { const int off_x = (x < 0) ? -x : 0; const int off_y = (y < 0) ? -y : 0; const int max_x = MIN(x + bitmap->width, surface->width); const int max_y = MIN(y + bitmap->rows, surface->height); const int rx = MAX(0, x); const int ry = MAX(0, y); int i, j, shift; int item_stride = surface->item_stride; int item_size = surface->format->BytesPerPixel; unsigned char *src; unsigned char *dst; unsigned char *src_cpy; unsigned char *dst_cpy; FT_UInt32 val; FT_Byte shade = fg_color->a; /* * Assumption, target buffer was filled with the background color before * any rendering. */ src = bitmap->buffer + (off_y * bitmap->pitch) + (off_x >> 3); dst = ((unsigned char *)surface->buffer + rx * surface->item_stride + ry * surface->pitch); shift = off_x & 7; if (item_size == 1) { /* Slightly optimized loop for 1 byte target int */ for (j = ry; j < max_y; ++j) { src_cpy = src; dst_cpy = dst; val = (FT_UInt32)(*src_cpy++ | 0x100) << shift; for (i = rx; i < max_x; ++i, dst_cpy += item_stride) { if (val & 0x10000) { val = (FT_UInt32)(*src_cpy++ | 0x100); } if (val & 0x80) { *dst_cpy = shade; } val <<= 1; } src += bitmap->pitch; dst += surface->pitch; } } else { /* Generic copy for arbitrary target int size */ int b, int_offset = surface->format->Ashift / 8; for (j = ry; j < max_y; ++j) { src_cpy = src; dst_cpy = dst; val = (FT_UInt32)(*src_cpy++ | 0x100) << shift; for (i = rx; i < max_x; ++i, dst_cpy += item_stride) { for (b = 0; b < item_size; ++b) { dst_cpy[b] = 0; } if (val & 0x10000) { val = (FT_UInt32)(*src_cpy++ | 0x100); } if (val & 0x80) { dst_cpy[int_offset] = shade; } val <<= 1; } src += bitmap->pitch; dst += surface->pitch; } } } void __fill_glyph_INT(FT_Fixed x, FT_Fixed y, FT_Fixed w, FT_Fixed h, FontSurface *surface, const FontColor *color) { int i, j; FT_Byte *dst; int itemsize = surface->format->BytesPerPixel; int item_stride = surface->item_stride; int byteoffset = surface->format->Ashift / 8; FT_Byte *dst_cpy; FT_Byte shade = color->a; FT_Byte edge_shade; x = MAX(0, x); y = MAX(0, y); if (x + w > INT_TO_FX6(surface->width)) { w = INT_TO_FX6(surface->width) - x; } if (y + h > INT_TO_FX6(surface->height)) { h = INT_TO_FX6(surface->height) - y; } dst = ((FT_Byte *)surface->buffer + FX6_TRUNC(FX6_CEIL(x)) * itemsize + FX6_TRUNC(FX6_CEIL(y)) * surface->pitch); if (itemsize == 1) { if (y < FX6_CEIL(y)) { dst_cpy = dst - surface->pitch; edge_shade = FX6_TRUNC(FX6_ROUND(shade * (FX6_CEIL(y) - y))); for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, dst_cpy += item_stride) { *dst_cpy = edge_shade; } } for (j = 0; j < FX6_TRUNC(FX6_FLOOR(h + y) - FX6_CEIL(y)); ++j) { dst_cpy = dst; for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, dst_cpy += item_stride) { *dst_cpy = shade; } dst += surface->pitch; } if (h > FX6_FLOOR(h + y) - y) { dst_cpy = dst; edge_shade = FX6_TRUNC(FX6_ROUND(shade * (y + y - FX6_FLOOR(h + y)))); for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, dst_cpy += item_stride) { *dst_cpy = edge_shade; } } } else { int b; if (y < FX6_CEIL(y)) { dst_cpy = dst - surface->pitch; edge_shade = FX6_TRUNC(FX6_ROUND(shade * (FX6_CEIL(y) - y))); for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, dst_cpy += item_stride) { for (b = 0; b < itemsize; ++b) { dst_cpy[b] = 0; } dst_cpy[byteoffset] = edge_shade; } } for (j = 0; j < FX6_TRUNC(FX6_FLOOR(h + y) - FX6_CEIL(y)); ++j) { dst_cpy = dst; for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, dst_cpy += item_stride) { for (b = 0; b < itemsize; ++b) { dst_cpy[b] = 0; } dst_cpy[byteoffset] = shade; } dst += surface->pitch; } if (h > FX6_FLOOR(h + y) - y) { dst_cpy = dst; edge_shade = FX6_TRUNC(FX6_ROUND(shade * (h + y - FX6_FLOOR(h + y)))); for (i = 0; i < FX6_TRUNC(FX6_CEIL(w)); ++i, dst_cpy += item_stride) { for (b = 0; b < itemsize; ++b) { dst_cpy[b] = 0; } dst_cpy[byteoffset] = edge_shade; } } } } #ifdef HAVE_PYGAME_SDL_VIDEO #ifndef NDEBUG #define POINTER_ASSERT_DECLARATIONS(s) \ const unsigned char *PA_bstart = ((unsigned char *)(s)->buffer);\ const unsigned char *PA_bend =\ (PA_bstart + (s)->height * (s)->pitch); #define POINTER_ASSERT(p) \ assert((const unsigned char *)(p) >= PA_bstart);\ assert((const unsigned char *)(p) < PA_bend); #else #define POINTER_ASSERT_DECLARATIONS(s) #define POINTER_ASSERT(p) #endif #define _CREATE_RGB_FILLER(_bpp, _getp, _setp, _blendp) \ void __fill_glyph_RGB##_bpp(FT_Fixed x, FT_Fixed y, \ FT_Fixed w, FT_Fixed h, \ FontSurface *surface, \ const FontColor *color) \ { \ FT_Fixed dh = 0; \ int i; \ unsigned char *dst; \ FT_UInt32 bgR, bgG, bgB, bgA; \ FT_Byte edge_a; \ POINTER_ASSERT_DECLARATIONS(surface) \ \ /* Crop the rectangle to the top and left of the \ * surface. \ */ \ x = MAX(0, x); \ y = MAX(0, y); \ \ /* Crop the rectangle to the bottom and right of \ * the surface. \ */ \ if (x + w > INT_TO_FX6(surface->width)) { \ w = INT_TO_FX6(surface->width) - x; \ } \ if (y + h > INT_TO_FX6(surface->height)) { \ h = INT_TO_FX6(surface->height) - y; \ } \ \ /* Start at the first pixel of the first row. \ */ \ dst = ((FT_Byte *)surface->buffer + \ FX6_TRUNC(FX6_CEIL(x)) * _bpp + \ FX6_TRUNC(FX6_CEIL(y)) * surface->pitch); \ \ /* Take care of the top row of the rectangle if the \ * rectangle starts within the pixels: y is not on \ * a pixel boundary. A special case is when the \ * bottom of the rectangle is also with the pixel \ * row. \ */ \ dh = FX6_CEIL(y) - y; \ if (dh > h) { \ dh = h; \ } \ h -= dh; \ if (dh > 0) { \ unsigned char *_dst = dst - surface->pitch; \ \ edge_a = FX6_TRUNC(FX6_ROUND(color->a * dh)); \ \ for (i = 0; \ i < FX6_TRUNC(FX6_CEIL(w)); \ ++i, _dst += _bpp) { \ FT_UInt32 pixel = (FT_UInt32)_getp; \ \ POINTER_ASSERT(_dst) \ \ if (_bpp == 1) { \ GET_PALETTE_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ } \ else { \ GET_RGB_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ \ } \ \ ALPHA_BLEND( \ color->r, color->g, color->b, \ edge_a, bgR, bgG, bgB, bgA); \ \ _blendp; \ } \ \ y += dh; \ } \ \ /* Fill in all entirely covered rows. These are \ * pixels which are entirely within the upper and \ * lower edges of the rectangle. \ */ \ dh = FX6_FLOOR(h); \ h -= dh; \ while (dh > 0) { \ unsigned char *_dst = dst; \ \ for (i = 0; \ i < FX6_TRUNC(FX6_CEIL(w)); \ ++i, _dst += _bpp) { \ FT_UInt32 pixel = (FT_UInt32)_getp; \ \ POINTER_ASSERT(_dst) \ \ if (_bpp == 1) { \ GET_PALETTE_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ } \ else { \ GET_RGB_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ \ } \ \ ALPHA_BLEND( \ color->r, color->g, color->b, \ color->a, bgR, bgG, bgB, bgA); \ \ _blendp; \ } \ \ dst += surface->pitch; \ dh -= FX6_ONE; \ y += FX6_ONE; \ } \ \ /* Fill in the bottom row of pixels if these pixels \ * are only partially covered: the rectangle bottom \ * is not on a pixel boundary. Otherwise, done. \ */ \ if (h > 0) { \ unsigned char *_dst = dst; \ edge_a = FX6_TRUNC(FX6_ROUND(color->a * h)); \ \ for (i = 0; \ i < FX6_TRUNC(FX6_CEIL(w)); \ ++i, _dst += _bpp) { \ FT_UInt32 pixel = (FT_UInt32)_getp; \ \ POINTER_ASSERT(_dst) \ \ if (_bpp == 1) { \ GET_PALETTE_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ } \ else { \ GET_RGB_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ \ } \ \ ALPHA_BLEND( \ color->r, color->g, color->b, \ edge_a, bgR, bgG, bgB, bgA); \ \ _blendp; \ } \ } \ } #define __MONO_RENDER_INNER_LOOP(_bpp, _code) \ for (j = ry; j < max_y; ++j) \ { \ const unsigned char* _src = src; \ unsigned char* _dst = dst; \ FT_UInt32 val = \ (FT_UInt32)(*_src++ | 0x100) << shift; \ \ for (i = rx; i < max_x; ++i, _dst += _bpp) { \ if (val & 0x10000) { \ val = (FT_UInt32)(*_src++ | 0x100); \ } \ if (val & 0x80) { \ _code; \ } \ val <<= 1; \ } \ \ src += bitmap->pitch; \ dst += surface->pitch; \ } \ #define _CREATE_MONO_RENDER(_bpp, _getp, _setp, _blendp) \ void __render_glyph_MONO##_bpp(int x, int y, \ FontSurface *surface, \ const FT_Bitmap *bitmap, \ const FontColor *color) \ { \ const int off_x = (x < 0) ? -x : 0; \ const int off_y = (y < 0) ? -y : 0; \ \ const int max_x = \ MIN(x + bitmap->width, surface->width); \ const int max_y = \ MIN(y + bitmap->rows, surface->height); \ \ const int rx = MAX(0, x); \ const int ry = MAX(0, y); \ \ int i, j, shift; \ const unsigned char* src; \ unsigned char* dst; \ FT_UInt32 full_color; \ FT_UInt32 bgR, bgG, bgB, bgA; \ \ src = bitmap->buffer + (off_y * bitmap->pitch) + (off_x >> 3); \ dst = (unsigned char *)surface->buffer + (rx * _bpp) + \ (ry * surface->pitch); \ \ full_color = SDL_MapRGBA(surface->format, (FT_Byte)color->r, \ (FT_Byte)color->g, (FT_Byte)color->b, 255); \ \ shift = off_x & 7; \ \ if (color->a == 0xFF) { \ __MONO_RENDER_INNER_LOOP(_bpp, \ { \ _setp; \ }); \ } \ else if (color->a > 0) { \ __MONO_RENDER_INNER_LOOP(_bpp, \ { \ FT_UInt32 pixel = (FT_UInt32)_getp; \ \ if (_bpp == 1) { \ GET_PALETTE_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ } \ else { \ GET_RGB_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ \ } \ \ ALPHA_BLEND( \ color->r, color->g, color->b, color->a, \ bgR, bgG, bgB, bgA); \ \ _blendp; \ }); \ } \ } #define _CREATE_RGB_RENDER(_bpp, _getp, _setp, _blendp) \ void __render_glyph_RGB##_bpp(int x, int y, FontSurface *surface, \ const FT_Bitmap *bitmap, \ const FontColor *color) \ { \ const int off_x = (x < 0) ? -x : 0; \ const int off_y = (y < 0) ? -y : 0; \ \ const int max_x = MIN(x + bitmap->width, surface->width); \ const int max_y = MIN(y + bitmap->rows, surface->height); \ \ const int rx = MAX(0, x); \ const int ry = MAX(0, y); \ \ FT_Byte *dst = ((FT_Byte*)surface->buffer) + (rx * _bpp) + \ (ry * surface->pitch); \ FT_Byte *_dst; \ \ const FT_Byte *src = bitmap->buffer + off_x + \ (off_y * bitmap->pitch); \ const FT_Byte *_src; \ \ _DECLARE_full_color##_bpp(surface, color) \ /* \ const FT_UInt32 full_color = \ SDL_MapRGBA(surface->format, (FT_Byte)color->r, \ (FT_Byte)color->g, (FT_Byte)color->b, 255); \ */ \ \ FT_UInt32 bgR, bgG, bgB, bgA; \ int j, i; \ \ for (j = ry; j < max_y; ++j) { \ _src = src; \ _dst = dst; \ \ for (i = rx; i < max_x; ++i, _dst += _bpp) { \ FT_UInt32 alpha = (*_src++); \ alpha = (alpha * color->a) / 255; \ \ if (alpha == 0xFF) { \ _setp; \ } \ else if (alpha > 0) { \ FT_UInt32 pixel = (FT_UInt32)_getp; \ \ if (_bpp == 1) { \ GET_PALETTE_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ } \ else { \ GET_RGB_VALS( \ pixel, surface->format, \ bgR, bgG, bgB, bgA); \ \ } \ \ ALPHA_BLEND( \ color->r, color->g, color->b, alpha, \ bgR, bgG, bgB, bgA); \ \ _blendp; \ } \ } \ \ dst += surface->pitch; \ src += bitmap->pitch; \ } \ } /* These macros removes a gcc unused variable warning for __render_glyph_RGB3 */ #define _DECLARE_full_color(s, c) const FT_UInt32 full_color = \ SDL_MapRGBA((s)->format, (FT_Byte)(c)->r, (FT_Byte)(c)->g, \ (FT_Byte)(c)->b, 255); #define _DECLARE_full_color1(s, c) _DECLARE_full_color(s, c) #define _DECLARE_full_color2(s, c) _DECLARE_full_color(s, c) #define _DECLARE_full_color3(s, c) #define _DECLARE_full_color4(s, c) _DECLARE_full_color(s, c) #define _SET_PIXEL_24 \ SET_PIXEL24_RGB(_dst, surface->format, color->r, color->g, color->b); #define _BLEND_PIXEL_24 \ SET_PIXEL24_RGB(_dst, surface->format, bgR, bgG, bgB); #define _SET_PIXEL(T) \ *(T*)_dst = (T)full_color; #define _BLEND_PIXEL(T) *((T*)_dst) = (T)( \ ((bgR >> surface->format->Rloss) << surface->format->Rshift) | \ ((bgG >> surface->format->Gloss) << surface->format->Gshift) | \ ((bgB >> surface->format->Bloss) << surface->format->Bshift) | \ ((bgA >> surface->format->Aloss) << surface->format->Ashift & \ surface->format->Amask) ) #define _BLEND_PIXEL_GENERIC(T) *(T*)_dst = (T)( \ SDL_MapRGB(surface->format, \ (FT_Byte)bgR, (FT_Byte)bgG, (FT_Byte)bgB) ) #define _GET_PIXEL(T) (*((T*)_dst)) _CREATE_RGB_RENDER(4, _GET_PIXEL(FT_UInt32), _SET_PIXEL(FT_UInt32), _BLEND_PIXEL(FT_UInt32)) _CREATE_RGB_RENDER(3, GET_PIXEL24(_dst), _SET_PIXEL_24, _BLEND_PIXEL_24) _CREATE_RGB_RENDER(2, _GET_PIXEL(FT_UInt16), _SET_PIXEL(FT_UInt16), _BLEND_PIXEL(FT_UInt16)) _CREATE_RGB_RENDER(1, _GET_PIXEL(FT_Byte), _SET_PIXEL(FT_Byte), _BLEND_PIXEL_GENERIC(FT_Byte)) _CREATE_MONO_RENDER(4, _GET_PIXEL(FT_UInt32), _SET_PIXEL(FT_UInt32), _BLEND_PIXEL(FT_UInt32)) _CREATE_MONO_RENDER(3, GET_PIXEL24(_dst), _SET_PIXEL_24, _BLEND_PIXEL_24) _CREATE_MONO_RENDER(2, _GET_PIXEL(FT_UInt16), _SET_PIXEL(FT_UInt16), _BLEND_PIXEL(FT_UInt16)) _CREATE_MONO_RENDER(1, _GET_PIXEL(FT_Byte), _SET_PIXEL(FT_Byte), _BLEND_PIXEL_GENERIC(FT_Byte)) _CREATE_RGB_FILLER(4, _GET_PIXEL(FT_UInt32), _SET_PIXEL(FT_UInt32), _BLEND_PIXEL(FT_UInt32)) _CREATE_RGB_FILLER(3, GET_PIXEL24(_dst), _SET_PIXEL_24, _BLEND_PIXEL_24) _CREATE_RGB_FILLER(2, _GET_PIXEL(FT_UInt16), _SET_PIXEL(FT_UInt16), _BLEND_PIXEL(FT_UInt16)) _CREATE_RGB_FILLER(1, _GET_PIXEL(FT_Byte), _SET_PIXEL(FT_Byte), _BLEND_PIXEL_GENERIC(FT_Byte)) #endif