diff --git a/data/fontDistanceField/font1.frag b/data/fontDistanceField/font1.frag index dc4d47c1..fda03013 100644 --- a/data/fontDistanceField/font1.frag +++ b/data/fontDistanceField/font1.frag @@ -12,37 +12,44 @@ uniform int EW_SoftEdge; varying vec2 f_texcoord; varying vec4 f_color; -void main(void) { - vec4 tmpcolor = texture2D(EW_texID, f_texcoord); - vec4 outColor = vec4(0,0,0,0); - // compare distance with 0.5 that represent the middle ... - /* - if (tmpcolor[0]>0.5) { - outColor = f_color; - outColor[3] = 1.0; - } else if (tmpcolor[0]>0.49) { - // antialiasing : - outColor = f_color; - outColor[3] = 0.0;//(tmpcolor[3]-0.49)*1.0/0.02; - } - */ - outColor = f_color; - outColor[3] = smoothstep(0.35, 0.65, tmpcolor[0]); - /* - outColor = f_color;// * tmpcolor[3]; - if (1==EW_SoftEdge) { - outColor[3] = smoothstep(EW_SoftEdgeMin, EW_SoftEdgeMax, tmpcolor[3]); - } else { - if (tmpcolor[3]>0.5) { - outColor[3] = 1.0; - } else { - outColor[3] = 0.0; - } - } - */ - //outColor = vec4(0,0,0,0); - //outColor[3] = tmpcolor[3]; - gl_FragColor = outColor; - //gl_FragColor = tmpcolor; -} + vec3 glyph_color = vec3(1.0,1.0,1.0); +const float glyph_center = 0.50; + vec3 outline_color = vec3(0.0,0.0,0.0); +const float outline_center = 0.55; + vec3 glow_color = vec3(1.0,1.0,1.0); +const float glow_center = 1.25; +void main(void) { + //vec4 color = texture2D(EW_texID, vec2(int(f_texcoord[0]*256.0)/256.0,int(f_texcoord[1]*256.0)/256.0) ); + vec4 color = texture2D(EW_texID, f_texcoord ); + float dist = color.r; + float width = fwidth(dist); + float alpha = smoothstep(glyph_center-width, glyph_center+width, dist); + + // Smooth + + gl_FragColor = vec4(glyph_color, alpha); + + // Outline + /* + float mu = smoothstep(outline_center-width, outline_center+width, dist); + vec3 rgb = mix(outline_color, glyph_color, mu); + gl_FragColor = vec4(rgb, max(alpha,mu)); + */ + // Glow + /* + vec3 rgb = mix(glow_color, glyph_color, alpha); + float mu = smoothstep(glyph_center, glow_center, sqrt(dist)); + gl_FragColor = vec4(rgb, max(alpha,mu)); + */ + + // Glow + outline + /* + vec3 rgb = mix(glow_color, glyph_color, alpha); + float mu = smoothstep(glyph_center, glow_center, sqrt(dist)); + color = vec4(rgb, max(alpha,mu)); + float beta = smoothstep(outline_center-width, outline_center+width, dist); + rgb = mix(outline_color, color.rgb, beta); + gl_FragColor = vec4(rgb, max(color.a,beta)); + */ +} diff --git a/data/fontDistanceField/font1.vert b/data/fontDistanceField/font1.vert index 1050877b..a0d1fabd 100644 --- a/data/fontDistanceField/font1.vert +++ b/data/fontDistanceField/font1.vert @@ -21,6 +21,7 @@ void main(void) { f_color = EW_color; } + /* // Distance map contour texturing according to Green (2007), // implementation by Stefan Gustavson 2009. diff --git a/external/edtaa3/edtaa3/edtaa3func.c b/external/edtaa3/edtaa3/edtaa3func.c index 530d6d80..093b6e2f 100644 --- a/external/edtaa3/edtaa3/edtaa3func.c +++ b/external/edtaa3/edtaa3/edtaa3func.c @@ -5,12 +5,12 @@ * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY STEFAN GUSTAVSON ''AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF @@ -65,27 +65,27 @@ */ void computegradient(double *img, int w, int h, double *gx, double *gy) { - int i,j,k; - double glength; + int i,j,k; + double glength; #define SQRT2 1.4142136 - for(i = 1; i < h-1; i++) { // Avoid edges where the kernels would spill over - for(j = 1; j < w-1; j++) { - k = i*w + j; - if((img[k]>0.0) && (img[k]<1.0)) { // Compute gradient for edge pixels only - gx[k] = -img[k-w-1] - SQRT2*img[k-1] - img[k+w-1] + img[k-w+1] + SQRT2*img[k+1] + img[k+w+1]; - gy[k] = -img[k-w-1] - SQRT2*img[k-w] - img[k+w-1] + img[k-w+1] + SQRT2*img[k+w] + img[k+w+1]; - glength = gx[k]*gx[k] + gy[k]*gy[k]; - if(glength > 0.0) { // Avoid division by zero - glength = sqrt(glength); - gx[k]=gx[k]/glength; - gy[k]=gy[k]/glength; - } - } - } - } - // TODO: Compute reasonable values for gx, gy also around the image edges. - // (These are zero now, which reduces the accuracy for a 1-pixel wide region - // around the image edge.) 2x2 kernels would be suitable for this. + for(i = 1; i < h-1; i++) { // Avoid edges where the kernels would spill over + for(j = 1; j < w-1; j++) { + k = i*w + j; + if((img[k]>0.0) && (img[k]<1.0)) { // Compute gradient for edge pixels only + gx[k] = -img[k-w-1] - SQRT2*img[k-1] - img[k+w-1] + img[k-w+1] + SQRT2*img[k+1] + img[k+w+1]; + gy[k] = -img[k-w-1] - SQRT2*img[k-w] - img[k+w-1] + img[k-w+1] + SQRT2*img[k+w] + img[k+w+1]; + glength = gx[k]*gx[k] + gy[k]*gy[k]; + if(glength > 0.0) { // Avoid division by zero + glength = sqrt(glength); + gx[k]=gx[k]/glength; + gy[k]=gy[k]/glength; + } + } + } + } + // TODO: Compute reasonable values for gx, gy also around the image edges. + // (These are zero now, which reduces the accuracy for a 1-pixel wide region + // around the image edge.) 2x2 kernels would be suitable for this. } /* @@ -97,66 +97,69 @@ void computegradient(double *img, int w, int h, double *gx, double *gy) * accuracy at and near edges, and reduces the error even at distant pixels * provided that the gradient direction is accurately estimated. */ -double edgedf(double gx, double gy, double a) -{ - double df, glength, temp, a1; - - if ((gx == 0) || (gy == 0)) { // Either A) gu or gv are zero, or B) both - df = 0.5-a; // Linear approximation is A) correct or B) a fair guess - } else { - glength = sqrt(gx*gx + gy*gy); - if(glength>0) { - gx = gx/glength; - gy = gy/glength; - } - /* Everything is symmetric wrt sign and transposition, - * so move to first octant (gx>=0, gy>=0, gx>=gy) to - * avoid handling all possible edge directions. - */ - gx = fabs(gx); - gy = fabs(gy); - if(gx0) { + gx = gx/glength; + gy = gy/glength; + } + /* Everything is symmetric wrt sign and transposition, + * so move to first octant (gx>=0, gy>=0, gx>=gy) to + * avoid handling all possible edge directions. + */ + gx = fabs(gx); + gy = fabs(gy); + if(gx 1.0) a = 1.0; - if(a < 0.0) a = 0.0; // Clip grayscale values outside the range [0,1] - if(a == 0.0) return 1000000.0; // Not an object pixel, return "very far" ("don't know yet") - - dx = (double)xi; - dy = (double)yi; - di = sqrt(dx*dx + dy*dy); // Length of integer vector, like a traditional EDT - if(di==0) { // Use local gradient only at edges - // Estimate based on local gradient only - df = edgedf(gx, gy, a); - } else { - // Estimate gradient based on direction to edge (accurate for large di) - df = edgedf(dx, dy, a); - } - return di + df; // Same metric as edtaa2, except at edges (where di=0) +double distaa3(double *img, double *gximg, double *gyimg, int w, int c, int xc, int yc, int xi, int yi) { + double di, df, dx, dy, gx, gy, a; + int closest; + + closest = c-xc-yc*w; // Index to the edge pixel pointed to from c + a = img[closest]; // Grayscale value at the edge pixel + gx = gximg[closest]; // X gradient component at the edge pixel + gy = gyimg[closest]; // Y gradient component at the edge pixel + + if(a > 1.0) { + a = 1.0; + } + if(a < 0.0) { + a = 0.0; // Clip grayscale values outside the range [0,1] + } + if(a == 0.0) { + return 1000000.0; // Not an object pixel, return "very far" ("don't know yet") + } + + dx = (double)xi; + dy = (double)yi; + di = sqrt(dx*dx + dy*dy); // Length of integer vector, like a traditional EDT + if(di==0) { // Use local gradient only at edges + // Estimate based on local gradient only + df = edgedf(gx, gy, a); + } else { + // Estimate gradient based on direction to edge (accurate for large di) + df = edgedf(dx, dy, a); + } + return di + df; // Same metric as edtaa2, except at edges (where di=0) } // Shorthand macro: add ubiquitous parameters dist, gx, gy, img and w and call distaa3() @@ -164,414 +167,358 @@ double distaa3(double *img, double *gximg, double *gyimg, int w, int c, int xc, void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, short *disty, double *dist) { - int x, y, i, c; - int offset_u, offset_ur, offset_r, offset_rd, - offset_d, offset_dl, offset_l, offset_lu; - double olddist, newdist; - int cdistx, cdisty, newdistx, newdisty; - int changed; - double epsilon = 1e-3; + int x, y, i, c; + int offset_u, offset_ur, offset_r, offset_rd, + offset_d, offset_dl, offset_l, offset_lu; + double olddist, newdist; + int cdistx, cdisty, newdistx, newdisty; + int changed; + double epsilon = 1e-3; + + /* Initialize index offsets for the current image width */ + offset_u = -w; + offset_ur = -w+1; + offset_r = 1; + offset_rd = w+1; + offset_d = w; + offset_dl = w-1; + offset_l = -1; + offset_lu = -w-1; + + /* Initialize the distance images */ + for(i=0; i 0) // If non-zero distance or not set yet - { - c = i + offset_u; // Index of candidate for testing - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx; - newdisty = cdisty+1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_ur; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx-1; - newdisty = cdisty+1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - changed = 1; - } - } - i++; - - /* Middle pixels have all neighbors */ - for(x=1; x 0) // If not already zero distance - { - c = i+offset_l; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx+1; - newdisty = cdisty; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_lu; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx+1; - newdisty = cdisty+1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_u; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx; - newdisty = cdisty+1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - changed = 1; - } - } - - /* Move index to second rightmost pixel of current row. */ - /* Rightmost pixel is skipped, it has no right neighbor. */ - i = y*w + w-2; - - /* scan left, propagate distance from right */ - for(x=w-2; x>=0; x--, i--) - { - olddist = dist[i]; - if(olddist <= 0) continue; // Already zero distance - - c = i+offset_r; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx-1; - newdisty = cdisty; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - changed = 1; - } - } - } - - /* Scan rows in reverse order, except last row */ - for(y=h-2; y>=0; y--) - { - /* move index to rightmost pixel of current row */ - i = y*w + w-1; - - /* Scan left, propagate distances from below & right */ - - /* Rightmost pixel is special, has no right neighbors */ - olddist = dist[i]; - if(olddist > 0) // If not already zero distance - { - c = i+offset_d; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx; - newdisty = cdisty-1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_dl; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx+1; - newdisty = cdisty-1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - changed = 1; - } - } - i--; - - /* Middle pixels have all neighbors */ - for(x=w-2; x>0; x--, i--) - { - olddist = dist[i]; - if(olddist <= 0) continue; // Already zero distance - - c = i+offset_r; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx-1; - newdisty = cdisty; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_rd; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx-1; - newdisty = cdisty-1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_d; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx; - newdisty = cdisty-1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_dl; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx+1; - newdisty = cdisty-1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - changed = 1; - } - } - /* Leftmost pixel is special, has no left neighbors */ - olddist = dist[i]; - if(olddist > 0) // If not already zero distance - { - c = i+offset_r; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx-1; - newdisty = cdisty; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_rd; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx-1; - newdisty = cdisty-1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - olddist=newdist; - changed = 1; - } - - c = i+offset_d; - cdistx = distx[c]; - cdisty = disty[c]; - newdistx = cdistx; - newdisty = cdisty-1; - newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); - if(newdist < olddist-epsilon) - { - distx[i]=newdistx; - disty[i]=newdisty; - dist[i]=newdist; - changed = 1; - } - } - - /* Move index to second leftmost pixel of current row. */ - /* Leftmost pixel is skipped, it has no left neighbor. */ - i = y*w + 1; - for(x=1; x 0) { // If non-zero distance or not set yet + c = i + offset_u; // Index of candidate for testing + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx; + newdisty = cdisty+1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_ur; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx-1; + newdisty = cdisty+1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + changed = 1; + } + } + i++; + /* Middle pixels have all neighbors */ + for(x=1; x 0) {// If not already zero distance + c = i+offset_l; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx+1; + newdisty = cdisty; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_lu; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx+1; + newdisty = cdisty+1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_u; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx; + newdisty = cdisty+1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + changed = 1; + } + } + /* Move index to second rightmost pixel of current row. */ + /* Rightmost pixel is skipped, it has no right neighbor. */ + i = y*w + w-2; + /* scan left, propagate distance from right */ + for(x=w-2; x>=0; x--, i--) { + olddist = dist[i]; + if(olddist <= 0) { + continue; // Already zero distance + } + c = i+offset_r; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx-1; + newdisty = cdisty; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + changed = 1; + } + } + } + /* Scan rows in reverse order, except last row */ + for(y=h-2; y>=0; y--) { + /* move index to rightmost pixel of current row */ + i = y*w + w-1; + /* Scan left, propagate distances from below & right */ + /* Rightmost pixel is special, has no right neighbors */ + olddist = dist[i]; + if(olddist > 0) { // If not already zero distance + c = i+offset_d; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx; + newdisty = cdisty-1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_dl; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx+1; + newdisty = cdisty-1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + changed = 1; + } + } + i--; + /* Middle pixels have all neighbors */ + for(x=w-2; x>0; x--, i--) { + olddist = dist[i]; + if(olddist <= 0) { + continue; // Already zero distance + } + c = i+offset_r; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx-1; + newdisty = cdisty; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_rd; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx-1; + newdisty = cdisty-1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_d; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx; + newdisty = cdisty-1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_dl; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx+1; + newdisty = cdisty-1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + changed = 1; + } + } + /* Leftmost pixel is special, has no left neighbors */ + olddist = dist[i]; + if(olddist > 0) { // If not already zero distance + c = i+offset_r; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx-1; + newdisty = cdisty; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_rd; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx-1; + newdisty = cdisty-1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + olddist=newdist; + changed = 1; + } + c = i+offset_d; + cdistx = distx[c]; + cdisty = disty[c]; + newdistx = cdistx; + newdisty = cdisty-1; + newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty); + if(newdist < olddist-epsilon) { + distx[i]=newdistx; + disty[i]=newdisty; + dist[i]=newdist; + changed = 1; + } + } + /* Move index to second leftmost pixel of current row. */ + /* Leftmost pixel is skipped, it has no left neighbor. */ + i = y*w + 1; + for(x=1; x #include #include +#include #undef __class__ #define __class__ "resource::DistanceFieldFont" @@ -27,7 +28,7 @@ ewol::resource::DistanceFieldFont::DistanceFieldFont(const std::string& _fontNam m_font = NULL; m_lastGlyphPos.setValue(1,1); m_lastRawHeigh = 0; - m_size = 36; + m_size = 70; std::string localName = _fontName; std::vector folderList; if (true == ewol::getContext().getFontDefault().getUseExternal()) { @@ -112,45 +113,41 @@ ewol::resource::DistanceFieldFont::~DistanceFieldFont(void) { ewol::resource::FontFreeType::release(m_font); } -void ewol::resource::DistanceFieldFont::GenerateSoftDistanceField(const egami::ImageMono& _input, egami::Image& _output) { - unsigned char *img = &_input[0]; - unsigned int width = _input.getSize().x(); - unsigned int height = _input.getSize().y(); - std::vector xdist; - std::vector ydist; - std::vector gx; - std::vector gy; - std::vector data; - std::vector outside; - std::vector inside; - xdist.resize(width*height, 0); - ydist.resize(width*height, 0); - gx.resize(width*height, 0.0); - gy.resize(width*height, 0.0); - data.resize(width*height, 0.0); - outside.resize(width*height, 0.0); - inside.resize(width*height, 0.0); - +void ewol::resource::DistanceFieldFont::GenerateDistanceField(const egami::ImageMono& _input, egami::Image& _output) { + int32_t size = _input.getSize().x() * _input.getSize().y(); + std::vector xdist(size); + std::vector ydist(size); + std::vector gx(size); + std::vector gy(size); + std::vector data(size); + std::vector outside(size); + std::vector inside(size); // Convert img into double (data) double img_min = 255, img_max = -255; - for(size_t iii = 0; iii < data.size(); ++iii) { - double v = img[iii]; - data[iii] = v; - if (v > img_max) { - img_max = v; - } - if (v < img_min) { - img_min = v; + for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) { + for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) { + int32_t iii = yyy * _input.getSize().x() + xxx; + double v = _input.get(ivec2(xxx, yyy)); + data[iii] = v; + if (v > img_max) { + img_max = v; + } + if (v < img_min) { + img_min = v; + } } } // Rescale image levels between 0 and 1 - for(size_t iii = 0; iii < data.size(); ++iii) { - data[iii] = (img[iii]-img_min)/img_max; + for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) { + for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) { + int32_t iii = yyy * _input.getSize().x() + xxx; + data[iii] = (_input.get(ivec2(xxx, yyy))-img_min)/img_max; + } } // Compute outside = edtaa3(bitmap); % Transform background (0's) computegradient(&data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]); - edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().y(), _input.getSize().x(), &xdist[0], &ydist[0], &outside[0]); + edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &outside[0]); for(size_t iii = 0; iii < outside.size(); ++iii) { if( outside[iii] < 0 ) { outside[iii] = 0.0; @@ -168,7 +165,7 @@ void ewol::resource::DistanceFieldFont::GenerateSoftDistanceField(const egami::I data[iii] = 1 - data[iii]; } computegradient( &data[0], _input.getSize().x(), _input.getSize().y(), &gx[0], &gy[0]); - edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().y(), _input.getSize().x(), &xdist[0], &ydist[0], &inside[0]); + edtaa3(&data[0], &gx[0], &gy[0], _input.getSize().x(), _input.getSize().y(), &xdist[0], &ydist[0], &inside[0]); for(size_t iii = 0; iii < inside.size(); ++iii) { if( inside[iii] < 0 ) { inside[iii] = 0.0; @@ -195,106 +192,6 @@ void ewol::resource::DistanceFieldFont::GenerateSoftDistanceField(const egami::I } } -class GirdDF { - private: - std::vector m_data; - ivec2 m_size; - ivec2 m_error; - public: - GirdDF(const ivec2& _size, const ivec2& _base = ivec2(0,0), const ivec2& _error = ivec2(0,0)) { - m_size = _size; - m_data.resize(m_size.x()*m_size.y(), _base); - m_error = _error; - } - const ivec2& get(const ivec2& _pos) const { - if( _pos.x()>0 && _pos.x()0 && _pos.y()0 && _pos.x()0 && _pos.y()= 0;--xxx) { - ivec2 data = get(ivec2(xxx, yyy)); - compare(data, ivec2(xxx, yyy), ivec2(1, 0)); - set(ivec2(xxx, yyy), data ); - } - } - // Second pass - for (int32_t yyy = m_size.y()-1; yyy >= 0; --yyy) { - for (int32_t xxx = m_size.x()-1; xxx >= 0; --xxx) { - ivec2 data = get(ivec2(xxx, yyy)); - compare(data, ivec2(xxx, yyy), ivec2( 1, 0)); - compare(data, ivec2(xxx, yyy), ivec2( 0, 1)); - compare(data, ivec2(xxx, yyy), ivec2(-1, 1)); - compare(data, ivec2(xxx, yyy), ivec2( 1, 1)); - set(ivec2(xxx, yyy), data ); - } - for (int32_t xxx = 0; xxx < m_size.x(); ++xxx) { - ivec2 data = get(ivec2(xxx, yyy)); - compare(data, ivec2(xxx, yyy), ivec2(-1, 0)); - set(ivec2(xxx, yyy), data); - } - } - } -}; - -void ewol::resource::DistanceFieldFont::GenerateDistanceField(const egami::ImageMono& _input, egami::Image& _output) { - GirdDF myGird1(_input.getSize(), ivec2(0,0), ivec2(0, 0)); - GirdDF myGird2(_input.getSize(), ivec2(0,0), ivec2(9999, 9999)); - - // Reformat gird : - for (int32_t xxx = 0; xxx < _input.getSize().x(); ++xxx) { - for (int32_t yyy = 0; yyy < _input.getSize().y(); ++yyy) { - if ( _input.get(ivec2(xxx, yyy)) < 128 ) { - myGird1.set(ivec2(xxx, yyy), ivec2(0, 0)); - myGird2.set(ivec2(xxx, yyy), ivec2(9999, 9999)); - } else { - myGird1.set(ivec2(xxx, yyy), ivec2(9999, 9999)); - myGird2.set(ivec2(xxx, yyy), ivec2(0, 0)); - } - } - } - // Create internal distance of the 2 layer mode : - myGird1.GenerateSoftDistanceField(); - myGird2.GenerateSoftDistanceField(); - // Generate output : - _output.resize(_input.getSize(), etk::Color<>(0)); - _output.clear(etk::Color<>(0)); - for (int32_t xxx = 0; xxx < _output.getSize().x(); ++xxx) { - for (int32_t yyy = 0; yyy < _output.getSize().y(); ++yyy) { - float dist1 = myGird1.get(ivec2(xxx, yyy)).length(); - float dist2 = myGird2.get(ivec2(xxx, yyy)).length(); - float dist = dist1 - dist2; - float value = etk_avg(0.0f, dist*15.0f + 128.0f, 256.0f); - _output.set(ivec2(xxx, yyy), etk::Color<>((int32_t)value,(int32_t)value,(int32_t)value,256)); - } - } -} - bool ewol::resource::DistanceFieldFont::addGlyph(const char32_t& _val) { bool hasChange = false; if (m_font == NULL) {