mirror of https://github.com/adamdruppe/arsd.git
changes for terminal emulator
This commit is contained in:
parent
dbc6110d57
commit
7d16a8c8aa
55
color.d
55
color.d
|
@ -1,5 +1,7 @@
|
|||
module arsd.color;
|
||||
|
||||
@safe:
|
||||
|
||||
// importing phobos explodes the size of this code 10x, so not doing it.
|
||||
|
||||
private {
|
||||
|
@ -31,6 +33,7 @@ private {
|
|||
return accumulator + accumulator2 / count;
|
||||
}
|
||||
|
||||
@trusted
|
||||
string toInternal(T)(int a) {
|
||||
if(a == 0)
|
||||
return "0";
|
||||
|
@ -110,10 +113,16 @@ private {
|
|||
|
||||
/// Represents an RGBA color
|
||||
struct Color {
|
||||
ubyte r; /// red
|
||||
ubyte g; /// green
|
||||
ubyte b; /// blue
|
||||
ubyte a; /// alpha. 255 == opaque
|
||||
union {
|
||||
ubyte[4] components;
|
||||
|
||||
struct {
|
||||
ubyte r; /// red
|
||||
ubyte g; /// green
|
||||
ubyte b; /// blue
|
||||
ubyte a; /// alpha. 255 == opaque
|
||||
}
|
||||
}
|
||||
|
||||
// this makes sure they are in range before casting
|
||||
static Color fromIntegers(int red, int green, int blue, int alpha = 255) {
|
||||
|
@ -126,7 +135,11 @@ struct Color {
|
|||
|
||||
/// .
|
||||
this(int red, int green, int blue, int alpha = 255) {
|
||||
this.r = cast(ubyte) red;
|
||||
// workaround dmd bug 10937
|
||||
if(__ctfe)
|
||||
this.components[0] = cast(ubyte) red;
|
||||
else
|
||||
this.r = cast(ubyte) red;
|
||||
this.g = cast(ubyte) green;
|
||||
this.b = cast(ubyte) blue;
|
||||
this.a = cast(ubyte) alpha;
|
||||
|
@ -764,7 +777,7 @@ class IndexedImage : MemoryImage {
|
|||
|
||||
/// Number of colors currently in the palette (note: palette entries are not necessarily used in the image data)
|
||||
int numColors() const {
|
||||
return palette.length;
|
||||
return cast(int) palette.length;
|
||||
}
|
||||
|
||||
/// Adds an entry to the palette, returning its inded
|
||||
|
@ -790,6 +803,8 @@ class TrueColorImage : MemoryImage {
|
|||
// the union is no good because the length of the struct is wrong!
|
||||
|
||||
/// the same data as Color structs
|
||||
@trusted // the cast here is typically unsafe, but it is ok
|
||||
// here because I guarantee the layout, note the static assert below
|
||||
@property inout(Color)[] colors() inout {
|
||||
return cast(inout(Color)[]) bytes;
|
||||
}
|
||||
|
@ -935,7 +950,7 @@ ubyte findNearestColor(in Color[] palette, in Color pixel) {
|
|||
int dist = dr*dr + dg*dg + db*db;
|
||||
|
||||
if(dist < bestDistance) {
|
||||
best = pe;
|
||||
best = cast(int) pe;
|
||||
bestDistance = dist;
|
||||
}
|
||||
}
|
||||
|
@ -1007,12 +1022,18 @@ img = imageFromPng(readPng(range.range)).getAsTrueColorImage;
|
|||
/+
|
||||
/// If the background is transparent, it simply erases the alpha channel.
|
||||
void removeTransparency(IndexedImage img, Color background)
|
||||
|
||||
Color alphaBlend(Color a, Color b) {
|
||||
|
||||
}
|
||||
+/
|
||||
|
||||
Color alphaBlend(Color foreground, Color background) {
|
||||
if(foreground.a != 255)
|
||||
foreach(idx, ref part; foreground.components) {
|
||||
part = cast(ubyte) (part * foreground.a / 255 +
|
||||
background.components[idx] * (255 - foreground.a) / 255);
|
||||
}
|
||||
|
||||
return foreground;
|
||||
}
|
||||
|
||||
/*
|
||||
/// Reduces the number of colors in a palette.
|
||||
void reducePaletteSize(IndexedImage img, int maxColors = 16) {
|
||||
|
@ -1065,3 +1086,15 @@ void floydSteinbergDither(IndexedImage img, in TrueColorImage original) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// these are just really useful in a lot of places where the color/image functions are used,
|
||||
// so I want them available with Color
|
||||
struct Point {
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
|
||||
struct Size {
|
||||
int width;
|
||||
int height;
|
||||
}
|
||||
|
|
19
eventloop.d
19
eventloop.d
|
@ -474,8 +474,25 @@ version(linux) {
|
|||
|
||||
auto nfds = epoll_wait(epoll, events.ptr, events.length, lowestWait);
|
||||
moreEvents:
|
||||
if(nfds == -1)
|
||||
if(nfds == -1) {
|
||||
if(errno == EINTR) {
|
||||
// if we're interrupted, we can just advance the timers (we know none triggered since the timeout didn't go off) and try again
|
||||
if(timers.length) {
|
||||
long prev = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
gettimeofday(&tv, null);
|
||||
long diff = tv.tv_sec * 1000 + tv.tv_usec / 1000 - prev;
|
||||
|
||||
for(size_t idx = 0; idx < timers.length; idx++) {
|
||||
auto timer = timers[idx];
|
||||
timer.timeoutRemaining -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new Exception("epoll_wait");
|
||||
}
|
||||
|
||||
foreach(n; 0 .. nfds) {
|
||||
auto fd = events[n].data.fd;
|
||||
|
|
|
@ -18,11 +18,43 @@ struct TtfFont {
|
|||
throw new Exception("load font problem");
|
||||
}
|
||||
|
||||
ubyte[] renderCharacter(dchar c, int size, out int width, out int height) {
|
||||
auto ptr = stbtt_GetCodepointBitmap(&font, 0.0,stbtt_ScaleForPixelHeight(&font, size), c, &width, &height, null,null);
|
||||
ubyte[] renderCharacter(dchar c, int size, out int width, out int height, float shift_x = 0.0, float shift_y = 0.0) {
|
||||
auto ptr = stbtt_GetCodepointBitmapSubpixel(&font, 0.0,stbtt_ScaleForPixelHeight(&font, size),
|
||||
shift_x, shift_y, c, &width, &height, null,null);
|
||||
return ptr[0 .. width * height];
|
||||
}
|
||||
|
||||
void getStringSize(string s, int size, out int width, out int height) {
|
||||
float xpos=0;
|
||||
|
||||
auto scale = stbtt_ScaleForPixelHeight(&font, size);
|
||||
int ascent, descent, line_gap;
|
||||
stbtt_GetFontVMetrics(&font, &ascent,&descent,&line_gap);
|
||||
auto baseline = cast(int) (ascent*scale);
|
||||
|
||||
import std.math;
|
||||
|
||||
int maxWidth;
|
||||
|
||||
foreach(i, dchar ch; s) {
|
||||
int advance,lsb;
|
||||
auto x_shift = xpos - floor(xpos);
|
||||
stbtt_GetCodepointHMetrics(&font, ch, &advance, &lsb);
|
||||
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBoxSubpixel(&font, ch, scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
|
||||
|
||||
maxWidth = cast(int)(xpos + x1);
|
||||
|
||||
xpos += (advance * scale);
|
||||
if (i + 1 < s.length)
|
||||
xpos += scale*stbtt_GetCodepointKernAdvance(&font, ch,s[i+1]);
|
||||
}
|
||||
|
||||
width = maxWidth;
|
||||
height = size;
|
||||
}
|
||||
|
||||
ubyte[] renderString(string s, int size, out int width, out int height) {
|
||||
float xpos=0;
|
||||
|
||||
|
@ -33,16 +65,17 @@ struct TtfFont {
|
|||
|
||||
import std.math;
|
||||
|
||||
auto swidth = s.length * size;
|
||||
int sheight = size + baseline + 32;
|
||||
int swidth;
|
||||
int sheight;
|
||||
getStringSize(s, size, swidth, sheight);
|
||||
auto screen = new ubyte[](swidth * sheight);
|
||||
|
||||
foreach(i, ch; s) {
|
||||
foreach(i, dchar ch; s) {
|
||||
int advance,lsb;
|
||||
auto x_shift = xpos - floor(xpos);
|
||||
stbtt_GetCodepointHMetrics(&font, ch, &advance, &lsb);
|
||||
int cw, cheight;
|
||||
auto c = renderCharacter(ch, size, cw, cheight);
|
||||
auto c = renderCharacter(ch, size, cw, cheight, x_shift, 0.0);
|
||||
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBoxSubpixel(&font, ch, scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
|
||||
|
@ -56,10 +89,13 @@ struct TtfFont {
|
|||
y++;
|
||||
x = cast(int) xpos + x0;
|
||||
}
|
||||
int val = (pixel * (255 - screen[swidth * y + x]) / 255);
|
||||
auto offset = swidth * y + x;
|
||||
if(offset >= screen.length)
|
||||
break;
|
||||
int val = (cast(int) pixel * (255 - screen[offset]) / 255);
|
||||
if(val > 255)
|
||||
val = 255;
|
||||
screen[swidth * y + x] += cast(ubyte)(val);
|
||||
screen[offset] += cast(ubyte)(val);
|
||||
x++;
|
||||
cx++;
|
||||
}
|
||||
|
@ -85,6 +121,7 @@ struct TtfFont {
|
|||
|
||||
|
||||
// test program
|
||||
/+
|
||||
int main(string[] args)
|
||||
{
|
||||
import std.conv;
|
||||
|
@ -100,12 +137,12 @@ import std.file;
|
|||
|
||||
for (int j=0; j < h; ++j) {
|
||||
for (int i=0; i < w; ++i)
|
||||
img.putPixel(i, j, Color(0, bitmap[j*w+i], 0));
|
||||
img.putPixel(i, j, Color(0, (bitmap[j*w+i] > 128) ? 255 : 0, 0));
|
||||
}
|
||||
img.displayImage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue