mirror of https://github.com/buggins/dlangui.git
Text drawing is working. Refcounted fonts working ok
This commit is contained in:
parent
b8f8f8f64b
commit
e44c7fd3fd
|
@ -41,8 +41,13 @@ public struct Rect {
|
|||
public class RefCountedObject {
|
||||
protected int _refCount;
|
||||
public @property int refCount() { return _refCount; }
|
||||
public void addRef() { _refCount++; }
|
||||
public void releaseRef() { if (--_refCount == 0) destroy(this); }
|
||||
public void addRef() {
|
||||
_refCount++;
|
||||
}
|
||||
public void releaseRef() {
|
||||
if (--_refCount == 0)
|
||||
destroy(this);
|
||||
}
|
||||
public ~this() {}
|
||||
}
|
||||
|
||||
|
@ -56,23 +61,39 @@ public struct Ref(T) { // if (T is RefCountedObject)
|
|||
if (_data !is null)
|
||||
_data.addRef();
|
||||
}
|
||||
public void opAssign(Ref!T data) {
|
||||
public this(this) {
|
||||
if (_data !is null)
|
||||
_data.addRef();
|
||||
}
|
||||
public ref Ref opAssign(ref Ref data) {
|
||||
if (data._data == _data)
|
||||
return;
|
||||
return this;
|
||||
if (_data !is null)
|
||||
_data.releaseRef();
|
||||
_data = data._data;
|
||||
if (_data !is null)
|
||||
_data.addRef();
|
||||
return this;
|
||||
}
|
||||
public void opAssign(T data) {
|
||||
public ref Ref opAssign(Ref data) {
|
||||
if (data._data == _data)
|
||||
return this;
|
||||
if (_data !is null)
|
||||
_data.releaseRef();
|
||||
_data = data._data;
|
||||
if (_data !is null)
|
||||
_data.addRef();
|
||||
return this;
|
||||
}
|
||||
public ref Ref opAssign(T data) {
|
||||
if (data == _data)
|
||||
return;
|
||||
return this;
|
||||
if (_data !is null)
|
||||
_data.releaseRef();
|
||||
_data = data;
|
||||
if (_data !is null)
|
||||
_data.addRef();
|
||||
return this;
|
||||
}
|
||||
public void clear() {
|
||||
if (_data !is null) {
|
||||
|
|
|
@ -47,6 +47,7 @@ class DrawBuf : RefCountedObject {
|
|||
fillRect(Rect(left, top, right, bottom), color);
|
||||
}
|
||||
abstract public void fillRect(Rect rc, uint color);
|
||||
abstract public void drawGlyph(int x, int y, ubyte[] src, int srcdx, int srcdy, uint color);
|
||||
public void clear() {}
|
||||
public ~this() { clear(); }
|
||||
}
|
||||
|
@ -59,6 +60,35 @@ class ColorDrawBufBase : DrawBuf {
|
|||
public override void fillRect(int left, int top, int right, int bottom, uint color) {
|
||||
fillRect(Rect(left, top, right, bottom), color);
|
||||
}
|
||||
public override void drawGlyph(int x, int y, ubyte[] src, int srcdx, int srcdy, uint color) {
|
||||
bool clipping = !_clipRect.empty();
|
||||
for (int yy = 0; yy < srcdy; yy++) {
|
||||
int liney = y + yy;
|
||||
if (clipping && (liney < _clipRect.top || liney >= _clipRect.bottom))
|
||||
continue;
|
||||
if (liney < 0 || liney >= _dy)
|
||||
continue;
|
||||
uint * row = scanLine(liney);
|
||||
ubyte * srcrow = src.ptr + yy * srcdx;
|
||||
for (int xx = 0; xx < srcdx; xx++) {
|
||||
int colx = xx + x;
|
||||
if (clipping && (colx < _clipRect.left || colx >= _clipRect.right))
|
||||
continue;
|
||||
if (colx < 0 || colx >= _dx)
|
||||
continue;
|
||||
uint alpha1 = srcrow[xx] ^ 255;
|
||||
uint alpha2 = (color >> 24);
|
||||
uint alpha = ((((alpha1 ^ 255) * (alpha2 ^ 255)) >> 8) ^ 255) & 255;
|
||||
uint pixel = row[colx];
|
||||
if (!alpha)
|
||||
row[colx] = pixel;
|
||||
else if (alpha < 255) {
|
||||
// apply blending
|
||||
row[colx] = blendARGB(pixel, color, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void fillRect(Rect rc, uint color) {
|
||||
if (applyClipping(rc)) {
|
||||
for (int y = rc.top; y < rc.bottom; y++) {
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
module dlangui.graphics.fonts;
|
||||
import dlangui.core.types;
|
||||
public import dlangui.graphics.drawbuf;
|
||||
public import dlangui.core.types;
|
||||
public import dlangui.core.logger;
|
||||
import std.algorithm;
|
||||
|
||||
public enum FontFamily : int {
|
||||
SansSerif,
|
||||
|
@ -91,12 +94,53 @@ public class Font : RefCountedObject {
|
|||
abstract public @property bool isNull();
|
||||
// measure text string, return accumulated widths[] (distance to end of n-th character), returns number of measured chars.
|
||||
abstract public int measureText(const dchar[] text, ref int[] widths, int maxWidth);
|
||||
// draw text string to buffer
|
||||
abstract public void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color);
|
||||
abstract public Glyph * getCharGlyph(dchar ch);
|
||||
public void clear() {}
|
||||
public ~this() { clear(); }
|
||||
}
|
||||
alias FontRef = Ref!Font;
|
||||
|
||||
public struct FontList {
|
||||
FontRef[] _list;
|
||||
uint _len;
|
||||
public ~this() {
|
||||
for (uint i = 0; i < _len; i++) {
|
||||
_list[i].clear();
|
||||
}
|
||||
}
|
||||
// returns item by index
|
||||
public ref FontRef get(int index) {
|
||||
return _list[index];
|
||||
}
|
||||
// returns index of found item, -1 if not found
|
||||
public int find(int size, int weight, bool italic, FontFamily family, string face) {
|
||||
for (int i = 0; i < _list.length; i++) {
|
||||
Font item = _list[i].get;
|
||||
if (item.family != family)
|
||||
continue;
|
||||
if (item.size != size)
|
||||
continue;
|
||||
if (item.italic != italic || item.weight != weight)
|
||||
continue;
|
||||
if (!equal(item.face, face))
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
public ref FontRef add(Font item) {
|
||||
Log.d("FontList.add() enter");
|
||||
if (_len >= _list.length) {
|
||||
_list.length = _len < 16 ? 16 : _list.length * 2;
|
||||
}
|
||||
_list[_len++] = item;
|
||||
Log.d("FontList.add() exit");
|
||||
return _list[_len - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public class FontManager {
|
||||
static __gshared FontManager _instance;
|
||||
public static @property void instance(FontManager manager) {
|
||||
|
@ -105,6 +149,6 @@ public class FontManager {
|
|||
public static @property FontManager instance() {
|
||||
return _instance;
|
||||
}
|
||||
abstract public FontRef getFont(int size, int weight, bool italic, FontFamily family, string face);
|
||||
abstract public ref FontRef getFont(int size, int weight, bool italic, FontFamily family, string face);
|
||||
public ~this() {}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@ class Win32Font : Font {
|
|||
|
||||
public this() {
|
||||
}
|
||||
public ~this() {
|
||||
Log.d("Deleting font");
|
||||
clear();
|
||||
}
|
||||
public override void clear() {
|
||||
if (_hfont !is null)
|
||||
{
|
||||
|
@ -174,6 +178,26 @@ class Win32Font : Font {
|
|||
return _glyphCache.put(cast(ushort)glyphIndex, &g);
|
||||
}
|
||||
|
||||
// draw text string to buffer
|
||||
public override void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color) {
|
||||
int[] widths;
|
||||
int charsMeasured = measureText(text, widths, 3000);
|
||||
for (int i = 0; i < charsMeasured; i++) {
|
||||
int xx = (i > 0) ? widths[i - 1] : 0;
|
||||
Glyph * glyph = getCharGlyph(text[i]);
|
||||
if (glyph is null)
|
||||
continue;
|
||||
if ( glyph.blackBoxX && glyph.blackBoxY ) {
|
||||
buf.drawGlyph( x + xx + glyph.originX,
|
||||
y + _baseline - glyph.originY,
|
||||
glyph.glyph,
|
||||
glyph.blackBoxX,
|
||||
glyph.blackBoxY,
|
||||
color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override int measureText(const dchar[] text, ref int[] widths, int maxWidth) {
|
||||
if (_hfont is null || _drawbuf is null || text.length == 0)
|
||||
return 0;
|
||||
|
@ -251,7 +275,7 @@ class Win32Font : Font {
|
|||
|
||||
|
||||
class Win32FontManager : FontManager {
|
||||
FontRef[] _activeFonts;
|
||||
FontList _activeFonts;
|
||||
FontDef[] _fontFaces;
|
||||
FontDef*[string] _faceByName;
|
||||
public this() {
|
||||
|
@ -277,32 +301,23 @@ class Win32FontManager : FontManager {
|
|||
Log.i("Found ", _fontFaces.length, " font faces");
|
||||
return res!=0;
|
||||
}
|
||||
public override FontRef getFont(int size, int weight, bool italic, FontFamily family, string face) {
|
||||
FontRef res;
|
||||
FontRef _emptyFontRef;
|
||||
public override ref FontRef getFont(int size, int weight, bool italic, FontFamily family, string face) {
|
||||
Log.i("getFont()");
|
||||
FontDef * def = findFace(family, face);
|
||||
if (def !is null) {
|
||||
for (int i = 0; i < _activeFonts.length; i++) {
|
||||
Font item = _activeFonts[i].get;
|
||||
if (item.family != def.family)
|
||||
continue;
|
||||
if (item.size != size)
|
||||
continue;
|
||||
if (item.italic != italic || item.weight != weight)
|
||||
continue;
|
||||
if (!equal(item.face, def.face))
|
||||
continue;
|
||||
res = _activeFonts[i];
|
||||
break;
|
||||
}
|
||||
if (res.isNull) {
|
||||
Win32Font item = new Win32Font();
|
||||
if (!item.create(def, size, weight, italic))
|
||||
return res;
|
||||
res = item;
|
||||
_activeFonts ~= res;
|
||||
}
|
||||
int index = _activeFonts.find(size, weight, italic, def.family, def.face);
|
||||
if (index >= 0)
|
||||
return _activeFonts.get(index);
|
||||
Log.d("Creating new font");
|
||||
Win32Font item = new Win32Font();
|
||||
if (!item.create(def, size, weight, italic))
|
||||
return _emptyFontRef;
|
||||
Log.d("Adding to list of active fonts");
|
||||
return _activeFonts.add(item);
|
||||
} else {
|
||||
return _emptyFontRef;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
FontDef * findFace(FontFamily family) {
|
||||
FontDef * res = null;
|
||||
|
|
25
winmain.d
25
winmain.d
|
@ -6,19 +6,42 @@ import dlangui.core.logger;
|
|||
import dlangui.graphics.fonts;
|
||||
import std.stdio;
|
||||
|
||||
class TestWidget : Widget {
|
||||
public override void onDraw(DrawBuf buf) {
|
||||
super.onDraw(buf);
|
||||
FontRef font1;
|
||||
FontRef font2;
|
||||
Log.d("Testing opAssign");
|
||||
font1 = font2;
|
||||
Log.d("Testing copy constructor");
|
||||
FontRef font3 = font2;
|
||||
Log.d("On draw: getting font");
|
||||
FontRef font = FontManager.instance.getFont(32, 400, false, FontFamily.SansSerif, "Arial");
|
||||
Log.d("Got font, drawing text");
|
||||
font.drawText(buf, _pos.left + 5, _pos.top + 5, "Text"d, 0x0000FF);
|
||||
Log.d("Text is drawn successfully");
|
||||
}
|
||||
}
|
||||
|
||||
extern (C) int UIAppMain() {
|
||||
Log.d("Some debug message");
|
||||
Log.e("Sample error #", 22);
|
||||
|
||||
Window window = Platform.instance().createWindow("My Window", null);
|
||||
Widget myWidget = new Widget();
|
||||
Widget myWidget = new TestWidget();
|
||||
window.mainWidget = myWidget;
|
||||
window.show();
|
||||
window.windowCaption = "New Window Caption";
|
||||
|
||||
|
||||
|
||||
Log.d("Before getFont");
|
||||
FontRef font = FontManager.instance.getFont(32, 400, false, FontFamily.SansSerif, "Arial");
|
||||
Log.d("After getFont");
|
||||
assert(!font.isNull);
|
||||
int[] widths;
|
||||
dchar[] text = cast(dchar[])"Test string"d;
|
||||
Log.d("Calling measureText");
|
||||
int charsMeasured = font.measureText(text, widths, 1000);
|
||||
assert(charsMeasured > 0);
|
||||
int w = widths[charsMeasured - 1];
|
||||
|
|
Loading…
Reference in New Issue