int _PGFT_GetTextRect(FreeTypeInstance *ft, PgFaceObject *faceobj, const FaceRenderMode *mode, PGFT_String *text, SDL_Rect *r) { FaceText *face_text; unsigned width; unsigned height; FT_Vector offset; FT_Pos underline_size; FT_Pos underline_top; face_text = _PGFT_LoadFaceText(ft, faceobj, mode, text); if (!face_text) { return -1; } _PGFT_GetRenderMetrics(mode, face_text, &width, &height, &offset, &underline_size, &underline_top); r->x = -(Sint16)FX6_TRUNC(FX6_FLOOR(offset.x)); r->y = (Sint16)FX6_TRUNC(FX6_CEIL(offset.y)); r->w = (Uint16)width; r->h = (Uint16)height; return 0; }
int _PGFT_Render_Array(FreeTypeInstance *ft, PgFontObject *fontobj, const FontRenderMode *mode, PyObject *arrayobj, PGFT_String *text, int invert, int x, int y, SDL_Rect *r) { static int view_init = 0; Pg_buffer pg_view; Py_buffer *view_p = (Py_buffer *)&pg_view; unsigned width; unsigned height; int itemsize; FT_Vector offset; FT_Vector array_offset; FT_Pos underline_top; FT_Fixed underline_size; FontSurface font_surf; SDL_PixelFormat format; Layout *font_text; /* Get target buffer */ if (!view_init) { import_pygame_base(); if (PyErr_Occurred()) { return -1; } } if (PgObject_GetBuffer(arrayobj, &pg_view, PyBUF_RECORDS)) { return -1; } if (view_p->ndim != 2) { PyErr_Format(PyExc_ValueError, "expecting a 2d target array: got %id array instead", (int)view_p->ndim); PgBuffer_Release(&pg_view); return -1; } if (_validate_view_format(view_p->format)) { PgBuffer_Release(&pg_view); return -1; } width = (unsigned)view_p->shape[0]; height = (unsigned)view_p->shape[1]; itemsize = (unsigned)view_p->itemsize; /* build font text */ font_text = _PGFT_LoadLayout(ft, fontobj, mode, text); if (!font_text) { PgBuffer_Release(&pg_view); return -1; } /* if empty string, then nothing more to do */ if (font_text->length == 0) { PgBuffer_Release(&pg_view); r->x = 0; r->y = 0; r->w = 0; r->h = _PGFT_Font_GetHeightSized(ft, fontobj, mode->face_size); return 0; } _PGFT_GetRenderMetrics(mode, font_text, &width, &height, &offset, &underline_top, &underline_size); if (width == 0 || height == 0) { /* Nothing more to do. */ PgBuffer_Release(&pg_view); r->x = 0; r->y = 0; r->w = 0; r->h = _PGFT_Font_GetHeightSized(ft, fontobj, mode->face_size); return 0; } array_offset.x = INT_TO_FX6(x); array_offset.y = INT_TO_FX6(y); if (mode->render_flags & FT_RFLAG_ORIGIN) { x -= FX6_TRUNC(FX6_CEIL(offset.x)); y -= FX6_TRUNC(FX6_CEIL(offset.y)); } else { array_offset.x += offset.x; array_offset.y += offset.y; } /* * Setup target surface struct */ format.BytesPerPixel = itemsize; #if SDL_BYTEORDER == SDL_LIL_ENDIAN format.Ashift = _is_swapped(view_p) ? (itemsize - 1) * 8 : 0; #else format.Ashift = _is_swapped(view_p) ? 0 : (itemsize - 1) * 8; #endif font_surf.buffer = view_p->buf; font_surf.width = (unsigned)view_p->shape[0]; font_surf.height = (unsigned)view_p->shape[1]; font_surf.item_stride = (unsigned)view_p->strides[0]; font_surf.pitch = (unsigned)view_p->strides[1]; font_surf.format = &format; font_surf.render_gray = __render_glyph_INT; font_surf.render_mono = __render_glyph_MONO_as_INT; font_surf.fill = __fill_glyph_INT; render(ft, font_text, mode, invert ? &mono_transparent : &mono_opaque, &font_surf, width, height, &array_offset, underline_top, underline_size); PgBuffer_Release(&pg_view); r->x = -(Sint16)FX6_TRUNC(FX6_FLOOR(offset.x)); r->y = (Sint16)FX6_TRUNC(FX6_CEIL(offset.y)); r->w = (Uint16)width; r->h = (Uint16)height; return 0; }
SDL_Surface *_PGFT_Render_NewSurface(FreeTypeInstance *ft, PgFontObject *fontobj, const FontRenderMode *mode, PGFT_String *text, FontColor *fgcolor, FontColor *bgcolor, SDL_Rect *r) { #if SDL_BYTEORDER == SDL_BIG_ENDIAN FT_UInt32 rmask = 0xff000000; FT_UInt32 gmask = 0x00ff0000; FT_UInt32 bmask = 0x0000ff00; FT_UInt32 amask = 0x000000ff; #else FT_UInt32 rmask = 0x000000ff; FT_UInt32 gmask = 0x0000ff00; FT_UInt32 bmask = 0x00ff0000; FT_UInt32 amask = 0xff000000; #endif int locked = 0; FT_UInt32 fillcolor; SDL_Surface *surface = 0; int bits_per_pixel = (bgcolor || mode->render_flags & FT_RFLAG_ANTIALIAS) ? 32 : 8; FT_UInt32 surface_flags = SDL_SWSURFACE; FontSurface font_surf; Layout *font_text; unsigned width; unsigned height; FT_Vector offset; FT_Pos underline_top; FT_Fixed underline_size; FontColor mono_fgcolor = {0, 0, 0, 1}; FontColor mono_bgcolor = {0, 0, 0, 0}; /* build font text */ font_text = _PGFT_LoadLayout(ft, fontobj, mode, text); if (!font_text) { return 0; } if (font_text->length > 0) { _PGFT_GetRenderMetrics(mode, font_text, &width, &height, &offset, &underline_top, &underline_size); } else { width = 1; height = _PGFT_Font_GetHeightSized(ft, fontobj, mode->face_size); offset.x = -font_text->min_x; offset.y = -font_text->min_y; } surface = SDL_CreateRGBSurface(surface_flags, width, height, bits_per_pixel, rmask, gmask, bmask, bits_per_pixel == 32 ? amask : 0); if (!surface) { PyErr_SetString(PyExc_SDLError, SDL_GetError()); return 0; } if (SDL_MUSTLOCK(surface)) { if (SDL_LockSurface(surface) == -1) { PyErr_SetString(PyExc_SDLError, SDL_GetError()); SDL_FreeSurface(surface); return 0; } locked = 1; } font_surf.buffer = surface->pixels; font_surf.width = surface->w; font_surf.height = surface->h; font_surf.pitch = surface->pitch; font_surf.format = surface->format; if (bits_per_pixel == 32) { font_surf.render_gray = __render_glyph_RGB4; font_surf.render_mono = __render_glyph_MONO4; font_surf.fill = __fill_glyph_RGB4; /* * Fill our texture with the required bg color */ if (bgcolor) { fillcolor = SDL_MapRGBA( surface->format, bgcolor->r, bgcolor->g, bgcolor->b, bgcolor->a); } else { fillcolor = SDL_MapRGBA(surface->format, 0, 0, 0, SDL_ALPHA_TRANSPARENT); } SDL_FillRect(surface, 0, fillcolor); } else { SDL_Color colors[2]; colors[1].r = fgcolor->r; /* Foreground */ colors[1].g = fgcolor->g; colors[1].b = fgcolor->b; colors[0].r = ~colors[1].r; /* Background */ colors[0].g = ~colors[1].g; colors[0].b = ~colors[1].b; if (!SDL_SetColors(surface, colors, 0, 2)) { PyErr_SetString(PyExc_SystemError, "Pygame bug in _PGFT_Render_NewSurface: " "SDL_SetColors failed"); SDL_FreeSurface(surface); return 0; } SDL_SetColorKey(surface, SDL_SRCCOLORKEY, (FT_UInt32)0); if (fgcolor->a != SDL_ALPHA_OPAQUE) { SDL_SetAlpha(surface, SDL_SRCALPHA, fgcolor->a); } fgcolor = &mono_fgcolor; bgcolor = &mono_bgcolor; font_surf.render_gray = __render_glyph_GRAY_as_MONO1; font_surf.render_mono = __render_glyph_MONO_as_GRAY1; font_surf.fill = __fill_glyph_GRAY1; /* * Fill our texture with the required bg color */ SDL_FillRect(surface, 0, 0); } /* * Render the text! */ render(ft, font_text, mode, fgcolor, &font_surf, width, height, &offset, underline_top, underline_size); r->x = -(Sint16)FX6_TRUNC(FX6_FLOOR(offset.x)); r->y = (Sint16)FX6_TRUNC(FX6_CEIL(offset.y)); r->w = (Uint16)width; r->h = (Uint16)height; if (locked) { SDL_UnlockSurface(surface); } return surface; }
PyObject *_PGFT_Render_PixelArray(FreeTypeInstance *ft, PgFontObject *fontobj, const FontRenderMode *mode, PGFT_String *text, int invert, int *_width, int *_height) { FT_Byte *buffer = 0; PyObject *array = 0; FontSurface surf; Layout *font_text; unsigned width; unsigned height; FT_Vector offset; FT_Pos underline_top; FT_Fixed underline_size; int array_size; /* build font text */ font_text = _PGFT_LoadLayout(ft, fontobj, mode, text); if (!font_text) { return 0; } if (font_text->length == 0) { /* Nothing to render */ *_width = 0; *_height = _PGFT_Font_GetHeight(ft, fontobj); return Bytes_FromStringAndSize("", 0); } _PGFT_GetRenderMetrics(mode, font_text, &width, &height, &offset, &underline_top, &underline_size); array_size = width * height; if (array_size == 0) { /* Empty array */ *_width = 0; *_height = height; return Bytes_FromStringAndSize("", 0); } /* Create an uninitialized string whose buffer can be directly set. */ array = Bytes_FromStringAndSize(0, array_size); if (!array) { return 0; } buffer = (FT_Byte *)Bytes_AS_STRING(array); if (invert) { memset(buffer, SDL_ALPHA_OPAQUE, (size_t)array_size); } else { memset(buffer, SDL_ALPHA_TRANSPARENT, (size_t)array_size); } surf.buffer = buffer; surf.width = width; surf.height = height; surf.pitch = (int)surf.width; surf.format = 0; surf.render_gray = __render_glyph_GRAY1; surf.render_mono = __render_glyph_MONO_as_GRAY1; surf.fill = __fill_glyph_GRAY1; render(ft, font_text, mode, invert ? &mono_transparent : &mono_opaque, &surf, width, height, &offset, underline_top, underline_size); *_width = width; *_height = height; return array; }
int _PGFT_Render_ExistingSurface(FreeTypeInstance *ft, PgFontObject *fontobj, const FontRenderMode *mode, PGFT_String *text, SDL_Surface *surface, int x, int y, FontColor *fgcolor, FontColor *bgcolor, SDL_Rect *r) { static const FontRenderPtr __SDLrenderFuncs[] = { 0, __render_glyph_RGB1, __render_glyph_RGB2, __render_glyph_RGB3, __render_glyph_RGB4 }; static const FontRenderPtr __MONOrenderFuncs[] = { 0, __render_glyph_MONO1, __render_glyph_MONO2, __render_glyph_MONO3, __render_glyph_MONO4 }; static const FontFillPtr __RGBfillFuncs[] = { 0, __fill_glyph_RGB1, __fill_glyph_RGB2, __fill_glyph_RGB3, __fill_glyph_RGB4 }; int locked = 0; unsigned width; unsigned height; FT_Vector offset; FT_Vector surf_offset; FT_Pos underline_top; FT_Fixed underline_size; FontSurface font_surf; Layout *font_text; if (SDL_MUSTLOCK(surface)) { if (SDL_LockSurface(surface) == -1) { SDL_FreeSurface(surface); PyErr_SetString(PyExc_SDLError, SDL_GetError()); return -1; } locked = 1; } /* build font text */ font_text = _PGFT_LoadLayout(ft, fontobj, mode, text); if (!font_text) { if (locked) { SDL_UnlockSurface(surface); } return -1; } if (font_text->length == 0) { /* Nothing to rendering */ r->x = 0; r->y = 0; r->w = 0; r->h = _PGFT_Font_GetHeightSized(ft, fontobj, mode->face_size); return 0; } _PGFT_GetRenderMetrics(mode, font_text, &width, &height, &offset, &underline_top, &underline_size); if (width == 0 || height == 0) { /* Nothing more to do. */ if (locked) { SDL_UnlockSurface(surface); } r->x = 0; r->y = 0; r->w = 0; r->h = _PGFT_Font_GetHeightSized(ft, fontobj, mode->face_size); return 0; } surf_offset.x = INT_TO_FX6(x); surf_offset.y = INT_TO_FX6(y); if (mode->render_flags & FT_RFLAG_ORIGIN) { x -= FX6_TRUNC(FX6_CEIL(offset.x)); y -= FX6_TRUNC(FX6_CEIL(offset.y)); } else { surf_offset.x += offset.x; surf_offset.y += offset.y; } /* * Setup target surface struct */ font_surf.buffer = surface->pixels; font_surf.width = surface->w; font_surf.height = surface->h; font_surf.pitch = surface->pitch; font_surf.format = surface->format; font_surf.render_gray = __SDLrenderFuncs[surface->format->BytesPerPixel]; font_surf.render_mono = __MONOrenderFuncs[surface->format->BytesPerPixel]; font_surf.fill = __RGBfillFuncs[surface->format->BytesPerPixel]; /* * if bg color exists, paint background */ if (bgcolor) { if (bgcolor->a == SDL_ALPHA_OPAQUE) { SDL_Rect bg_fill; FT_UInt32 fillcolor; fillcolor = SDL_MapRGBA(surface->format, bgcolor->r, bgcolor->g, bgcolor->b, bgcolor->a); bg_fill.x = (FT_Int16)x; bg_fill.y = (FT_Int16)y; bg_fill.w = (FT_UInt16)width; bg_fill.h = (FT_UInt16)height; SDL_FillRect(surface, &bg_fill, fillcolor); } else { font_surf.fill(INT_TO_FX6(x), INT_TO_FX6(y), INT_TO_FX6(width), INT_TO_FX6(height), &font_surf, bgcolor); } } /* * Render! */ render(ft, font_text, mode, fgcolor, &font_surf, width, height, &surf_offset, underline_top, underline_size); r->x = -(Sint16)FX6_TRUNC(FX6_FLOOR(offset.x)); r->y = (Sint16)FX6_TRUNC(FX6_CEIL(offset.y)); r->w = (Uint16)width; r->h = (Uint16)height; if (locked) { SDL_UnlockSurface(surface); } return 0; }