13 public enum GradientDirection { vertical, horizontal };
15 public void PaletteGradient(ColorAlpha * palette, int numColors, ColorKey * keys, int numKeys, float smoothness)
17 ColorKey * key = keys, * nextKey = keys;
18 int keyNum = 0, nextKeyNum = 0;
19 float inc = 1.0f/(numColors-1);
25 for(c = start = 0; c<numColors; c++)
27 ColorAlpha newColor = 0;
29 while(nextKey && percent > nextKey->percent)
31 key = nextKey; keyNum = nextKeyNum;
33 if(keyNum < numKeys - 1)
36 nextKeyNum = keyNum + 1;
42 if(nextKey && nextKey->percent != key->percent)
44 float scale = ease((percent - key->percent) / (nextKey->percent - key->percent),
45 smoothness, smoothness);
46 int ca = key->color.a;
47 int cr = key->color.color.r;
48 int cg = key->color.color.g;
49 int cb = key->color.color.b;
50 int na = nextKey->color.color.r;
51 int nr = nextKey->color.color.r;
52 int ng = nextKey->color.color.g;
53 int nb = nextKey->color.color.b;
54 int a = (int)(ca + (na - ca) * scale);
55 int r = (int)(cr + (nr - cr) * scale);
56 int g = (int)(cg + (ng - cg) * scale);
57 int b = (int)(cb + (nb - cb) * scale);
59 a = Max(Min(r, 255),0);
60 r = Max(Min(r, 255),0);
61 g = Max(Min(g, 255),0);
62 b = Max(Min(b, 255),0);
64 newColor = ColorAlpha { (byte)a, { (byte)r, (byte)g, (byte)b } };
67 newColor = key ? key->color : 0;
69 if(c == 0 || newColor != color)
74 for(i = start; i<c; i++)
86 for(i = start; i<c; i++)
91 float ease(float t, float a, float b)
96 if (s == 0.0f) return t;
103 if (t < a) return (k/a)*t*t;
104 if (t < 1.0f - b) return k*(2.0f * t - a);
106 return 1.0f - (k/b)*t*t;
109 public enum AlphaWriteMode
121 Box box, unclippedBox;
125 subclass(DisplayDriver) driver;
126 DisplaySystem displaySystem;
132 ColorAlpha foreground, background;
134 AlphaWriteMode alphaWrite;
138 ColorAlpha outlineColor;
145 outlineColor = black;
150 driver.ReleaseSurface(display, this);
154 property AlphaWriteMode alphaWrite
156 set { alphaWrite = value; }
157 get { return alphaWrite; }
161 set { blend = value; }
162 get { return blend; }
164 property Bitmap bitmap
168 return ((LFBSurface)driverData).bitmap;
171 property ColorAlpha outlineColor
173 set { outlineColor = value; }
174 get { return outlineColor; }
177 ColorAlpha GetPixel(int x, int y)
179 return driver.GetPixel(display, this, x,y);
182 void PutPixel(int x, int y)
184 driver.PutPixel(display, this, x,y);
187 void DrawLine(int x1, int y1, int x2, int y2)
189 driver.DrawLine(display, this, x1,y1,x2,y2);
192 void VLine(int y1, int y2, int x)
194 driver.DrawLine(display, this, x,y1,x,y2);
197 void HLine(int x1, int x2, int y)
199 driver.DrawLine(display, this, x1,y,x2,y);
202 void Rectangle(int x1, int y1, int x2, int y2)
204 driver.Rectangle(display, this, x1,y1,x2,y2);
207 void Area(int x1, int y1, int x2, int y2)
209 driver.Area(display, this, x1,y1,x2,y2);
212 void Clear(ClearType type)
214 driver.Clear(display, this, type);
217 void Blit(Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
219 if(src.driver == driver)
220 driver.Blit(display, this, src, dx,dy, sx, sy,w,h);
221 else if(!src.driver || src.driver == class(LFBDisplayDriver))
222 driver.BlitDI(display, this, src, dx,dy, sx, sy,w,h);
225 void Stretch(Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
227 if(src.driver == driver)
228 driver.Stretch(display, this, src, dx,dy, sx,sy, w,h, sw, sh);
229 else if(!src.driver || src.driver == class(LFBDisplayDriver))
230 driver.StretchDI(display, this, src, dx,dy, sx,sy, w,h, sw, sh);
233 void Filter(Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
235 if(src.driver == driver)
236 driver.Filter(display, this, src, dx,dy, sx,sy, w,h, sw, sh);
237 else if(!src.driver || src.driver == class(LFBDisplayDriver))
238 driver.FilterDI(display, this, src, dx,dy, sx,sy, w,h, sw, sh);
241 void Tile(Bitmap src, int dx, int dy, int w, int h)
243 if(src && src.width && src.height)
246 for(x = 0,sx = dx; x < w; x += src.width, sx += src.width)
247 for(y = 0, sy = dy; y < h; y += src.height,sy += src.height)
248 Blit(src, sx, sy, 0,0, Min(src.width, w - x), Min(src.height, h - y));
252 void HTile(Bitmap src, int dx, int dy, int w, int h)
254 if(src && src.width && src.height)
257 for(x = 0, sx = dx; x < w; x += src.width, sx += src.width)
258 Stretch(src, sx, dy, 0, 0, Min(src.width, w - x), h, Min(src.width, w - x), src.height);
262 void VTile(Bitmap src, int dx, int dy, int w, int h)
264 if(src && src.width && src.height)
267 for(y = 0, sy = dy; y < h; y += src.height, sy += src.height)
268 Stretch(src, dx, sy, 0,0, w, Min(src.height, h - y), src.width, Min(src.height, h - y));
272 void FilterHTile(Bitmap src, int dx, int dy, int w, int h)
274 if(src && src.width && src.height)
277 for(x = 0, sx = dx; x < w; x += src.width, sx += src.width)
278 Filter(src, sx, dy, 0, 0, Min(src.width, w - x), h, Min(src.width, w - x), src.height);
282 void FilterVTile(Bitmap src, int dx, int dy, int w, int h)
284 if(src && src.width && src.height)
287 for(y = 0, sy = dy; y < h; y += src.height, sy += src.height)
288 Filter(src, dx, sy, 0,0, w, Min(src.height, h - y), src.width, Min(src.height, h - y));
292 void WriteText(int x, int y, const char * text, int len)
295 driver.WriteText(display, this, x,y, text, len, 0, null); //, null);
298 void WriteText2(int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
301 driver.WriteText(display, this, x,y, text, len, prevGlyph, rPrevGlyph);
304 void TextExtent(const char * text, int len, int * width, int * height)
307 driver.TextExtent(display, this, text, len, width, height, 0, null, &advance);
312 void TextExtent2(const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * overHang)
314 driver.TextExtent(display, this, text, len, width, height, prevGlyph, rPrevGlyph, overHang);
317 void WriteTextf(int x, int y, const char * format, ...)
321 char text[MAX_F_STRING];
323 va_start(args, format);
324 vsnprintf(text, sizeof(text), format, args);
325 text[sizeof(text)-1] = 0;
327 driver.WriteText(display, this, x,y, text, strlen(text), 0, null);
332 void CenterTextf(int x, int y, const char * format, ...)
336 char text[MAX_F_STRING];
340 va_start(args, format);
341 vsnprintf(text, sizeof(text), format, args);
342 text[sizeof(text)-1] = 0;
345 driver.TextExtent(display, this, text, len, &w, &h, 0, null, &oh);
347 driver.WriteText(display, this, x - w/2, y, text, len, 0, null);
352 void WriteTextDots(Alignment alignment, int x, int y, int width, const char * text, int len)
356 TextExtent(text, len, &w, &h);
359 if(alignment == right)
361 else if(alignment == center)
362 x += (width - w) / 2;
363 WriteText(x, y, text, len);
374 TextExtent(".", 1, &dw, &dh);
376 #define UTF8_NUM_BYTES(x) (__extension__({ byte b = x; (b & 0x80 && b & 0x40) ? ((b & 0x20) ? ((b & 0x10) ? 4 : 3) : 2) : 1; }))
377 for(c = 0; (ch = text[c]); c += nb)
379 nb = UTF8_NUM_BYTES(ch);
380 TextExtent(text+c, nb, &w, &h);
386 WriteText(x, y, text, c);
387 //TextExtent(text, c, &totalW, &h);
389 WriteText(x, y, "...", 3);
393 void WriteTextDotsf(Alignment alignment, int x, int y, int width, const char * format, ...)
397 char text[MAX_F_STRING];
399 va_start(args, format);
400 vsnprintf(text, sizeof(text), format, args);
401 text[sizeof(text)-1] = 0;
402 WriteTextDots(alignment, x,y, width, text, strlen(text));
407 void Bevel(bool inner, int x, int y, int w, int h)
409 ColorAlpha foreground = this.foreground;
411 SetForeground(inner ? Color { 128,128,128 } : formColor);
412 HLine(x, x+w - 2, y);
413 VLine(y+1, y+h - 2, x);
415 SetForeground(inner ? Color { 64,64,64 } : white);
416 HLine(x+1, x+w-3, y+1);
417 VLine(y+2, y+h-3, x+1);
419 SetForeground(inner ? formColor : Color { 128,128,128 } );
420 HLine(x+1, x+w-2, y + h -2);
421 VLine(y+1, y+h-3, x + w - 2);
423 SetForeground(inner ? white : Color { 64,64,64 });
424 HLine(x, x+w-1, y + h - 1);
425 VLine(y, y+h-2, x + w - 1);
427 SetForeground(foreground);
430 void ThinBevel(bool inner, int x, int y, int w, int h)
432 SetForeground(inner ? Color { 128,128,128 } : white);
433 HLine(x, x+w - 2, y);
434 VLine(y+1, y+h - 2, x);
435 SetForeground(inner ? white : Color { 128,128,128 });
436 HLine(x, x+w-1, y + h - 1);
437 VLine(y, y+h-2, x + w - 1);
440 void Gradient(ColorKey * keys, int numKeys, float smoothness, GradientDirection direction, int x1, int y1, int x2, int y2)
442 if(x2 >= box.left && x1 <= box.right && y2 >= box.top && y1 <= box.bottom)
444 ColorKey * key = keys, * nextKey = keys;
445 int keyNum = 0, nextKeyNum = 0;
446 int height = (direction == horizontal) ? ((x2 - x1) + 1) : ((y2 - y1) + 1);
447 float inc = 1.0f/(height-1);
450 ColorAlpha color = 0;
451 int firstPixel = (direction == horizontal) ? x1 : y1;
452 int lastPixel = (direction == horizontal) ? x2 : y2;
453 int boxLeft = (direction == horizontal) ? box.left : box.top;
454 int boxRight = (direction == horizontal) ? box.right : box.bottom;
458 if(boxLeft > firstPixel)
460 percent = (boxLeft - firstPixel) * inc;
461 firstPixel = boxLeft;
463 if(boxRight < lastPixel)
464 lastPixel = boxRight;
466 for(c = start = firstPixel; c<=lastPixel; c++)
470 while(nextKey && percent > nextKey->percent)
472 key = nextKey; keyNum = nextKeyNum;
474 if(keyNum < numKeys - 1)
477 nextKeyNum = keyNum + 1;
483 if(nextKey && nextKey->percent != key->percent)
485 float scale = ease((percent - key->percent) / (nextKey->percent - key->percent),
486 smoothness, smoothness);
487 int cr = key->color.color.r;
488 int cg = key->color.color.g;
489 int cb = key->color.color.b;
490 int nr = nextKey->color.color.r;
491 int ng = nextKey->color.color.g;
492 int nb = nextKey->color.color.b;
493 int r = (int)(cr + (nr - cr) * scale);
494 int g = (int)(cg + (ng - cg) * scale);
495 int b = (int)(cb + (nb - cb) * scale);
497 r = Max(Min(r, 255),0);
498 g = Max(Min(g, 255),0);
499 b = Max(Min(b, 255),0);
501 newColor = Color { (byte)r, (byte)g, (byte)b };
504 newColor = key ? key->color : 0;
506 if(c == firstPixel || newColor != color)
510 SetBackground(color);
512 if(direction == horizontal)
513 Area(start,y1,c-1,y2);
515 Area(x1, start,x2, c-1);
523 SetBackground(color);
524 if(direction == horizontal)
525 Area(start,y1,c-1,y2);
527 Area(x1, start,x2, c-1);
532 property ColorAlpha foreground
537 driver.SetForeground(display, this, value);
539 get { return foreground; }
542 property ColorAlpha background
547 driver.SetBackground(display, this, value);
549 get { return background; }
552 property ColorAlpha blitTint
557 driver.SetBlitTint(display, this, value);
559 get { return blitTint; }
562 property uint lineStipple
566 driver.LineStipple(display, this, value);
572 get { value = { width, height }; }
580 if(display && display.flags.text)
582 value.left *= textCellW;
583 value.top *= textCellH;
584 value.right *= textCellW;
585 value.bottom *= textCellH;
590 property Display display
592 get { return display; }
599 if(value && font != value)
601 driver.TextFont(display, this, value);
609 property bool textOpacity
614 driver.TextOpacity(display, this, value);
617 get { return textOpacity; }
620 property byte drawingChar
622 set { driver.DrawingChar(display, this, value); }
625 property Box clipping
627 set { driver.Clip(display, this, value); }
630 // TODO: Make these functions obsolete
631 void SetForeground(ColorAlpha value)
634 driver.SetForeground(display, this, value);
637 void SetBackground(ColorAlpha value)
640 driver.SetBackground(display, this, value);
643 Color GetForeground(void)
648 Color GetBackground(void)
653 void LineStipple(uint value)
655 driver.LineStipple(display, this, value);
658 void GetSize(int * w, int * h)
664 void GetBox(Box value)
667 if(display.flags.text)
669 box.left *= textCellW;
670 box.top *= textCellH;
671 box.right *= textCellW;
672 box.bottom *= textCellH;
676 Display GetDisplay(void)
681 void TextFont(Font value)
683 if(value && font != value)
685 driver.TextFont(display, this, value);
695 bool GetTextOpacity(void)
700 void TextOpacity(bool value)
703 driver.TextOpacity(display, this, value);
706 void DrawingChar(unsigned char value)
708 driver.DrawingChar(display, this, value);
713 driver.Clip(display, this, box);