aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp')
-rw-r--r--libraries/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp b/libraries/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp
new file mode 100644
index 0000000..f072e87
--- /dev/null
+++ b/libraries/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp
@@ -0,0 +1,231 @@
1//#define ENABLE_LOG_PRINTF
2
3#include <string.h>
4
5#include "evas_direct3d_object_font.h"
6#include "evas_direct3d_image_cache.h"
7#include "evas_direct3d_device.h"
8#include "evas_direct3d_shader_pack.h"
9#include "evas_direct3d_vertex_buffer_cache.h"
10
11D3DObjectFont::Cache D3DObjectFont::_cache;
12
13D3DObjectFont::D3DObjectFont(void *source, int image_id)
14{
15 _image_id = image_id;
16 _color = 0xff000000;
17 _source = source;
18 D3DImageCache::Current()->AddImageUser(_image_id);
19}
20
21D3DObjectFont::~D3DObjectFont()
22{
23 D3DImageCache::Current()->RemoveImageUser(_image_id);
24}
25
26void D3DObjectFont::CopyTo(D3DObjectFont *font)
27{
28 assert(font != NULL);
29 font->_image_id = _image_id;
30 font->_source = _source;
31 D3DImageCache::Current()->AddImageUser(font->_image_id);
32 _glyphs.CopyTo(font->_glyphs);
33}
34
35void D3DObjectFont::BeginCache(int image_id)
36{
37 if (_cache.enabled)
38 return;
39 int w = D3DImageCache::Current()->GetImageWidth(image_id);
40 int h = D3DImageCache::Current()->GetImageHeight(image_id);
41 _cache.enabled = true;
42 _cache.image_id = image_id;
43 _cache.data.Allocate(w * h);
44
45 if (_cache.dirty.Length() != h)
46 {
47 _cache.dirty.Allocate(h);
48 memset(_cache.dirty.Data(), 0xff, sizeof(POINT) * _cache.dirty.Length());
49 }
50
51 ZeroMemory(_cache.data.Data(), sizeof(DWORD) * _cache.data.Length());
52 _cache.width = w;
53 _cache.height = h;
54
55 _cache.valid_rect.left = w;
56 _cache.valid_rect.right = 0;
57 _cache.valid_rect.top = h;
58 _cache.valid_rect.bottom = 0;
59}
60
61void D3DObjectFont::Draw(D3DDevice *d3d)
62{
63 assert(_cache.image_id == _image_id);
64}
65
66void D3DObjectFont::EndCache(D3DDevice *d3d)
67{
68 if (!_cache.enabled)
69 return;
70 _cache.enabled = false;
71
72 if (_cache.data.Length() == 0)
73 return;
74
75 D3DImageCache::CacheEntryInfo info;
76 ZeroMemory(&info, sizeof(info));
77 info.id = _cache.image_id;
78 info.width = _cache.width;
79 info.height = _cache.height;
80 if (!D3DImageCache::Current()->UpdateImageDataWithDirtyInfo(info,
81 _cache.data.Data(), _cache.dirty.Data()))
82 //if (!D3DImageCache::Current()->UpdateImageDataDiscard(info, _cache.data.Data()));
83 {
84 return;
85 }
86
87 D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYUV);
88 D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_UV);
89 D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_TEX_2); // This image is in s1
90 D3DImageCache::Current()->SelectImageToDevice(d3d, _cache.image_id);
91
92 const FLOAT half_x = 0.5f / FLOAT(_cache.width);
93 const FLOAT half_y = 0.5f / FLOAT(_cache.height);
94 FLOAT left = FLOAT(_cache.valid_rect.left - 5) / FLOAT(_cache.width),
95 top = FLOAT(_cache.valid_rect.top - 5) / FLOAT(_cache.height),
96 right = FLOAT(_cache.valid_rect.right + 5) / FLOAT(_cache.width),
97 bottom = FLOAT(_cache.valid_rect.bottom + 5) / FLOAT(_cache.height);
98
99 const Vertex data[6] = {
100 {left * 2 - 1, 2 * (1 - bottom) - 1, left + half_x, bottom + half_y},
101 {left * 2 - 1, 2 * (1 - top) - 1, left + half_x, top + half_y},
102 {right * 2 - 1, 2 * (1 - bottom) - 1, right + half_x, bottom + half_y},
103 {right * 2 - 1, 2 * (1 - bottom) - 1, right + half_x, bottom + half_y},
104 {left * 2 - 1, 2 * (1 - top) - 1, left + half_x, top + half_y},
105 {right * 2 - 1, 2 * (1 - top) - 1, right + half_x, top + half_y}};
106
107 d3d->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, data, sizeof(Vertex));
108
109 //D3DImageCache::Current()->UpdateImageDataWithDirtyInfo(info, NULL, _cache.dirty.Data());
110}
111
112D3DObjectFont::Glyph *D3DObjectFont::GetGlyph(void *source)
113{
114 if (_image_id < 0)
115 {
116 WRN("Font is not initialized");
117 return NULL;
118 }
119 for (int i = 0; i < _glyphs.Length(); i++)
120 {
121 if (_glyphs[i]->Compare(source))
122 return _glyphs[i];
123 }
124 return NULL;
125}
126
127D3DObjectFont::Glyph *D3DObjectFont::AddGlyph(D3DDevice *d3d, void *source,
128 BYTE *data8, int width, int height, int pitch)
129{
130 if (_image_id < 0)
131 {
132 WRN("Font is not initialized");
133 return NULL;
134 }
135 for (int i = 0; i < _glyphs.Length(); i++)
136 {
137 if (_glyphs[i]->Compare(source))
138 return _glyphs[i];
139 }
140 Ref<Glyph> glyph = new Glyph(source);
141 glyph->_data.Allocate(width * height);
142 glyph->_width = width;
143 glyph->_height = height;
144
145 for (int i = 0; i < height; i++)
146 CopyMemory(&glyph->_data[i * width], &data8[i * pitch], width);
147
148 Log("Glyph added (%p) (%dx%d)", source, width, height);
149 _glyphs.Add(glyph);
150 return _glyphs.Last()->Addr();
151}
152
153void D3DObjectFont::PushForDraw(Glyph *glyph, int x, int y)
154{
155 BeginCache(_image_id);
156
157 // Uff, I'm not sure about multiple windows...
158
159#define LERP(a, b, t1, t2) (BYTE)(FLOAT(a) * (t1) + FLOAT(b) * (t2))
160
161 Color dc, sc;
162 FLOAT a;
163 sc.color = _color;
164
165 const FLOAT color_alpha = sc.Alpha();
166
167 DWORD *data = _cache.data.Data();
168 BYTE *gdata = glyph->_data.Data();
169 const int glyph_height = glyph->_height;
170 const int cache_height = _cache.height;
171 const int glyph_width = glyph->_width;
172 const int cache_width = _cache.width;
173
174 for (int i = 0, yi = y; i < glyph_height && yi < cache_height; i++, yi++)
175 {
176 if (yi < 0)
177 continue;
178 DWORD *dst = data + ((yi) * cache_width + x);
179 BYTE *src = gdata + (i * glyph_width);
180 POINT *dirty_yi = &_cache.dirty[yi];
181
182 if (_cache.valid_rect.top > yi)
183 _cache.valid_rect.top = yi;
184 if (_cache.valid_rect.bottom < yi)
185 _cache.valid_rect.bottom = yi;
186
187 for (int j = 0, xj = x; j < glyph_width && xj < cache_width; j++, xj++, dst++, src++)
188 {
189 if (xj < 0)
190 continue;
191 BYTE glyph_pix = *src;
192 if (glyph_pix == 0)
193 continue;
194
195 if (dirty_yi->x >= 0 && dirty_yi->y < 0)
196 dirty_yi->x = 0, dirty_yi->y = cache_width - 1;
197 else
198 {
199 if (dirty_yi->x < 0 || dirty_yi->x > xj)
200 dirty_yi->x = xj;
201 if (dirty_yi->y < 0 || dirty_yi->y < xj)
202 dirty_yi->y = xj;
203 }
204
205 if (_cache.valid_rect.left > xj)
206 _cache.valid_rect.left = xj;
207 if (_cache.valid_rect.right < xj)
208 _cache.valid_rect.right = xj;
209
210 if (glyph_pix == 0xff && sc.a == 0xff)
211 {
212 *dst = sc.color;
213 continue;
214 }
215 a = FLOAT(glyph_pix) * color_alpha / 255.f;
216 if (*dst == 0)
217 {
218 *dst = (BYTE(255.f * a) << 24) | (0x00ffffff & sc.color);
219 continue;
220 }
221
222 dc.color = *dst;
223
224 dc.r = LERP(dc.r, sc.r, 1 - a, a);
225 dc.g = LERP(dc.g, sc.g, 1 - a, a);
226 dc.b = LERP(dc.b, sc.b, 1 - a, a);
227 dc.a = max(dc.a, BYTE(255.f * a));
228 *dst = dc.color;
229 }
230 }
231}