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 {
|
public class RefCountedObject {
|
||||||
protected int _refCount;
|
protected int _refCount;
|
||||||
public @property int refCount() { return _refCount; }
|
public @property int refCount() { return _refCount; }
|
||||||
public void addRef() { _refCount++; }
|
public void addRef() {
|
||||||
public void releaseRef() { if (--_refCount == 0) destroy(this); }
|
_refCount++;
|
||||||
|
}
|
||||||
|
public void releaseRef() {
|
||||||
|
if (--_refCount == 0)
|
||||||
|
destroy(this);
|
||||||
|
}
|
||||||
public ~this() {}
|
public ~this() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,23 +61,39 @@ public struct Ref(T) { // if (T is RefCountedObject)
|
||||||
if (_data !is null)
|
if (_data !is null)
|
||||||
_data.addRef();
|
_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)
|
if (data._data == _data)
|
||||||
return;
|
return this;
|
||||||
if (_data !is null)
|
if (_data !is null)
|
||||||
_data.releaseRef();
|
_data.releaseRef();
|
||||||
_data = data._data;
|
_data = data._data;
|
||||||
if (_data !is null)
|
if (_data !is null)
|
||||||
_data.addRef();
|
_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)
|
if (data == _data)
|
||||||
return;
|
return this;
|
||||||
if (_data !is null)
|
if (_data !is null)
|
||||||
_data.releaseRef();
|
_data.releaseRef();
|
||||||
_data = data;
|
_data = data;
|
||||||
if (_data !is null)
|
if (_data !is null)
|
||||||
_data.addRef();
|
_data.addRef();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
public void clear() {
|
public void clear() {
|
||||||
if (_data !is null) {
|
if (_data !is null) {
|
||||||
|
|
|
@ -47,6 +47,7 @@ class DrawBuf : RefCountedObject {
|
||||||
fillRect(Rect(left, top, right, bottom), color);
|
fillRect(Rect(left, top, right, bottom), color);
|
||||||
}
|
}
|
||||||
abstract public void fillRect(Rect rc, uint 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 void clear() {}
|
||||||
public ~this() { 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) {
|
public override void fillRect(int left, int top, int right, int bottom, uint color) {
|
||||||
fillRect(Rect(left, top, right, bottom), 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) {
|
public override void fillRect(Rect rc, uint color) {
|
||||||
if (applyClipping(rc)) {
|
if (applyClipping(rc)) {
|
||||||
for (int y = rc.top; y < rc.bottom; y++) {
|
for (int y = rc.top; y < rc.bottom; y++) {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
module dlangui.graphics.fonts;
|
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 {
|
public enum FontFamily : int {
|
||||||
SansSerif,
|
SansSerif,
|
||||||
|
@ -91,12 +94,53 @@ public class Font : RefCountedObject {
|
||||||
abstract public @property bool isNull();
|
abstract public @property bool isNull();
|
||||||
// measure text string, return accumulated widths[] (distance to end of n-th character), returns number of measured chars.
|
// 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);
|
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);
|
abstract public Glyph * getCharGlyph(dchar ch);
|
||||||
public void clear() {}
|
public void clear() {}
|
||||||
public ~this() { clear(); }
|
public ~this() { clear(); }
|
||||||
}
|
}
|
||||||
alias FontRef = Ref!Font;
|
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 {
|
public class FontManager {
|
||||||
static __gshared FontManager _instance;
|
static __gshared FontManager _instance;
|
||||||
public static @property void instance(FontManager manager) {
|
public static @property void instance(FontManager manager) {
|
||||||
|
@ -105,6 +149,6 @@ public class FontManager {
|
||||||
public static @property FontManager instance() {
|
public static @property FontManager instance() {
|
||||||
return _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() {}
|
public ~this() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,10 @@ class Win32Font : Font {
|
||||||
|
|
||||||
public this() {
|
public this() {
|
||||||
}
|
}
|
||||||
|
public ~this() {
|
||||||
|
Log.d("Deleting font");
|
||||||
|
clear();
|
||||||
|
}
|
||||||
public override void clear() {
|
public override void clear() {
|
||||||
if (_hfont !is null)
|
if (_hfont !is null)
|
||||||
{
|
{
|
||||||
|
@ -174,6 +178,26 @@ class Win32Font : Font {
|
||||||
return _glyphCache.put(cast(ushort)glyphIndex, &g);
|
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) {
|
public override int measureText(const dchar[] text, ref int[] widths, int maxWidth) {
|
||||||
if (_hfont is null || _drawbuf is null || text.length == 0)
|
if (_hfont is null || _drawbuf is null || text.length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -251,7 +275,7 @@ class Win32Font : Font {
|
||||||
|
|
||||||
|
|
||||||
class Win32FontManager : FontManager {
|
class Win32FontManager : FontManager {
|
||||||
FontRef[] _activeFonts;
|
FontList _activeFonts;
|
||||||
FontDef[] _fontFaces;
|
FontDef[] _fontFaces;
|
||||||
FontDef*[string] _faceByName;
|
FontDef*[string] _faceByName;
|
||||||
public this() {
|
public this() {
|
||||||
|
@ -277,32 +301,23 @@ class Win32FontManager : FontManager {
|
||||||
Log.i("Found ", _fontFaces.length, " font faces");
|
Log.i("Found ", _fontFaces.length, " font faces");
|
||||||
return res!=0;
|
return res!=0;
|
||||||
}
|
}
|
||||||
public override FontRef getFont(int size, int weight, bool italic, FontFamily family, string face) {
|
FontRef _emptyFontRef;
|
||||||
FontRef res;
|
public override ref FontRef getFont(int size, int weight, bool italic, FontFamily family, string face) {
|
||||||
|
Log.i("getFont()");
|
||||||
FontDef * def = findFace(family, face);
|
FontDef * def = findFace(family, face);
|
||||||
if (def !is null) {
|
if (def !is null) {
|
||||||
for (int i = 0; i < _activeFonts.length; i++) {
|
int index = _activeFonts.find(size, weight, italic, def.family, def.face);
|
||||||
Font item = _activeFonts[i].get;
|
if (index >= 0)
|
||||||
if (item.family != def.family)
|
return _activeFonts.get(index);
|
||||||
continue;
|
Log.d("Creating new font");
|
||||||
if (item.size != size)
|
Win32Font item = new Win32Font();
|
||||||
continue;
|
if (!item.create(def, size, weight, italic))
|
||||||
if (item.italic != italic || item.weight != weight)
|
return _emptyFontRef;
|
||||||
continue;
|
Log.d("Adding to list of active fonts");
|
||||||
if (!equal(item.face, def.face))
|
return _activeFonts.add(item);
|
||||||
continue;
|
} else {
|
||||||
res = _activeFonts[i];
|
return _emptyFontRef;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (res.isNull) {
|
|
||||||
Win32Font item = new Win32Font();
|
|
||||||
if (!item.create(def, size, weight, italic))
|
|
||||||
return res;
|
|
||||||
res = item;
|
|
||||||
_activeFonts ~= res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
FontDef * findFace(FontFamily family) {
|
FontDef * findFace(FontFamily family) {
|
||||||
FontDef * res = null;
|
FontDef * res = null;
|
||||||
|
|
25
winmain.d
25
winmain.d
|
@ -6,19 +6,42 @@ import dlangui.core.logger;
|
||||||
import dlangui.graphics.fonts;
|
import dlangui.graphics.fonts;
|
||||||
import std.stdio;
|
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() {
|
extern (C) int UIAppMain() {
|
||||||
Log.d("Some debug message");
|
Log.d("Some debug message");
|
||||||
Log.e("Sample error #", 22);
|
Log.e("Sample error #", 22);
|
||||||
|
|
||||||
Window window = Platform.instance().createWindow("My Window", null);
|
Window window = Platform.instance().createWindow("My Window", null);
|
||||||
Widget myWidget = new Widget();
|
Widget myWidget = new TestWidget();
|
||||||
window.mainWidget = myWidget;
|
window.mainWidget = myWidget;
|
||||||
window.show();
|
window.show();
|
||||||
window.windowCaption = "New Window Caption";
|
window.windowCaption = "New Window Caption";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Log.d("Before getFont");
|
||||||
FontRef font = FontManager.instance.getFont(32, 400, false, FontFamily.SansSerif, "Arial");
|
FontRef font = FontManager.instance.getFont(32, 400, false, FontFamily.SansSerif, "Arial");
|
||||||
|
Log.d("After getFont");
|
||||||
assert(!font.isNull);
|
assert(!font.isNull);
|
||||||
int[] widths;
|
int[] widths;
|
||||||
dchar[] text = cast(dchar[])"Test string"d;
|
dchar[] text = cast(dchar[])"Test string"d;
|
||||||
|
Log.d("Calling measureText");
|
||||||
int charsMeasured = font.measureText(text, widths, 1000);
|
int charsMeasured = font.measureText(text, widths, 1000);
|
||||||
assert(charsMeasured > 0);
|
assert(charsMeasured > 0);
|
||||||
int w = widths[charsMeasured - 1];
|
int w = widths[charsMeasured - 1];
|
||||||
|
|
Loading…
Reference in New Issue