diff options
author | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-04 18:41:13 +1000 |
commit | dd7595a3475407a7fa96a97393bae8c5220e8762 (patch) | |
tree | e341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp | |
parent | Add the skeleton. (diff) | |
download | SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2 SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz |
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
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.cpp | 231 |
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 | |||
11 | D3DObjectFont::Cache D3DObjectFont::_cache; | ||
12 | |||
13 | D3DObjectFont::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 | |||
21 | D3DObjectFont::~D3DObjectFont() | ||
22 | { | ||
23 | D3DImageCache::Current()->RemoveImageUser(_image_id); | ||
24 | } | ||
25 | |||
26 | void 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 | |||
35 | void 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 | |||
61 | void D3DObjectFont::Draw(D3DDevice *d3d) | ||
62 | { | ||
63 | assert(_cache.image_id == _image_id); | ||
64 | } | ||
65 | |||
66 | void 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 | |||
112 | D3DObjectFont::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 | |||
127 | D3DObjectFont::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 | |||
153 | void 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 | } | ||