mirror of
https://gitea.nishi.boats/pyrite-dev/milsko
synced 2026-01-19 15:44:07 +00:00
merge git PR #3 (round 2)
git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@469 b9cfdab3-6d41-4d17-bbe4-086880011989
This commit is contained in:
232
src/text/draw.c
Normal file
232
src/text/draw.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/* $Id$ */
|
||||
#include <Mw/Milsko.h>
|
||||
|
||||
#ifdef HAS_FREETYPE
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#endif
|
||||
|
||||
#define bitmap_FontWidth 7
|
||||
#define bitmap_FontHeight 14
|
||||
|
||||
#define ft_FontWidth 14
|
||||
#define ft_FontHeight 14
|
||||
|
||||
static void bitmap_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
int i = 0, x, y, sx, sy;
|
||||
int tw;
|
||||
int th;
|
||||
unsigned char* px;
|
||||
MwRect r;
|
||||
MwLLPixmap p;
|
||||
|
||||
if(strlen(text) == 0) text = " ";
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, text);
|
||||
px = malloc(tw * th * 4);
|
||||
|
||||
memset(px, 0, tw * th * 4);
|
||||
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
|
||||
while(text[i] != 0) {
|
||||
int out;
|
||||
i += MwUTF8ToUTF32(text + i, &out);
|
||||
|
||||
if(out >= 0x80) out = 0;
|
||||
|
||||
if(out == '\n') {
|
||||
sx = 0;
|
||||
sy += bitmap_FontHeight;
|
||||
} else {
|
||||
for(y = 0; y < bitmap_FontHeight; y++) {
|
||||
for(x = 0; x < bitmap_FontWidth; x++) {
|
||||
unsigned char* ppx = &px[((sy + y) * tw + sx + x) * 4];
|
||||
if((bold ? MwBoldFontData : MwFontData)[out].data[y] & (1 << ((bitmap_FontWidth - 1) - x))) {
|
||||
ppx[0] = color->red;
|
||||
ppx[1] = color->green;
|
||||
ppx[2] = color->blue;
|
||||
ppx[3] = 255;
|
||||
} else {
|
||||
ppx[0] = 0;
|
||||
ppx[1] = 0;
|
||||
ppx[2] = 0;
|
||||
ppx[3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
sx += bitmap_FontWidth;
|
||||
}
|
||||
}
|
||||
|
||||
p = MwLoadRaw(handle, px, tw, th);
|
||||
r.x = point->x;
|
||||
r.y = point->y - th / 2;
|
||||
r.width = tw;
|
||||
r.height = th;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
}
|
||||
|
||||
#ifdef HAS_FREETYPE
|
||||
static void ft_MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
FT_Error err;
|
||||
|
||||
FT_Error (*_FT_Load_Char)(FT_Face face,
|
||||
FT_ULong char_code,
|
||||
FT_Int32 load_flags);
|
||||
FT_Error (*_FT_Set_Pixel_Sizes)(FT_Face face,
|
||||
FT_UInt pixel_width,
|
||||
FT_UInt pixel_height);
|
||||
|
||||
MwLL l = handle->lowlevel;
|
||||
|
||||
int i = 0, x, y, sx, sy;
|
||||
int tw;
|
||||
int th;
|
||||
unsigned char* px;
|
||||
MwRect r;
|
||||
MwLLPixmap p;
|
||||
|
||||
if(strlen(text) == 0) text = " ";
|
||||
tw = MwTextWidth(handle, text);
|
||||
th = MwTextHeight(handle, text);
|
||||
|
||||
// allocate 4x memory then what we need to account for spacing, italics, etc.
|
||||
px = malloc(tw * th * 16);
|
||||
memset(px, 0, tw * th * 16);
|
||||
|
||||
sx = 0;
|
||||
sy = 0;
|
||||
|
||||
FT_WITH_FUNC(l, FT_Set_Pixel_Sizes, {
|
||||
if((err = _FT_Set_Pixel_Sizes(l->ftFace, ft_FontWidth, ft_FontHeight)) != 0) {
|
||||
if(r.width == 0 || r.height == 0) {
|
||||
printf("failed to set pixel sizes");
|
||||
print_ft_error(l->ftLib, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
FT_WITH_FUNC(l, FT_Load_Char, {
|
||||
while(text[i] != 0) {
|
||||
int out;
|
||||
i += MwUTF8ToUTF32(text + i, &out);
|
||||
|
||||
if(out >= 0x80) out = 0;
|
||||
|
||||
if((err = _FT_Load_Char(l->ftFace, out, FT_LOAD_RENDER)) != 0) {
|
||||
printf("[WARNING] Failed to render %c. ", out);
|
||||
print_ft_error(l->ftLib, err);
|
||||
continue;
|
||||
}
|
||||
|
||||
FT_GlyphSlot glyph = l->ftFace->glyph;
|
||||
FT_Bitmap bitmap = glyph->bitmap;
|
||||
|
||||
r.width = bitmap.width;
|
||||
r.height = bitmap.rows;
|
||||
|
||||
if(sy == 0) {
|
||||
sy = r.height;
|
||||
}
|
||||
|
||||
if(r.width == 0 || r.height == 0) {
|
||||
sx += ft_FontWidth;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(out == '\n') {
|
||||
sx = 0;
|
||||
sy += r.height;
|
||||
} else {
|
||||
// printf("%ld\n", (glyph->advance.x / r.width));
|
||||
int gsx = sx + glyph->bitmap_left;
|
||||
int gsy = (sy - glyph->bitmap_top);
|
||||
for(y = 0; y < r.height; y++) {
|
||||
for(x = 0; x < r.width; x++) {
|
||||
unsigned char* ppx = &px[((gsy + y) * tw + gsx + x) * 4];
|
||||
unsigned char gray = bitmap.buffer[(y * r.width) + x];
|
||||
ppx[0] = color->red - gray;
|
||||
ppx[1] = color->green - gray;
|
||||
ppx[2] = color->blue - gray;
|
||||
ppx[3] = gray;
|
||||
}
|
||||
}
|
||||
sx += r.width;
|
||||
// sx += glyph->advance.x;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
p = MwLoadRaw(handle, px, tw, th);
|
||||
r.x = point->x;
|
||||
r.y = point->y - th / 2;
|
||||
r.width = tw;
|
||||
r.height = th;
|
||||
|
||||
if(align == MwALIGNMENT_CENTER) {
|
||||
r.x -= tw / 2;
|
||||
} else if(align == MwALIGNMENT_END) {
|
||||
r.x -= tw;
|
||||
}
|
||||
|
||||
MwLLDrawPixmap(handle->lowlevel, &r, p);
|
||||
MwLLDestroyPixmap(p);
|
||||
free(px);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void MwDrawText(MwWidget handle, MwPoint* point, const char* text, int bold, int align, MwLLColor color) {
|
||||
bitmap_MwDrawText(handle, point, text, bold, align, color);
|
||||
}
|
||||
|
||||
int MwTextWidth(MwWidget handle, const char* text) {
|
||||
(void)handle;
|
||||
|
||||
/* TODO: check newline */
|
||||
#ifdef HAS_FREETYPE
|
||||
if(handle->lowlevel->ftLib != NULL) {
|
||||
return strlen(text) * ft_FontWidth;
|
||||
} else {
|
||||
#endif
|
||||
return strlen(text) * bitmap_FontWidth;
|
||||
#ifdef HAS_FREETYPE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int MwTextHeight(MwWidget handle, const char* text) {
|
||||
int c = 1;
|
||||
int i = 0;
|
||||
|
||||
(void)handle;
|
||||
(void)text;
|
||||
|
||||
while(text[i] != 0) {
|
||||
int out;
|
||||
i += MwUTF8ToUTF32(text + i, &out);
|
||||
|
||||
if(out == '\n') c++;
|
||||
}
|
||||
#ifdef HAS_FREETYPE
|
||||
if(handle->lowlevel->ftLib != NULL) {
|
||||
return ft_FontHeight * c;
|
||||
} else {
|
||||
#endif
|
||||
return bitmap_FontHeight * c;
|
||||
#ifdef HAS_FREETYPE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user