src/gfx/Surface.ec \
src/gfx/fontManagement.ec \
src/gfx/fontRendering.ec \
+ src/gfx/imgDistMap.ec \
src/gui/controls/Button.ec \
src/gui/controls/CalendarControl.ec \
src/gui/controls/DataBox.ec \
$(OBJ)fontRendering.sym: src/gfx/fontRendering.ec
$(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c $(call quote_path,src/gfx/fontRendering.ec) -o $(call quote_path,$@)
+$(OBJ)imgDistMap.sym: src/gfx/imgDistMap.ec
+ $(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c $(call quote_path,src/gfx/imgDistMap.ec) -o $(call quote_path,$@)
+
$(OBJ)Button.sym: src/gui/controls/Button.ec
$(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/gui/controls/Button.ec -o $(OBJ)Button.sym
$(OBJ)fontRendering.c: src/gfx/fontRendering.ec $(OBJ)fontRendering.sym | $(SYMBOLS)
$(ECC) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) $(FVISIBILITY) -c $(call quote_path,src/gfx/fontRendering.ec) -o $(call quote_path,$@) -symbols $(OBJ)
+$(OBJ)imgDistMap.c: src/gfx/imgDistMap.ec $(OBJ)imgDistMap.sym | $(SYMBOLS)
+ $(ECC) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) $(FVISIBILITY) -c $(call quote_path,src/gfx/imgDistMap.ec) -o $(call quote_path,$@) -symbols $(OBJ)
+
$(OBJ)Button.c: src/gui/controls/Button.ec $(OBJ)Button.sym | $(SYMBOLS)
$(ECC) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/gui/controls/Button.ec -o $(OBJ)Button.c -symbols $(OBJ)
$(OBJ)fontRendering$(O): $(OBJ)fontRendering.c
$(CC) $(CFLAGS) $(PRJ_CFLAGS) $(FVISIBILITY) -c $(call quote_path,$(OBJ)fontRendering.c) -o $(call quote_path,$@)
+$(OBJ)imgDistMap$(O): $(OBJ)imgDistMap.c
+ $(CC) $(CFLAGS) $(PRJ_CFLAGS) $(FVISIBILITY) -c $(call quote_path,$(OBJ)imgDistMap.c) -o $(call quote_path,$@)
+
$(OBJ)Button.o: $(OBJ)Button.c
$(CC) $(CFLAGS) $(PRJ_CFLAGS) -c $(OBJ)Button.c -o $(OBJ)Button.o
"Resource.ec",
"Surface.ec",
"fontManagement.ec",
- "fontRendering.ec"
+ "fontRendering.ec",
+ "imgDistMap.ec"
],
"Configurations" : [
{
virtual bool ::MakeDDBitmap(DisplaySystem, Bitmap, bool);
// Font loading
- virtual Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags);
+ virtual Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade);
virtual void ::UnloadFont(DisplaySystem, Font);
// 2D Drawing
return result;
}
- Font LoadFont(const char * faceName, float size, FontFlags flags)
+ Font LoadOutlineFont(const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
Font result = null;
subclass(DisplayDriver) driver = this ? this.driver : ((subclass(DisplayDriver))class(LFBDisplayDriver));
{
TrimLSpaces(fonts[c],fonts[c]);
TrimRSpaces(fonts[c],fonts[c]);
- if((result = driver.LoadFont(this, fonts[c], size, flags)))
+ if((result = driver.LoadFont(this, fonts[c], size, flags, outlineSize, outlineFade)))
{
break;
}
return result;
}
+ Font LoadFont(const char * faceName, float size, FontFlags flags)
+ {
+ return LoadOutlineFont(faceName, size, flags, 0, 0);
+ }
+
void UnloadFont(Font font)
{
subclass(DisplayDriver) driver = this ? this.driver : ((subclass(DisplayDriver))class(LFBDisplayDriver));
property bool italic { set { flags.italic = value; } get { return this ? flags.italic : false; } };
property bool underline { set { flags.underline = value; } get { return this ? flags.underline : false; } };
property Font font { get { return this ? font : null; } };
- property Window window { set { if(value) value.AddResource(this); } };
+ property Window window { set { if(value) { value.RemoveResource(this); value.AddResource(this); } } };
+ property float outlineSize { set { outlineSize = value; } get { return this ? outlineSize : 0; } };
+ property float outlineFade { set { outlineFade = value; } get { return this ? outlineFade : 0; } };
private:
char * faceName;
float size;
FontFlags flags;
DisplaySystem displaySystem;
+ float outlineSize, outlineFade;
void Load(FontResource copy, DisplaySystem displaySystem)
{
delete faceName;
- faceName = CopyString(copy.faceName);
- size = copy.size;
- flags = copy.flags;
- this.displaySystem = displaySystem;
- if(faceName)
- font = displaySystem.LoadFont(faceName, size, flags);
+ faceName = *&CopyString(copy.faceName);
+ *&size = *©.size;
+ *&flags = *©.flags;
+ *&outlineSize = *©.outlineSize;
+ *&outlineFade = *©.outlineFade;
+ if(faceName && displaySystem)
+ {
+ this.displaySystem = displaySystem;
+ font = displaySystem.LoadOutlineFont(faceName, size, flags, outlineSize, outlineFade);
+ }
}
void Reference(FontResource reference)
bool blend;
bool writeColor;
ColorAlpha blitTint;
+ ColorAlpha outlineColor;
blitTint = white;
blend = true;
writeColor = true;
alphaWrite = blend;
+ outlineColor = black;
~Surface()
{
return ((LFBSurface)driverData).bitmap;
}
}
+ property ColorAlpha outlineColor
+ {
+ set { outlineColor = value; }
+ get { return outlineColor; }
+ }
ColorAlpha GetPixel(int x, int y)
{
bool opaqueText;
int xOffset;
bool writingText;
+ bool writingOutline;
float foreground[4], background[4], bitmapMult[4];
};
LFBDisplayDriver::UnloadFont(displaySystem, font);
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
- Font font = LFBDisplayDriver::LoadFont(displaySystem, faceName, size, flags);
+ Font font = LFBDisplayDriver::LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
printf("CocoaOpenGLDisplayDriver:LoadFont(%s):%p %s:%i\n", faceName, font, __FILE__, __LINE__);
bool opaqueText;
int xOffset;
bool writingText;
+ bool writingOutline;
ColorAlpha background;
};
((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
- return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
+ return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
}
void TextFont(Display display, Surface surface, Font font)
bool opaqueText;
int xOffset;
bool writingText;
+ bool writingOutline;
ColorAlpha background;
};
((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
- return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
+ return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
}
void TextFont(Display display, Surface surface, Font font)
#endif
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
#ifdef USE_GDI_FONT
void * font;
ReleaseDC(null, hdc);
return font;
#else
- Font font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
+ Font font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
/*if(font)
{
font.bitmap.pixelFormat = C8;
char faceName[512];
FontFlags flags;
float size;
+ float outlineSize;
+ float outlineFade;
int ascent, descent;
float scale;
Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
if(false) //display.alphaBlend)
- return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
+ return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
else
{
GDIFont font { };
if(!gdiFont.font)
{
gdiFont.font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(display.displaySystem,
- gdiFont.faceName, gdiFont.size, gdiFont.flags);
+ gdiFont.faceName, gdiFont.size, gdiFont.flags, gdiFont.outlineSize, gdiFont.outlineFade);
}
((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, gdiFont.font);
}
if(!gdiFont.font)
{
gdiFont.font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(display.displaySystem,
- gdiFont.faceName, gdiFont.size, gdiFont.flags);
+ gdiFont.faceName, gdiFont.size, gdiFont.flags, gdiFont.outlineSize, gdiFont.outlineFade);
}
if(surface.textOpacity)
{
bool opaqueText;
int xOffset;
bool writingText;
+ bool writingOutline;
Bitmap bitmap;
delete font;
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
#ifndef ECERE_NOTRUETYPE
- return Font::Load(displaySystem, faceName, size, flags);
+ return Font::Load(displaySystem, faceName, size, flags, outlineSize, outlineFade);
#else
return { };
#endif
if(width)
{
int w = 0, advance = 0;
- font.ProcessString(displaySystem, (const byte *)text, len, null, null, null, &w, 0, prevGlyph, rPrevGlyph, &advance);
+ font.ProcessString(displaySystem, (const byte *)text, len, false, null, null, &w, 0, prevGlyph, rPrevGlyph, &advance);
if(adv) *adv = advance >> 6;
//*width = (w + 64 - w % 64) >> 6;
*width = w >> 6;
}
}
-#if !defined(ECERE_NOTRUETYPE)
- void ::OutputGlyph(Surface surface, Display display, int x, int y, Glyph glyph, Bitmap bitmap)
- {
- surface.driver.Blit(display, surface, bitmap, x + glyph.left, y + glyph.top, glyph.x, glyph.y, glyph.w, glyph.h);
- }
-#endif
-
void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
{
LFBSurface lfbSurface = surface.driverData;
lfbSurface.writingText = true;
#if !defined(ECERE_NOTRUETYPE)
x <<= 6;
- lfbSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, OutputGlyph, surface, display, &x, y, prevGlyph, rPrevGlyph, &adv);
+ lfbSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, true, surface, display, &x, y, prevGlyph, rPrevGlyph, &adv);
x += adv;
#endif
lfbSurface.writingText = false;
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
return (void *) true;
}
bool opaqueText;
int xOffset;
bool writingText;
+ bool writingOutline;
float foreground[4], background[4], bitmapMult[4];
} OGLSurface;
((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
Font font;
OGLSystem oglSystem = displaySystem.driverData;
oglSystem.loadingFont = true;
- font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
+ font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
return font;
}
oglSurface.writingText = true;
glEnable(GL_TEXTURE_2D);
+ if(surface.font.outlineSize)
+ {
+ ColorAlpha outlineColor = surface.outlineColor;
+ glColor4ub(outlineColor.color.r, outlineColor.color.g, outlineColor.color.b, outlineColor.a);
+ oglSurface.writingOutline = true;
+ ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
+ oglSurface.writingOutline = false;
+ }
glColor4fv(oglSurface.foreground);
((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
Win32BitmapPrinterSystem gdiSystem = displaySystem.driverData;
HDC hdc = gdiSystem.hdc;
}
- Font LoadFont(DisplaySystem displaySystem, const char * string, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * string, float size, FontFlags flags, float outlineSize, float outlineFade)
{
return (void *) bool::true;
}
Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
Win32PrinterSystem gdiSystem = displaySystem.driverData;
HDC hdc = gdiSystem.hdc;
bool opaqueText;
int xOffset;
bool writingText;
+ bool writingOutline;
ColorAlpha foreground, background;
bool opaque;
}
}
- Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
Font font;
- font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
+ font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
return font;
}
#if !defined(ECERE_NOTRUETYPE)
+#if !defined(ECERE_VANILLA)
+import "imgDistMap"
+#endif
+
#define MAX_FONT_LINK_ENTRIES 10
static HB_Script theCurrentScript;
{
glFont.glyphPacks.Add((pack = GlyphPack { key = (uintptr)packNo }));
pack.Render(glFont, fontEntryNum, glFont.displaySystem);
- pack.bitmap.alphaBlend = true;
}
lastPack = packNo;
}
pack = { key = (uintptr)packNo };
glFont.glyphPacks.Add(pack);
pack.Render(glFont, fontEntryNum, glFont.displaySystem);
- pack.bitmap.alphaBlend = true;
}
lastPack = packNo;
}
{
int ax, ay;
int x, y;
+ int ox, oy; // Outline
int w, h;
int left, top;
int bx, by;
class GlyphPack : BTNode
{
Glyph glyphs[256];
- Bitmap bitmap { };
+ Bitmap bitmap { transparent = true, alphaBlend = true };
+ Bitmap outline;
int cellWidth, cellHeight;
+ int oCellWidth, oCellHeight;
+
+ ~GlyphPack()
+ {
+ delete outline;
+ }
void Render(Font font, int startFontEntry, DisplaySystem displaySystem)
{
#if !defined(ECERE_NOTRUETYPE)
unichar c;
- int maxWidth, maxHeight;
+ int maxWidth = 0, maxHeight = 0;
int cellWidth, cellHeight;
- int width, height;
+ int oCellWidth = 0, oCellHeight = 0;
+ int width, height, oWidth = 0, oHeight = 0;
FontEntry fontEntry = null;
FT_Face faces[128];
float scales[128];
+ float outlineSize = font.outlineSize;
+ int padding = 1 + (int)outlineSize;
bool isGlyph = ((uint)key & 0x80000000) != 0;
- //int curScript = ((uint)key & 0x7F000000) >> 24;
unichar testChar = 0;
- /*
- if(isGlyph)
- {
- switch(curScript)
- {
- case HB_Script_Arabic:
- testChar = 0x621;
- // printf("\nRendering arabic in %s (%d)\n", faceName, key & 0xFFFFFF);
- break;
- case HB_Script_Devanagari:
- testChar = 0x905;
- break;
- case 60: testChar = 'あ'; break;
- case 61: testChar = 0x3400; break;
- }
- }
- */
- /*
- FT_GlyphSlot slot;
- FT_Matrix matrix;
- FT_Vector pen = { 0, 0 };
- if(fakeItalic)
- {
- matrix.xx = (FT_Fixed)( 1.0 * 0x10000L );
- matrix.xy = (FT_Fixed)( 0.3 * 0x10000L );
- matrix.yx = (FT_Fixed)( 0.0 * 0x10000L );
- matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
- FT_Set_Transform( fontEntry.face, &matrix, &pen );
- }
- FT_Set_Char_Size( fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
- */
-
- maxWidth = 0;
- maxHeight = 0;
+ Bitmap bitmap = this.bitmap;
for(c = 0; c < MAX_FONT_LINK_ENTRIES; c++)
{
matrix.yy = (FT_Fixed)( 1.0 * 0x10000L );
FT_Set_Transform(fontEntry.face, &matrix, &pen);
}
- //FT_Set_Char_Size(fontEntry.face, (int)(size * 64), (int)(size * 64), 96, 96);
fontEntry.scale = FaceSetCharSize(fontEntry.face, font.size);
if(!font.scale)
font.scale = fontEntry.scale;
{
maxWidth = Max(maxWidth, ((faces[c]->glyph->metrics.width + 64 + (64 - (faces[c]->glyph->metrics.width & 0x3F))) >> 6));
maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height + 64 + (64 - (faces[c]->glyph->metrics.height & 0x3F))) >> 6));
- //maxHeight = Max(maxHeight, ((faces[c]->glyph->metrics.height) >> 6));
}
}
this.cellWidth = cellWidth = maxWidth;
this.cellHeight = cellHeight = maxHeight;
- width = maxWidth * 16;
- height = maxHeight * 8;
+ width = pow2i(maxWidth * 16);
+ height = pow2i(maxHeight * 8);
- if(true)
+ if(outlineSize)
{
- width = pow2i(width);
- height = pow2i(height);
+ oCellWidth = 2*padding + cellWidth;
+ oCellHeight = 2*padding + cellHeight;
+ oWidth = pow2i(oCellWidth * 16);
+ oHeight = pow2i(oCellHeight * 8);
+ outline = { transparent = true, alphaBlend = true };
}
- if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false /*true*/))
+ if(bitmap.Allocate(null, width, height, 0, pixelFormatAlpha, false) &&
+ (!outline || outline.Allocate(null, oWidth, oHeight, 0, pixelFormatAlpha, false)))
{
- Bitmap bitmap = this.bitmap;
-
- bitmap.transparent = true;
+ float fade = font.outlineFade;
+ float alphaFactor = 1.0f / (0.2f + fade);
+ // float intensityFactor = 1.0f / (0.2f + outlineSize);
+ float range = outlineSize, rangeInv = 1.0f / range;
+ float * distanceMap = null;
+ byte * padded = null;
+ if(outline)
+ {
+ distanceMap = new float[oCellWidth * oCellHeight];
+ padded = new byte[oCellWidth * oCellHeight];
+ }
for(c = 0; c < 128; c++)
{
FT_Int i, j, p, q;
FT_Int xMax, yMax;
- int sx = (c % 16) * cellWidth;
- int sy = (c / 16) * cellHeight;
- int x, y;
+ int gx = ((uint)c & 0xF), gy = ((uint)c >> 4);
+ int sx = gx * cellWidth, sy = gy * cellHeight;
byte * picture = (byte *)bitmap.picture;
Glyph * glyph = &glyphs[c];
FT_GlyphSlot slot = null;
if(faces[c])
{
double em_size = 1.0 * faces[c]->units_per_EM;
- //double x_scale = faces[c]->size->metrics.x_ppem / em_size;
double y_scale = em_size ? (faces[c]->size->metrics.y_ppem / em_size) : 1;
double ascender = faces[c]->ascender * y_scale;
slot = faces[c]->glyph;
FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
- x = sx;
- y = sy;
- //printf("%d, %d\n", maxHeight, faces[c]->size->metrics.height >> 6);
-
glyph->left = slot->bitmap_left;
- // glyph->top = ((64 + (64 - faces[c]->glyph->metrics.height & 0x3F)) >> 6) + (int)(ascender - slot->bitmap_top) + height - (faces[c]->size->metrics.height >> 6);
- // glyph->top = (int)(ascender - slot->bitmap_top) + 2 * (height - maxHeight);
- //glyph->top = (int)(ascender - slot->bitmap_top) + 2 * ((((faces[c]->size->metrics.height + 64 + (64 - faces[c]->size->metrics.height & 0x3F)) >> 6)) - height);
- //glyph->top = (int)(ascender - slot->bitmap_top) + (height - (faces[c]->size->metrics.height >> 6));
-
- //glyph->top = (int)(ascender + (height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
- //glyph->top = (int)(ascender + (height *64 - /*faces[0]->size->metrics.height - */faces[c]->size->metrics.height) / 64.0 + 0.5) - slot->bitmap_top;
-
- //glyph->top = (int)((ascender - slot->bitmap_top) + (height * 64 - maxHeight * 64 + faces[c]->glyph->metrics.height - faces[c]->glyph->metrics.height) / 64);
-
- //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (height - (faces[c]->size->metrics.height >> 6));
- //glyph->top = (int)(ascender - slot->bitmap_top); // + ((faces[c]->size->metrics.height >> 6) - (faces[0]->size->metrics.height >> 6)) + (height - (faces[c]->size->metrics.height >> 6));
-
- //glyph->top = (int)(ascender - slot->bitmap_top);// + (height - maxHeight);
glyph->top = (int)(ascender - slot->bitmap_top) + (int)(font.height - (faces[c]->size->metrics.height >> 6)) / 2;
- // printf("[char: %d] mode: %d, width: %d, height: %d, pitch: %d\n", key + c, slot->bitmap.pixel_mode, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
- xMax = x + slot->bitmap.width;
- yMax = y + slot->bitmap.rows;
+ xMax = sx + slot->bitmap.width;
+ yMax = sy + slot->bitmap.rows;
{
int total = 0;
int numPixels = 0;
- //int max;
if(slot->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
{
- for(j = y, q = 0; j<yMax; j++)
+ for(j = sy, q = 0; j<yMax; j++)
{
- for(p = 0, i = x; i<xMax; i++)
+ for(p = 0, i = sx; i<xMax; i++)
{
byte value = ((byte *)slot->bitmap.buffer)[q + p++];
if(value > 32)
q += slot->bitmap.pitch;
}
}
- //max = numPixels ? (total / numPixels) : 1;
- for(j = y, q = 0; j<yMax; j++)
+ for(j = sy, q = 0; j<yMax; j++)
{
int bit = 0x80;
- for(p = 0, i = x; i<xMax; i++)
+ for(p = 0, i = sx; i<xMax; i++)
{
if(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
{
else
{
byte value = ((byte *)slot->bitmap.buffer)[q + p++];
- picture[j * bitmap.stride + i] = /*(max < 192) ? Min(255, value * 192/max) :*/ value;
+ picture[j * bitmap.stride + i] = value;
}
}
q += slot->bitmap.pitch;
}
}
+ if(outline)
+ {
+ // Generate outline from distance map
+ float * dmap = distanceMap;
+ byte *dst = outline.picture + gy * oCellHeight * oWidth + gx * oCellWidth;
+ int x, y;
+ byte * core = picture + gy * cellHeight * width + gx * cellWidth, * p;
+ memset(padded, 0, oCellWidth * oCellHeight);
+ if(slot->bitmap.width)
+ {
+ byte * src = padded + padding * oCellWidth + padding;
+ picture = core;
+ for(y = 0; y < cellHeight; y++)
+ {
+ byte * pic = picture;
+ p = src;
+ for(x = 0; x < cellWidth; x++, p++, pic++)
+ *p = *pic;
+ picture += width;
+ src += oCellWidth;
+ }
+ }
+ imgDistMapBuild(distanceMap, padded, oCellWidth, oCellHeight, 1, oCellWidth);
+
+ //core -= padding * width;
+ for(y = 0; y < oCellHeight; y++, dst += oWidth)
+ {
+ byte * dstRow = dst;
+ p = core - padding;
+ for(x = 0; x < oCellWidth; x++, dstRow++, dmap++, p++)
+ {
+ float rangeBase = (range - *dmap) * rangeInv, alpha = alphaFactor * rangeBase;
+ *dstRow = (byte)( Max( 0.0f, Min( 255.0f, alpha * 255.0f ) ) + 0.5f);
+ /*
+ if(y >= padding && y < cellWidth + padding && x >= padding && x < cellWidth + padding)
+ {
+ float intensity = Max( (float) *p * (1.0f/255.0f), intensityFactor * rangeBase );
+ byte v = (byte)( Max( 0.0f, Min( 255.0f, intensity * 255.0f ) ) + 0.5f);
+ *p = v;
+ }
+ */
+ }
+ //core += width;
+ }
+
+ glyph->ox = gx * oCellWidth;
+ glyph->oy = gy * oCellHeight;
+ }
}
glyph->x = sx;
glyph->y = sy;
}
glyph->scale = scales[c];
}
+
+ delete padded;
+ delete distanceMap;
+
#if 0
{
int c;
bitmap.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
bitmap.pixelFormat = pixelFormat8;
- /*
- //strcpy(fileName, faceName);
- if(flags)
- strcat(fileName, "Bold");
- */
- sprintf(fileName, "font%d", fid++);
+ sprintf(fileName, "font%d", fid);
ChangeExtension(fileName, "pcx", fileName);
bitmap.Save(fileName, null, 0);
bitmap.pixelFormat = pixelFormatAlpha;
+
+ if(outline)
+ {
+ for(c = 0; c<256; c++)
+ outline.palette[c] = ColorAlpha { 255, { (byte)c,(byte)c,(byte)c } };
+ outline.pixelFormat = pixelFormat8;
+
+ sprintf(fileName, "outline%d", fid);
+ ChangeExtension(fileName, "pcx", fileName);
+
+ outline.Save(fileName, null, 0);
+ outline.pixelFormat = pixelFormatAlpha;
+ }
+ fid++;
}
#endif
|| displaySystem.driver == class(Direct3D8DisplayDriver)
|| displaySystem.driver == class(Direct3D9DisplayDriver)
#endif
-
)
#endif
+ {
bitmap.MakeDD(displaySystem);
+ if(outline)
+ outline.MakeDD(displaySystem);
+ }
displaySystem.Unlock();
}
}
char faceName[512];
FontFlags flags;
float size;
+ float outlineSize;
+ float outlineFade;
int ascent, descent;
float scale;
get { return (int)(this ? descent * scale : 0); }
}
- void Setup(DisplaySystem displaySystem, const String faceName, float size, FontFlags flags)
+ void Setup(DisplaySystem displaySystem, const String faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
strcpy(this.faceName, faceName);
this.flags = flags;
this.displaySystem = displaySystem;
this.size = size;
+ this.outlineSize = outlineSize;
+ this.outlineFade = outlineFade;
}
bool LoadEntry(FaceInfo info)
return result;
}
- Font ::Load(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+ Font ::Load(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
{
Font result = null;
Array<FaceInfo> infos = ResolveFont(faceName, size, flags);
{
Font font { };
bool success = false;
- font.Setup(displaySystem, faceName, size, flags);
+ font.Setup(displaySystem, faceName, size, flags, outlineSize, outlineFade);
for(f : infos)
success |= font.LoadEntry(f);
if(success)
}
void ProcessString(DisplaySystem displaySystem, const byte * text, int len,
- void (* callback)(Surface surface, Display display, int x, int y, Glyph glyph, Bitmap bitmap),
+ bool output,
Surface surface, Display display, int * x, int y, int prevGlyph, int * rPrevGlyph, int * advance)
{
#if !defined(ECERE_NOTRUETYPE)
if(this && fontEntries[0])
{
+ LFBSurface lfbSurface = surface ? surface.driverData : null;
int previousGlyph = prevGlyph;
FT_Face previousFace = 0;
int c, nb, glyphIndex = 0;
- unichar lastPack = 0;
+ bool writingOutline = lfbSurface && lfbSurface.writingOutline;
+ int padding = writingOutline ? 1 + (int)surface.font.outlineSize : 0;
+ unichar lastPack = writingOutline ? -1 : 0;
GlyphPack pack = asciiPack;
+ Bitmap bitmap = writingOutline ? pack.outline : pack.bitmap;
int wc = 0;
uint * glyphs = null;
int numGlyphs = 0;
Glyph * lastGlyph = null;
int lastAX = 0;
- pack.bitmap.alphaBlend = true;
-
for(c = 0; c < len || (numGlyphs && (rightToLeft ? (glyphIndex >= 0) : (glyphIndex < numGlyphs)));)
{
uint glyphNo = 0;
pack.Render(this, fontEntryNum, displaySystem);
}
}
- pack.bitmap.alphaBlend = true;
+ bitmap = writingOutline ? pack.outline : pack.bitmap;
lastPack = packNo;
}
if(pack)
previousGlyph = glyph->glyphNo;
previousFace = curFontEntry ? curFontEntry.face : null;
- if(callback)
- callback(surface, display, ((*x) >> 6), y + (oy >> 6), glyph, pack.bitmap);
+ if(output)
+ surface.driver.Blit(display, surface, bitmap, ((*x) >> 6) + glyph->left - writingOutline * padding, y + (oy >> 6) + glyph->top - writingOutline * padding,
+ writingOutline ? glyph->ox : glyph->x, writingOutline ? glyph->oy : glyph->y, glyph->w + writingOutline + 2 * padding, glyph->h + writingOutline + 2 * padding);
*x += ax;
lastGlyph = glyph;
*advance = w - lastAX;
}
if(rPrevGlyph) *rPrevGlyph = previousGlyph;
- }
- if(surface)
- {
- LFBSurface lfbSurface = surface.driverData;
- lfbSurface.xOffset = 0;
+ if(lfbSurface)
+ lfbSurface.xOffset = 0;
}
#endif
}
--- /dev/null
+import "instance"
+
+#include <math.h>
+
+// Based on The ‘‘dead reckoning’’ signed distance transform
+// by George J. Grevera
+
+struct MapDistMapPoint
+{
+ float distance;
+ float x, y;
+ float bias;
+};
+
+#define IMGDISTMAP_SQRT2 (1.41421356237f)
+#define IMGDISTMAP_SQRT5 (2.2360679775f)
+#define IMGDISTMAP_SQRT10 (3.16227766017f)
+#define IMGDISTMAP_SQRT13 (3.60555127546f)
+
+
+#if defined(__GNUC__)
+ #define ALWAYS_INLINE __attribute__((always_inline))
+#else
+ #define ALWAYS_INLINE
+#endif
+
+
+static inline ALWAYS_INLINE void imgDistMapCheck( MapDistMapPoint pt, float fx, float fy, MapDistMapPoint ptref, float delta )
+{
+ float dx, dy;
+ if( ( ptref.distance + delta ) < pt.distance )
+ {
+ pt.x = ptref.x;
+ pt.y = ptref.y;
+ dx = ptref.x - fx;
+ dy = ptref.y - fy;
+ pt.distance = sqrtf( ( dx * dx ) + ( dy * dy ) ) + ptref.bias;
+ pt.bias = ptref.bias;
+ }
+}
+
+#define IMGDIST_OPFLAGS_XP1_SHIFT (0)
+#define IMGDIST_OPFLAGS_XP2_SHIFT (1)
+#define IMGDIST_OPFLAGS_XP3_SHIFT (2)
+#define IMGDIST_OPFLAGS_XM1_SHIFT (3)
+#define IMGDIST_OPFLAGS_XM2_SHIFT (4)
+#define IMGDIST_OPFLAGS_XM3_SHIFT (5)
+#define IMGDIST_OPFLAGS_YP1_SHIFT (6)
+#define IMGDIST_OPFLAGS_YP2_SHIFT (7)
+#define IMGDIST_OPFLAGS_YP3_SHIFT (8)
+#define IMGDIST_OPFLAGS_YM1_SHIFT (9)
+#define IMGDIST_OPFLAGS_YM2_SHIFT (10)
+#define IMGDIST_OPFLAGS_YM3_SHIFT (11)
+
+#define IMGDIST_OPFLAGS_XP1 (1<<IMGDIST_OPFLAGS_XP1_SHIFT)
+#define IMGDIST_OPFLAGS_XP2 (1<<IMGDIST_OPFLAGS_XP2_SHIFT)
+#define IMGDIST_OPFLAGS_XP3 (1<<IMGDIST_OPFLAGS_XP3_SHIFT)
+#define IMGDIST_OPFLAGS_XM1 (1<<IMGDIST_OPFLAGS_XM1_SHIFT)
+#define IMGDIST_OPFLAGS_XM2 (1<<IMGDIST_OPFLAGS_XM2_SHIFT)
+#define IMGDIST_OPFLAGS_XM3 (1<<IMGDIST_OPFLAGS_XM3_SHIFT)
+#define IMGDIST_OPFLAGS_YP1 (1<<IMGDIST_OPFLAGS_YP1_SHIFT)
+#define IMGDIST_OPFLAGS_YP2 (1<<IMGDIST_OPFLAGS_YP2_SHIFT)
+#define IMGDIST_OPFLAGS_YP3 (1<<IMGDIST_OPFLAGS_YP3_SHIFT)
+#define IMGDIST_OPFLAGS_YM1 (1<<IMGDIST_OPFLAGS_YM1_SHIFT)
+#define IMGDIST_OPFLAGS_YM2 (1<<IMGDIST_OPFLAGS_YM2_SHIFT)
+#define IMGDIST_OPFLAGS_YM3 (1<<IMGDIST_OPFLAGS_YM3_SHIFT)
+
+
+static inline ALWAYS_INLINE int imgDistMapForwardOpFlags( int x, int y, int sizex, int sizey )
+{
+ int opflags;
+ opflags = 0;
+ opflags |= ( x >= 1 ) << IMGDIST_OPFLAGS_XM1_SHIFT;
+ opflags |= ( x >= 2 ) << IMGDIST_OPFLAGS_XM2_SHIFT;
+ opflags |= ( x >= 3 ) << IMGDIST_OPFLAGS_XM3_SHIFT;
+ opflags |= ( y >= 1 ) << IMGDIST_OPFLAGS_YM1_SHIFT;
+ opflags |= ( y >= 2 ) << IMGDIST_OPFLAGS_YM2_SHIFT;
+ opflags |= ( y >= 3 ) << IMGDIST_OPFLAGS_YM3_SHIFT;
+ opflags |= ( x < (sizex-1) ) << IMGDIST_OPFLAGS_XP1_SHIFT;
+ opflags |= ( x < (sizex-2) ) << IMGDIST_OPFLAGS_XP2_SHIFT;
+ opflags |= ( x < (sizex-3) ) << IMGDIST_OPFLAGS_XP3_SHIFT;
+ return opflags;
+}
+
+static void imgDistMapForwardClamp( MapDistMapPoint *p, float fx, float fy, int x, int y, int sizex, int opflags )
+{
+ if( opflags & IMGDIST_OPFLAGS_XM1 )
+ imgDistMapCheck( p, fx, fy, p+( 0*sizex)+(-1), 1.0f );
+ if( opflags & IMGDIST_OPFLAGS_YM1 )
+ {
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 0), 1.0f );
+ if( opflags & IMGDIST_OPFLAGS_XM1 )
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+(-1), IMGDISTMAP_SQRT2 );
+ if( opflags & IMGDIST_OPFLAGS_XP1 )
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 1), IMGDISTMAP_SQRT2 );
+ if( opflags & IMGDIST_OPFLAGS_XM2 )
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+(-2), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XP2 )
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 2), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XM3 )
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+(-3), IMGDISTMAP_SQRT10 );
+ if( opflags & IMGDIST_OPFLAGS_XP3 )
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 3), IMGDISTMAP_SQRT10 );
+ }
+ if( opflags & IMGDIST_OPFLAGS_YM2 )
+ {
+ if( opflags & IMGDIST_OPFLAGS_XM1 )
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+(-1), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XP1 )
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+( 1), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XM3 )
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+(-3), IMGDISTMAP_SQRT13 );
+ if( opflags & IMGDIST_OPFLAGS_XP3 )
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+( 3), IMGDISTMAP_SQRT13 );
+ }
+ if( opflags & IMGDIST_OPFLAGS_YM3 )
+ {
+ if( opflags & IMGDIST_OPFLAGS_XM1 )
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+(-1), IMGDISTMAP_SQRT10 );
+ if( opflags & IMGDIST_OPFLAGS_XP1 )
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+( 1), IMGDISTMAP_SQRT10 );
+ if( opflags & IMGDIST_OPFLAGS_XM2 )
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+(-2), IMGDISTMAP_SQRT13 );
+ if( opflags & IMGDIST_OPFLAGS_XP2 )
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+( 2), IMGDISTMAP_SQRT13 );
+ }
+}
+
+static inline ALWAYS_INLINE int imgDistMapBackwardOpFlags( int x, int y, int sizex, int sizey )
+{
+ int opflags;
+ opflags = 0;
+ opflags |= ( x >= 1 ) << IMGDIST_OPFLAGS_XM1_SHIFT;
+ opflags |= ( x >= 2 ) << IMGDIST_OPFLAGS_XM2_SHIFT;
+ opflags |= ( x >= 3 ) << IMGDIST_OPFLAGS_XM3_SHIFT;
+ opflags |= ( x < (sizex-1) ) << IMGDIST_OPFLAGS_XP1_SHIFT;
+ opflags |= ( x < (sizex-2) ) << IMGDIST_OPFLAGS_XP2_SHIFT;
+ opflags |= ( x < (sizex-3) ) << IMGDIST_OPFLAGS_XP3_SHIFT;
+ opflags |= ( y < (sizey-1) ) << IMGDIST_OPFLAGS_YP1_SHIFT;
+ opflags |= ( y < (sizey-2) ) << IMGDIST_OPFLAGS_YP2_SHIFT;
+ opflags |= ( y < (sizey-3) ) << IMGDIST_OPFLAGS_YP3_SHIFT;
+ return opflags;
+}
+
+static void imgDistMapBackwardClamp( MapDistMapPoint *p, float fx, float fy, int x, int y, int sizex, int opflags )
+{
+ if( opflags & IMGDIST_OPFLAGS_XP1 )
+ imgDistMapCheck( p, fx, fy, p+( 0*sizex)+( 1), 1.0f );
+ if( opflags & IMGDIST_OPFLAGS_YP1 )
+ {
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 0), 1.0f );
+ if( opflags & IMGDIST_OPFLAGS_XM1 )
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+(-1), IMGDISTMAP_SQRT2 );
+ if( opflags & IMGDIST_OPFLAGS_XP1 )
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 1), IMGDISTMAP_SQRT2 );
+ if( opflags & IMGDIST_OPFLAGS_XM2 )
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+(-2), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XP2 )
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 2), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XM3 )
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+(-3), IMGDISTMAP_SQRT10 );
+ if( opflags & IMGDIST_OPFLAGS_XP3 )
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 3), IMGDISTMAP_SQRT10 );
+ }
+ if( opflags & IMGDIST_OPFLAGS_YP2 )
+ {
+ if( opflags & IMGDIST_OPFLAGS_XM1 )
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+(-1), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XP1 )
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+( 1), IMGDISTMAP_SQRT5 );
+ if( opflags & IMGDIST_OPFLAGS_XM3 )
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+(-3), IMGDISTMAP_SQRT13 );
+ if( opflags & IMGDIST_OPFLAGS_XP3 )
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+( 3), IMGDISTMAP_SQRT13 );
+ }
+ if( opflags & IMGDIST_OPFLAGS_YP3 )
+ {
+ if( opflags & IMGDIST_OPFLAGS_XM1 )
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+(-1), IMGDISTMAP_SQRT10 );
+ if( opflags & IMGDIST_OPFLAGS_XP1 )
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+( 1), IMGDISTMAP_SQRT10 );
+ if( opflags & IMGDIST_OPFLAGS_XM2 )
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+(-2), IMGDISTMAP_SQRT13 );
+ if( opflags & IMGDIST_OPFLAGS_XP2 )
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+( 2), IMGDISTMAP_SQRT13 );
+ }
+}
+
+
+// The outer edge must be all zeroes
+void imgDistMapBuild( float *distancemap, byte *src, int sizex, int sizey, int srcbytesperpixel, int srcbytesperline )
+{
+ int x, y, mapindex, srcindex;
+ byte pixel;
+ float fx, fy, bias, maxdistance;
+ MapDistMapPoint *ptmap;
+ MapDistMapPoint *p;
+
+ if( ( sizex < 4 ) || ( sizey < 4 ) )
+ return;
+
+ ptmap = new MapDistMapPoint[sizex * sizey];
+
+ maxdistance = sizex + sizey;
+ mapindex = 0;
+ for( y = 0 ; y < sizey ; y++ )
+ {
+ srcindex = y * srcbytesperline;
+ for( x = 0 ; x < sizex ; x++ )
+ {
+ pixel = src[ srcindex ];
+ if( pixel )
+ {
+ fx = (float)x;
+ fy = (float)y;
+ bias = 1.0f - ( (float)pixel * (1.0f/255.0f) );
+ ptmap[mapindex].distance = bias;
+ ptmap[mapindex].x = fx;
+ ptmap[mapindex].y = fy;
+ ptmap[mapindex].bias = bias;
+ }
+ else
+ {
+ ptmap[mapindex].distance = maxdistance;
+ ptmap[mapindex].x = -1.0f;
+ ptmap[mapindex].y = -1.0f;
+ ptmap[mapindex].bias = 0.0f;
+ }
+ mapindex++;
+ srcindex += srcbytesperpixel;
+ }
+ }
+
+ // Forward pass
+ for( y = 0 ; y < 3 ; y++ )
+ {
+ mapindex = y * sizex;
+ for( x = 0 ; x < sizex ; x++ )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapForwardClamp( p, fx, fy, x, y, sizex, imgDistMapForwardOpFlags( x, y, sizex, sizey ) );
+ mapindex++;
+ }
+ }
+ for( ; y < sizey - 3 ; y++ )
+ {
+ mapindex = y * sizex;
+ for( x = 0 ; x < 3 ; x++ )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapForwardClamp( p, fx, fy, x, y, sizex, imgDistMapForwardOpFlags( x, y, sizex, sizey ) );
+ mapindex++;
+ }
+ for( x = 3 ; x < sizex - 3 ; x++ )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+
+ imgDistMapCheck( p, fx, fy, p+( 0*sizex)+(-1), 1.0f );
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 0), 1.0f );
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+(-1), IMGDISTMAP_SQRT2 );
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 1), IMGDISTMAP_SQRT2 );
+
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+(-1), IMGDISTMAP_SQRT5 );
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+( 1), IMGDISTMAP_SQRT5 );
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+(-2), IMGDISTMAP_SQRT5 );
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 2), IMGDISTMAP_SQRT5 );
+
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+(-1), IMGDISTMAP_SQRT10 );
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+( 1), IMGDISTMAP_SQRT10 );
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+(-3), IMGDISTMAP_SQRT10 );
+ imgDistMapCheck( p, fx, fy, p+(-1*sizex)+( 3), IMGDISTMAP_SQRT10 );
+
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+(-2), IMGDISTMAP_SQRT13 );
+ imgDistMapCheck( p, fx, fy, p+(-3*sizex)+( 2), IMGDISTMAP_SQRT13 );
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+(-3), IMGDISTMAP_SQRT13 );
+ imgDistMapCheck( p, fx, fy, p+(-2*sizex)+( 3), IMGDISTMAP_SQRT13 );
+ mapindex++;
+ }
+ for( ; x < sizex ; x++ )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapForwardClamp( p, fx, fy, x, y, sizex, imgDistMapForwardOpFlags( x, y, sizex, sizey ) );
+ mapindex++;
+ }
+ }
+ for( ; y < sizey ; y++ )
+ {
+ mapindex = y * sizex;
+ for( x = 0 ; x < sizex ; x++ )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapForwardClamp( p, fx, fy, x, y, sizex, imgDistMapForwardOpFlags( x, y, sizex, sizey ) );
+ mapindex++;
+ }
+ }
+
+ // Backward pass
+ for( y = sizey - 1 ; y >= sizey - 3 ; y-- )
+ {
+ mapindex = ( y * sizex ) + ( sizex - 1 );
+ for( x = sizex - 1 ; x >= 0 ; x-- )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapBackwardClamp( p, fx, fy, x, y, sizex, imgDistMapBackwardOpFlags( x, y, sizex, sizey ) );
+ distancemap[ mapindex ] = p->distance;
+ mapindex--;
+ }
+ }
+ for( ; y >= 3 ; y-- )
+ {
+ mapindex = ( y * sizex ) + ( sizex - 1 );
+ for( x = sizex - 1 ; x >= sizex - 3 ; x-- )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapBackwardClamp( p, fx, fy, x, y, sizex, imgDistMapBackwardOpFlags( x, y, sizex, sizey ) );
+ distancemap[ mapindex ] = p->distance;
+ mapindex--;
+ }
+ for( ; x >= 3 ; x-- )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+
+ imgDistMapCheck( p, fx, fy, p+( 0*sizex)+( 1), 1.0f );
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 0), 1.0f );
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+(-1), IMGDISTMAP_SQRT2 );
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 1), IMGDISTMAP_SQRT2 );
+
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+(-1), IMGDISTMAP_SQRT5 );
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+( 1), IMGDISTMAP_SQRT5 );
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+(-2), IMGDISTMAP_SQRT5 );
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 2), IMGDISTMAP_SQRT5 );
+
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+(-1), IMGDISTMAP_SQRT10 );
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+( 1), IMGDISTMAP_SQRT10 );
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+(-3), IMGDISTMAP_SQRT10 );
+ imgDistMapCheck( p, fx, fy, p+( 1*sizex)+( 3), IMGDISTMAP_SQRT10 );
+
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+(-2), IMGDISTMAP_SQRT13 );
+ imgDistMapCheck( p, fx, fy, p+( 3*sizex)+( 2), IMGDISTMAP_SQRT13 );
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+(-3), IMGDISTMAP_SQRT13 );
+ imgDistMapCheck( p, fx, fy, p+( 2*sizex)+( 3), IMGDISTMAP_SQRT13 );
+
+ distancemap[ mapindex ] = p->distance;
+ mapindex--;
+ }
+ for( ; x >= 0 ; x-- )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapBackwardClamp( p, fx, fy, x, y, sizex, imgDistMapBackwardOpFlags( x, y, sizex, sizey ) );
+ distancemap[ mapindex ] = p->distance;
+ mapindex--;
+ }
+ }
+ for( ; y >= 0 ; y-- )
+ {
+ mapindex = ( y * sizex ) + ( sizex - 1 );
+ for( x = sizex - 1 ; x >= 0 ; x-- )
+ {
+ p = &ptmap[mapindex];
+ fx = (float)x;
+ fy = (float)y;
+ imgDistMapBackwardClamp( p, fx, fy, x, y, sizex, imgDistMapBackwardOpFlags( x, y, sizex, sizey ) );
+ distancemap[ mapindex ] = p->distance;
+ mapindex--;
+ }
+ }
+
+ delete ptmap;
+}
// Default Settings
surface.TextFont(usedFont.font);
surface.TextOpacity(false);
+ surface.outlineColor = black;
OnRedraw(surface);
surface.TextFont(usedFont.font);
surface.TextOpacity(false);
+ surface.outlineColor = black;
OnDrawOverChildren(surface);