Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
FreeType
FreeType Demo Programs
Commits
3b0423bc
Commit
3b0423bc
authored
Aug 22, 2020
by
Anuj Verma
Committed by
Werner Lemberg
Dec 22, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ftsdf] Draw SDF to display.
* src/ftsdf.c (clamp, smoothstep, draw): New function.
parent
70df7820
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
249 additions
and
0 deletions
+249
-0
ChangeLog
ChangeLog
+6
-0
src/ftsdf.c
src/ftsdf.c
+243
-0
No files found.
ChangeLog
View file @
3b0423bc
2020-08-22 Anuj Verma <anujv@iitbhilai.ac.in>
[ftsdf] Draw SDF to display.
* src/ftsdf.c (clamp, smoothstep, draw): New function.
2020-08-22 Anuj Verma <anujv@iitbhilai.ac.in>
[ftsdf] Handle window events.
...
...
src/ftsdf.c
View file @
3b0423bc
...
...
@@ -391,4 +391,247 @@
return
ret
;
}
/* Clamp value `x` between `lower_limit` and `upper_limit`. */
float
clamp
(
float
x
,
float
lower_limit
,
float
upper_limit
)
{
if
(
x
<
lower_limit
)
x
=
lower_limit
;
if
(
x
>
upper_limit
)
x
=
upper_limit
;
return
x
;
}
/* Do smooth interpolation of value `x` between `edge0` and `edge1` */
/* using a polynomial function. */
/* */
/* This implementation is taken from Wikipedia. */
/* */
/* https://en.wikipedia.org/wiki/Smoothstep */
float
smoothstep
(
float
edge0
,
float
edge1
,
float
x
)
{
/* scale, bias and saturate x to 0..1 range */
x
=
clamp
(
(
x
-
edge0
)
/
(
edge1
-
edge0
),
0
.
0
,
1
.
0
);
/* evaluate polynomial */
return
x
*
x
*
(
3
-
2
*
x
);
}
/* Draw an SDF image to the display. */
static
FT_Error
draw
(
void
)
{
FT_Bitmap
*
bitmap
=
&
status
.
face
->
glyph
->
bitmap
;
Box
draw_region
;
Box
sample_region
;
Vec2
center
;
FT_Short
*
buffer
;
if
(
!
bitmap
||
!
bitmap
->
buffer
)
return
FT_Err_Invalid_Argument
;
/* compute center of display */
center
.
x
=
display
->
bitmap
->
width
/
2
;
center
.
y
=
display
->
bitmap
->
rows
/
2
;
/* compute draw region around `center` */
draw_region
.
xMin
=
center
.
x
-
(
bitmap
->
width
*
status
.
scale
)
/
2
;
draw_region
.
xMax
=
center
.
x
+
(
bitmap
->
width
*
status
.
scale
)
/
2
;
draw_region
.
yMin
=
center
.
y
-
(
bitmap
->
rows
*
status
.
scale
)
/
2
;
draw_region
.
yMax
=
center
.
y
+
(
bitmap
->
rows
*
status
.
scale
)
/
2
;
/* add position offset so that we can move the image */
draw_region
.
xMin
+=
status
.
x_offset
;
draw_region
.
xMax
+=
status
.
x_offset
;
draw_region
.
yMin
+=
status
.
y_offset
;
draw_region
.
yMax
+=
status
.
y_offset
;
/* Sample region is the region of the bitmap that gets */
/* sampled to the display buffer. */
sample_region
.
xMin
=
0
;
sample_region
.
xMax
=
bitmap
->
width
*
status
.
scale
;
sample_region
.
yMin
=
0
;
sample_region
.
yMax
=
bitmap
->
rows
*
status
.
scale
;
/* Adjust sample region in case our draw region */
/* goes outside of the display. */
/* adjust in -y */
if
(
draw_region
.
yMin
<
0
)
{
sample_region
.
yMax
-=
draw_region
.
yMin
;
draw_region
.
yMin
=
0
;
}
/* adjust in +y */
if
(
draw_region
.
yMax
>
display
->
bitmap
->
rows
)
{
sample_region
.
yMin
+=
draw_region
.
yMax
-
display
->
bitmap
->
rows
;
draw_region
.
yMax
=
display
->
bitmap
->
rows
;
}
/* adjust in -x */
if
(
draw_region
.
xMin
<
0
)
{
sample_region
.
xMin
-=
draw_region
.
xMin
;
draw_region
.
xMin
=
0
;
}
/* adjust in +x */
if
(
draw_region
.
xMax
>
display
->
bitmap
->
width
)
{
sample_region
.
xMax
+=
draw_region
.
xMax
-
display
->
bitmap
->
width
;
draw_region
.
xMax
=
display
->
bitmap
->
width
;
}
buffer
=
(
FT_Short
*
)
bitmap
->
buffer
;
/* Finally loop over all pixels inside the draw region */
/* and copy pixels from the sample region to the draw region. */
for
(
FT_Int
j
=
draw_region
.
yMax
-
1
,
y
=
sample_region
.
yMin
;
j
>=
draw_region
.
yMin
;
j
--
,
y
++
)
{
for
(
FT_Int
i
=
draw_region
.
xMin
,
x
=
sample_region
.
xMin
;
i
<
draw_region
.
xMax
;
i
++
,
x
++
)
{
FT_UInt
display_index
=
j
*
display
->
bitmap
->
width
+
i
;
float
min_dist
;
if
(
status
.
nearest_filtering
)
{
FT_UInt
bitmap_index
=
(
y
/
status
.
scale
)
*
bitmap
->
width
+
x
/
status
.
scale
;
FT_Short
pixel_value
=
buffer
[
bitmap_index
];
/* If nearest filtering then simply take the value of the */
/* nearest sampling pixel. */
min_dist
=
(
float
)
pixel_value
/
1024
.
0
f
;
}
else
{
/* for simplicity use floats */
float
bi_x
;
float
bi_y
;
float
nbi_x
;
float
nbi_y
;
int
indc
[
4
];
/* [0,0] [0,1] [1,0] [1,1] */
float
dist
[
4
];
float
m1
,
m2
;
int
width
=
(
int
)
bitmap
->
width
;
int
rows
=
(
int
)
bitmap
->
rows
;
/* If bilinear filtering then compute the bilinear */
/* interpolation of the current draw pixel using */
/* the nearby sampling pixel values. */
/* */
/* Again the concept is taken from Wikipedia. */
/* */
/* https://en.wikipedia.org/wiki/Bilinear_interpolation */
bi_x
=
(
float
)
x
/
(
float
)
status
.
scale
;
bi_y
=
(
float
)
y
/
(
float
)
status
.
scale
;
nbi_x
=
bi_x
-
(
int
)
bi_x
;
nbi_y
=
bi_y
-
(
int
)
bi_y
;
indc
[
0
]
=
(
int
)
bi_y
*
width
+
(
int
)
bi_x
;
indc
[
1
]
=
(
(
int
)
bi_y
+
1
)
*
width
+
(
int
)
bi_x
;
indc
[
2
]
=
(
int
)
bi_y
*
width
+
(
int
)
bi_x
+
1
;
indc
[
3
]
=
(
(
int
)
bi_y
+
1
)
*
width
+
(
int
)
bi_x
+
1
;
dist
[
0
]
=
(
float
)
buffer
[
indc
[
0
]]
/
1024
.
0
f
;
if
(
indc
[
1
]
>=
width
*
rows
)
dist
[
1
]
=
-
status
.
spread
;
else
dist
[
1
]
=
(
float
)
buffer
[
indc
[
1
]]
/
1024
.
0
f
;
if
(
indc
[
2
]
>=
width
*
rows
)
dist
[
2
]
=
-
status
.
spread
;
else
dist
[
2
]
=
(
float
)
buffer
[
indc
[
2
]]
/
1024
.
0
f
;
if
(
indc
[
3
]
>=
width
*
rows
)
dist
[
3
]
=
-
status
.
spread
;
else
dist
[
3
]
=
(
float
)
buffer
[
indc
[
3
]]
/
1024
.
0
f
;
m1
=
dist
[
0
]
*
(
1
.
0
f
-
nbi_y
)
+
dist
[
1
]
*
nbi_y
;
m2
=
dist
[
2
]
*
(
1
.
0
f
-
nbi_y
)
+
dist
[
3
]
*
nbi_y
;
/* This is our final display after bilinear interpolation. */
min_dist
=
(
1
.
0
f
-
nbi_x
)
*
m1
+
nbi_x
*
m2
;
}
if
(
status
.
reconstruct
)
{
float
alpha
;
/* If we are reconstructing then discard all values outside of */
/* the range defined by `status.width` and use `status.edge' to */
/* make smooth anti-aliased edges. */
/* This is similar to an OpenGL implementation to draw SDF. */
alpha
=
1
.
0
f
-
smoothstep
(
status
.
width
,
status
.
width
+
status
.
edge
,
-
min_dist
);
alpha
*=
255
;
/* finally copy the target value to the display buffer */
display_index
*=
3
;
display
->
bitmap
->
buffer
[
display_index
+
0
]
=
(
unsigned
char
)
alpha
;
display
->
bitmap
->
buffer
[
display_index
+
1
]
=
(
unsigned
char
)
alpha
;
display
->
bitmap
->
buffer
[
display_index
+
2
]
=
(
unsigned
char
)
alpha
;
}
else
{
float
final_dist
=
min_dist
;
/* If not reconstructing then normalize the values between */
/* [0, 255] and copy to the display buffer. */
/* normalize using `status.spread` */
final_dist
=
final_dist
<
0
?
-
final_dist
:
final_dist
;
final_dist
/=
(
float
)
status
.
spread
;
/* invert the values */
final_dist
=
1
.
0
f
-
final_dist
;
final_dist
*=
255
;
/* finally copy the target value to the display buffer */
display_index
*=
3
;
display
->
bitmap
->
buffer
[
display_index
+
0
]
=
(
unsigned
char
)
final_dist
;
display
->
bitmap
->
buffer
[
display_index
+
1
]
=
(
unsigned
char
)
final_dist
;
display
->
bitmap
->
buffer
[
display_index
+
2
]
=
(
unsigned
char
)
final_dist
;
}
}
}
return
FT_Err_Ok
;
}
/* END */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment