rays 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.doc/ext/rays/bitmap.cpp +28 -8
- data/.doc/ext/rays/bounds.cpp +1 -1
- data/.doc/ext/rays/camera.cpp +5 -5
- data/.doc/ext/rays/color.cpp +1 -1
- data/.doc/ext/rays/color_space.cpp +10 -6
- data/.doc/ext/rays/font.cpp +116 -18
- data/.doc/ext/rays/image.cpp +27 -4
- data/.doc/ext/rays/matrix.cpp +1 -1
- data/.doc/ext/rays/painter.cpp +5 -5
- data/.doc/ext/rays/point.cpp +1 -1
- data/.doc/ext/rays/polygon.cpp +4 -4
- data/.doc/ext/rays/polyline.cpp +2 -2
- data/.doc/ext/rays/shader.cpp +2 -2
- data/.github/workflows/release-gem.yml +2 -49
- data/.github/workflows/tag.yml +5 -28
- data/.github/workflows/test.yml +1 -37
- data/ChangeLog.md +21 -0
- data/Gemfile.lock +13 -8
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +28 -8
- data/ext/rays/bounds.cpp +1 -1
- data/ext/rays/camera.cpp +5 -5
- data/ext/rays/color.cpp +1 -1
- data/ext/rays/color_space.cpp +10 -6
- data/ext/rays/defs.h +3 -3
- data/ext/rays/extconf.rb +6 -5
- data/ext/rays/font.cpp +120 -18
- data/ext/rays/image.cpp +27 -4
- data/ext/rays/matrix.cpp +1 -1
- data/ext/rays/painter.cpp +5 -5
- data/ext/rays/point.cpp +1 -1
- data/ext/rays/polygon.cpp +4 -4
- data/ext/rays/polyline.cpp +2 -2
- data/ext/rays/shader.cpp +2 -2
- data/include/rays/bitmap.h +2 -0
- data/include/rays/font.h +46 -4
- data/include/rays/image.h +9 -5
- data/include/rays/painter.h +3 -1
- data/include/rays/ruby/color_space.h +2 -0
- data/include/rays/shader.h +3 -0
- data/lib/rays/font.rb +4 -1
- data/lib/rays/image.rb +2 -0
- data/lib/rays/painter.rb +5 -5
- data/rays.gemspec +3 -3
- data/src/bitmap.cpp +107 -0
- data/src/color.cpp +17 -0
- data/src/font.cpp +121 -25
- data/src/font.h +7 -5
- data/src/image.cpp +102 -100
- data/src/ios/font.mm +77 -24
- data/src/opengl/color_space.cpp +4 -1
- data/src/opengl/painter.cpp +86 -18
- data/src/opengl/shader.cpp +15 -13
- data/src/opengl/texture.cpp +2 -2
- data/src/opengl/win32/opengl.cpp +17 -12
- data/src/osx/font.mm +77 -24
- data/src/painter.cpp +12 -12
- data/src/painter.h +5 -1
- data/src/polygon.cpp +21 -21
- data/src/polyline.cpp +4 -4
- data/src/sdl/bitmap.cpp +16 -10
- data/src/sdl/font.cpp +56 -50
- data/src/win32/bitmap.cpp +22 -13
- data/src/win32/font.cpp +43 -44
- data/src/win32/gdi.cpp +43 -46
- data/src/win32/gdi.h +6 -1
- data/src/win32/rays.cpp +18 -1
- data/test/test_bitmap.rb +28 -10
- data/test/test_font.rb +58 -0
- data/test/test_image.rb +29 -6
- data/test/test_painter.rb +39 -0
- metadata +8 -8
- data/.github/workflows/utils.rb +0 -127
data/src/sdl/font.cpp
CHANGED
|
@@ -20,7 +20,11 @@ namespace Rays
|
|
|
20
20
|
|
|
21
21
|
String name;
|
|
22
22
|
|
|
23
|
-
coord size
|
|
23
|
+
coord size = 0;
|
|
24
|
+
|
|
25
|
+
int weight = Font::WEIGHT_NORMAL;
|
|
26
|
+
|
|
27
|
+
bool italic = false;
|
|
24
28
|
|
|
25
29
|
virtual ~Data ()
|
|
26
30
|
{
|
|
@@ -63,7 +67,7 @@ namespace Rays
|
|
|
63
67
|
|
|
64
68
|
String path;
|
|
65
69
|
|
|
66
|
-
SDLFontData (const char* path, coord size)
|
|
70
|
+
SDLFontData (const char* path, coord size, int weight, bool italic)
|
|
67
71
|
{
|
|
68
72
|
if (!path)
|
|
69
73
|
argument_error(__FILE__, __LINE__);
|
|
@@ -72,8 +76,16 @@ namespace Rays
|
|
|
72
76
|
if (!font)
|
|
73
77
|
rays_error(__FILE__, __LINE__, "failed to open font: %s", TTF_GetError());
|
|
74
78
|
|
|
75
|
-
this->path
|
|
76
|
-
this->size
|
|
79
|
+
this->path = path;
|
|
80
|
+
this->size = size;
|
|
81
|
+
this->weight = weight;
|
|
82
|
+
this->italic = italic;
|
|
83
|
+
|
|
84
|
+
int style = TTF_STYLE_NORMAL;
|
|
85
|
+
if (weight >= Font::WEIGHT_SEMIBOLD) style |= TTF_STYLE_BOLD;
|
|
86
|
+
if (italic) style |= TTF_STYLE_ITALIC;
|
|
87
|
+
if (style != TTF_STYLE_NORMAL)
|
|
88
|
+
TTF_SetFontStyle(font, style);
|
|
77
89
|
|
|
78
90
|
const char* family = TTF_FontFaceFamilyName(font);
|
|
79
91
|
if (family) this->name = family;
|
|
@@ -91,8 +103,9 @@ namespace Rays
|
|
|
91
103
|
rays_error(__FILE__, __LINE__, "TTF_RenderUTF8_Blended failed: %s", TTF_GetError());
|
|
92
104
|
|
|
93
105
|
SDL_Rect dst = {(int) x, (int) y, surface->w, surface->h};
|
|
106
|
+
// blending onto zeros premultiplies the straight alpha of SDL_ttf
|
|
94
107
|
SDL_FillRect(target, &dst, 0);
|
|
95
|
-
SDL_SetSurfaceBlendMode(surface,
|
|
108
|
+
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
|
|
96
109
|
SDL_BlitSurface(surface, NULL, target, &dst);
|
|
97
110
|
SDL_FreeSurface(surface);
|
|
98
111
|
}
|
|
@@ -126,7 +139,7 @@ namespace Rays
|
|
|
126
139
|
|
|
127
140
|
Data* dup (coord size) const override
|
|
128
141
|
{
|
|
129
|
-
return new SDLFontData(path.c_str(), size);
|
|
142
|
+
return new SDLFontData(path.c_str(), size, weight, italic);
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
};// SDLData
|
|
@@ -144,22 +157,22 @@ namespace Rays
|
|
|
144
157
|
});
|
|
145
158
|
|
|
146
159
|
EM_JS(double, rays_wasm_font_text_width_, (
|
|
147
|
-
const char* str, const char* name, double size),
|
|
160
|
+
const char* str, const char* name, double size, int weight, int italic),
|
|
148
161
|
{
|
|
149
162
|
const s = UTF8ToString(str);
|
|
150
163
|
const n = UTF8ToString(name);
|
|
151
164
|
const c = Module._raysFontContext;
|
|
152
|
-
c.font = `${size}px "${n}"`;
|
|
165
|
+
c.font = `${italic ? 'italic' : 'normal'} ${weight} ${size}px "${n}"`;
|
|
153
166
|
return c.measureText(s).width;
|
|
154
167
|
});
|
|
155
168
|
|
|
156
169
|
EM_JS(void, rays_wasm_font_get_metrics_, (
|
|
157
|
-
const char* name, double size,
|
|
170
|
+
const char* name, double size, int weight, int italic,
|
|
158
171
|
double* out_ascent, double* out_descent, double* out_leading),
|
|
159
172
|
{
|
|
160
173
|
const n = UTF8ToString(name);
|
|
161
174
|
const c = Module._raysFontContext;
|
|
162
|
-
c.font = `${size}px "${n}"`;
|
|
175
|
+
c.font = `${italic ? 'italic' : 'normal'} ${weight} ${size}px "${n}"`;
|
|
163
176
|
const m = c.measureText('Mgjpqy');
|
|
164
177
|
const asc = Math.max(
|
|
165
178
|
m. fontBoundingBoxAscent ?? 0,
|
|
@@ -174,29 +187,30 @@ namespace Rays
|
|
|
174
187
|
});
|
|
175
188
|
|
|
176
189
|
EM_JS(void*, rays_wasm_font_render_, (
|
|
177
|
-
const char* str, const char* name, double size,
|
|
190
|
+
const char* str, const char* name, double size, int weight, int italic,
|
|
178
191
|
int* out_width, int* out_height, double* out_ascent, double* out_descent),
|
|
179
192
|
{
|
|
180
|
-
const s
|
|
181
|
-
const n
|
|
182
|
-
const c
|
|
183
|
-
const cv
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const
|
|
193
|
+
const s = UTF8ToString(str);
|
|
194
|
+
const n = UTF8ToString(name);
|
|
195
|
+
const c = Module._raysFontContext;
|
|
196
|
+
const cv = Module._raysFontCanvas;
|
|
197
|
+
const font = `${italic ? 'italic' : 'normal'} ${weight} ${size}px "${n}"`;
|
|
198
|
+
c.font = font;
|
|
199
|
+
const m = c.measureText(s);
|
|
200
|
+
const asc = Math.max(
|
|
187
201
|
m. fontBoundingBoxAscent ?? 0,
|
|
188
202
|
m.actualBoundingBoxAscent ?? size * 0.8);
|
|
189
|
-
const dsc
|
|
203
|
+
const dsc = Math.max(
|
|
190
204
|
m. fontBoundingBoxDescent ?? 0,
|
|
191
205
|
m.actualBoundingBoxDescent ?? size * 0.2);
|
|
192
|
-
const w
|
|
193
|
-
const h
|
|
206
|
+
const w = Math.max(1, Math.ceil(m.width));
|
|
207
|
+
const h = Math.max(1, Math.ceil(asc + dsc));
|
|
194
208
|
|
|
195
209
|
if (cv.width < w) cv.width = w;
|
|
196
210
|
if (cv.height < h) cv.height = h;
|
|
197
211
|
|
|
198
212
|
c.clearRect(0, 0, cv.width, cv.height);
|
|
199
|
-
c.font =
|
|
213
|
+
c.font = font;// re-apply after canvas resize
|
|
200
214
|
c.fillStyle = 'white';
|
|
201
215
|
c.textBaseline = 'alphabetic';
|
|
202
216
|
c.fillText(s, 0, asc);
|
|
@@ -234,12 +248,14 @@ namespace Rays
|
|
|
234
248
|
struct CanvasFontData : public RawFont::Data
|
|
235
249
|
{
|
|
236
250
|
|
|
237
|
-
CanvasFontData (const char* name, coord size)
|
|
251
|
+
CanvasFontData (const char* name, coord size, int weight, bool italic)
|
|
238
252
|
{
|
|
239
253
|
rays_wasm_font_init_();
|
|
240
254
|
|
|
241
|
-
this->name
|
|
242
|
-
this->size
|
|
255
|
+
this->name = name && *name != '\0' ? name : "sans-serif";
|
|
256
|
+
this->size = size;
|
|
257
|
+
this->weight = weight;
|
|
258
|
+
this->italic = italic;
|
|
243
259
|
}
|
|
244
260
|
|
|
245
261
|
void draw_string (SDL_Surface* target, const char* str, coord x, coord y) override
|
|
@@ -248,7 +264,7 @@ namespace Rays
|
|
|
248
264
|
double ascent = 0, descent = 0;
|
|
249
265
|
std::shared_ptr<void> pixels(
|
|
250
266
|
rays_wasm_font_render_(
|
|
251
|
-
str, name.c_str(), (double) size,
|
|
267
|
+
str, name.c_str(), (double) size, weight, italic,
|
|
252
268
|
&w, &h, &ascent, &descent),
|
|
253
269
|
free);
|
|
254
270
|
if (!pixels || w <= 0 || h <= 0) return;
|
|
@@ -260,21 +276,24 @@ namespace Rays
|
|
|
260
276
|
rays_error(__FILE__, __LINE__, "SDL_CreateRGBSurfaceFrom failed: %s", SDL_GetError());
|
|
261
277
|
|
|
262
278
|
SDL_Rect dest = {(int) x, (int) y, w, h};
|
|
279
|
+
// blending onto zeros premultiplies the straight alpha of the canvas
|
|
263
280
|
SDL_FillRect(target, &dest, 0);
|
|
264
|
-
SDL_SetSurfaceBlendMode(surface,
|
|
281
|
+
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
|
|
265
282
|
SDL_BlitSurface(surface, NULL, target, &dest);
|
|
266
283
|
SDL_FreeSurface(surface);
|
|
267
284
|
}
|
|
268
285
|
|
|
269
286
|
coord get_width (const char* str) override
|
|
270
287
|
{
|
|
271
|
-
return (coord) rays_wasm_font_text_width_(
|
|
288
|
+
return (coord) rays_wasm_font_text_width_(
|
|
289
|
+
str, name.c_str(), (double) size, weight, italic);
|
|
272
290
|
}
|
|
273
291
|
|
|
274
292
|
coord get_height (coord* ascent, coord* descent, coord* leading) override
|
|
275
293
|
{
|
|
276
294
|
double asc = 0, desc = 0, lead = 0;
|
|
277
|
-
rays_wasm_font_get_metrics_(
|
|
295
|
+
rays_wasm_font_get_metrics_(
|
|
296
|
+
name.c_str(), (double) size, weight, italic, &asc, &desc, &lead);
|
|
278
297
|
|
|
279
298
|
if (ascent) *ascent = (coord) asc;
|
|
280
299
|
if (descent) *descent = (coord) desc;
|
|
@@ -290,7 +309,7 @@ namespace Rays
|
|
|
290
309
|
|
|
291
310
|
Data* dup (coord size) const override
|
|
292
311
|
{
|
|
293
|
-
return new CanvasFontData(name.c_str(), size);
|
|
312
|
+
return new CanvasFontData(name.c_str(), size, weight, italic);
|
|
294
313
|
}
|
|
295
314
|
|
|
296
315
|
};// CanvasData
|
|
@@ -334,7 +353,7 @@ namespace Rays
|
|
|
334
353
|
RawFont_load (const char* path, coord size)
|
|
335
354
|
{
|
|
336
355
|
RawFont rawfont;
|
|
337
|
-
rawfont.self.reset(new SDLFontData(path, size));
|
|
356
|
+
rawfont.self.reset(new SDLFontData(path, size, Font::WEIGHT_NORMAL, false));
|
|
338
357
|
return rawfont;
|
|
339
358
|
}
|
|
340
359
|
|
|
@@ -344,29 +363,23 @@ namespace Rays
|
|
|
344
363
|
}
|
|
345
364
|
|
|
346
365
|
static RawFont::Data*
|
|
347
|
-
create_data (const char* name, coord size)
|
|
366
|
+
create_data (const char* name, coord size, int weight, bool italic)
|
|
348
367
|
{
|
|
349
368
|
#ifdef WASM
|
|
350
|
-
return new CanvasFontData(name, size);
|
|
369
|
+
return new CanvasFontData(name, size, weight, italic);
|
|
351
370
|
#else
|
|
352
371
|
if (name)
|
|
353
372
|
not_implemented_error(__FILE__, __LINE__);
|
|
354
|
-
return new SDLFontData(
|
|
373
|
+
return new SDLFontData(
|
|
374
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", size, weight, italic);
|
|
355
375
|
#endif
|
|
356
376
|
}
|
|
357
377
|
|
|
358
|
-
RawFont::RawFont (const char* name, coord size)
|
|
359
|
-
: self(create_data(name, size))
|
|
378
|
+
RawFont::RawFont (const char* name, coord size, int weight, bool italic)
|
|
379
|
+
: self(create_data(name, size, weight, italic))
|
|
360
380
|
{
|
|
361
381
|
}
|
|
362
382
|
|
|
363
|
-
RawFont::RawFont (const This& obj, coord size)
|
|
364
|
-
{
|
|
365
|
-
if (!obj) return;
|
|
366
|
-
|
|
367
|
-
self.reset(obj.self->dup(size));
|
|
368
|
-
}
|
|
369
|
-
|
|
370
383
|
RawFont::~RawFont ()
|
|
371
384
|
{
|
|
372
385
|
}
|
|
@@ -398,13 +411,6 @@ namespace Rays
|
|
|
398
411
|
return self->name;
|
|
399
412
|
}
|
|
400
413
|
|
|
401
|
-
coord
|
|
402
|
-
RawFont::size () const
|
|
403
|
-
{
|
|
404
|
-
if (!*this) return 0;
|
|
405
|
-
return self->size;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
414
|
coord
|
|
409
415
|
RawFont::get_width (const char* str) const
|
|
410
416
|
{
|
data/src/win32/bitmap.cpp
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
#include "../bitmap.h"
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
#define STBI_WINDOWS_UTF8
|
|
5
|
+
#define STBIW_WINDOWS_UTF8
|
|
6
|
+
|
|
4
7
|
#define STB_IMAGE_IMPLEMENTATION
|
|
5
8
|
#include <stb_image.h>
|
|
6
9
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
7
10
|
#include <stb_image_write.h>
|
|
8
11
|
|
|
12
|
+
#include <memory>
|
|
9
13
|
#include "rays/exception.h"
|
|
10
14
|
#include "rays/image.h"
|
|
11
15
|
#include "rays/painter.h"
|
|
@@ -166,13 +170,13 @@ namespace Rays
|
|
|
166
170
|
}
|
|
167
171
|
|
|
168
172
|
const auto& cs = bitmap.color_space();
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
173
|
+
int w = bitmap.width();
|
|
174
|
+
int h = bitmap.height();
|
|
175
|
+
int row_size = w * cs.Bpp();
|
|
172
176
|
|
|
173
|
-
std::unique_ptr<uchar[]> pixels(new uchar[h *
|
|
174
|
-
for (
|
|
175
|
-
memcpy(pixels.get() +
|
|
177
|
+
std::unique_ptr<uchar[]> pixels(new uchar[h * row_size]);
|
|
178
|
+
for (int y = 0; y < h; ++y)
|
|
179
|
+
memcpy(pixels.get() + row_size * y, bitmap.at<uchar>(0, y), row_size);
|
|
176
180
|
|
|
177
181
|
String ext = extension;
|
|
178
182
|
ext.downcase();
|
|
@@ -207,6 +211,10 @@ namespace Rays
|
|
|
207
211
|
p.end();
|
|
208
212
|
bmp = img.bitmap();
|
|
209
213
|
}
|
|
214
|
+
|
|
215
|
+
if (bmp.color_space().has_alpha())
|
|
216
|
+
bmp = bmp.dup(false);// stb_image_write expects straight alpha
|
|
217
|
+
|
|
210
218
|
save_bitmap(bmp, path);
|
|
211
219
|
}
|
|
212
220
|
|
|
@@ -217,16 +225,17 @@ namespace Rays
|
|
|
217
225
|
argument_error(__FILE__, __LINE__);
|
|
218
226
|
|
|
219
227
|
int w = 0, h = 0, Bpp = 0;
|
|
220
|
-
uchar
|
|
228
|
+
std::unique_ptr<uchar, decltype(&stbi_image_free)>
|
|
229
|
+
pixels(stbi_load(path, &w, &h, &Bpp, 0), stbi_image_free);
|
|
221
230
|
if (!pixels)
|
|
222
231
|
rays_error(__FILE__, __LINE__, "failed to load: '%s'", path);
|
|
223
232
|
|
|
224
233
|
ColorSpace cs;
|
|
225
234
|
switch (Bpp)
|
|
226
235
|
{
|
|
227
|
-
case 1: cs = GRAY_8;
|
|
228
|
-
case 3: cs = RGB_888;
|
|
229
|
-
case 4: cs = RGBA_8888; break
|
|
236
|
+
case 1: cs = GRAY_8; break;
|
|
237
|
+
case 3: cs = RGB_888; break;
|
|
238
|
+
case 4: cs = ColorSpace(RGBA_8888, false); break;// stb_image gives straight alpha
|
|
230
239
|
default:
|
|
231
240
|
rays_error(__FILE__, __LINE__, "unsupported image file: '%s'", path);
|
|
232
241
|
}
|
|
@@ -235,11 +244,11 @@ namespace Rays
|
|
|
235
244
|
if (!bmp)
|
|
236
245
|
rays_error(__FILE__, __LINE__, "failed to create Bitmap object");
|
|
237
246
|
|
|
238
|
-
int
|
|
247
|
+
int size = Bpp * w;
|
|
239
248
|
for (int y = 0; y < h; ++y)
|
|
240
|
-
memcpy(bmp.at<uchar>(0, y), pixels +
|
|
249
|
+
memcpy(bmp.at<uchar>(0, y), pixels.get() + size * y, size);
|
|
241
250
|
|
|
242
|
-
return bmp;
|
|
251
|
+
return cs.has_alpha() ? bmp.dup(true) : bmp;
|
|
243
252
|
}
|
|
244
253
|
|
|
245
254
|
HBITMAP
|
data/src/win32/font.cpp
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
#include <assert.h>
|
|
5
|
+
#include <string>
|
|
5
6
|
#include <set>
|
|
6
7
|
#include "rays/exception.h"
|
|
7
8
|
#include "gdi.h"
|
|
@@ -16,7 +17,7 @@ namespace Rays
|
|
|
16
17
|
|
|
17
18
|
Win32::Font font;
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
mutable coord height = -1, ascent = 0, descent = 0, leading = 0;
|
|
20
21
|
|
|
21
22
|
};// RawFont::Data
|
|
22
23
|
|
|
@@ -40,15 +41,18 @@ namespace Rays
|
|
|
40
41
|
|
|
41
42
|
static int CALLBACK
|
|
42
43
|
enum_callback (
|
|
43
|
-
const
|
|
44
|
+
const ENUMLOGFONTW* elf, const NEWTEXTMETRICW* ntm, DWORD font_type, LPARAM lp)
|
|
44
45
|
{
|
|
45
|
-
const auto* params
|
|
46
|
-
const
|
|
47
|
-
?
|
|
48
|
-
:
|
|
46
|
+
const auto* params = (EnumFontFamiliesCallbackParams*) lp;
|
|
47
|
+
const wchar_t* name = params->fullname
|
|
48
|
+
? elf->elfFullName
|
|
49
|
+
: elf->elfLogFont.lfFaceName;
|
|
49
50
|
|
|
50
|
-
if (name && *name != '\0'
|
|
51
|
-
|
|
51
|
+
if (name && *name != L'\0' && *name != L'@')
|
|
52
|
+
{
|
|
53
|
+
size_t max_ = params->fullname ? LF_FULLFACESIZE : LF_FACESIZE;
|
|
54
|
+
params->names->insert(String(name, wcsnlen(name, max_)));
|
|
55
|
+
}
|
|
52
56
|
|
|
53
57
|
return TRUE;
|
|
54
58
|
}
|
|
@@ -57,16 +61,19 @@ namespace Rays
|
|
|
57
61
|
get_font_names (
|
|
58
62
|
StringSet* names, HDC hdc, const char* query = NULL, bool fullname = false)
|
|
59
63
|
{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
LOGFONT lf = {0};
|
|
64
|
+
LOGFONTW lf = {0};
|
|
63
65
|
lf.lfCharSet = DEFAULT_CHARSET;
|
|
64
66
|
|
|
65
|
-
if (query)
|
|
67
|
+
if (query)
|
|
68
|
+
{
|
|
69
|
+
std::wstring wquery = String(query).to_wstr();
|
|
70
|
+
assert(wquery.size() < LF_FACESIZE);
|
|
71
|
+
wcsncpy(lf.lfFaceName, wquery.c_str(), LF_FACESIZE - 1);
|
|
72
|
+
}
|
|
66
73
|
|
|
67
74
|
EnumFontFamiliesCallbackParams params(names, fullname);
|
|
68
|
-
|
|
69
|
-
hdc, &lf, (
|
|
75
|
+
EnumFontFamiliesExW(
|
|
76
|
+
hdc, &lf, (FONTENUMPROCW) &enum_callback, (LPARAM) ¶ms, 0);
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
const FontFamilyMap&
|
|
@@ -105,18 +112,9 @@ namespace Rays
|
|
|
105
112
|
{
|
|
106
113
|
}
|
|
107
114
|
|
|
108
|
-
RawFont::RawFont (const char* name, coord size)
|
|
109
|
-
{
|
|
110
|
-
self->font = Win32::Font(name, size);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
RawFont::RawFont (const This& obj, coord size)
|
|
115
|
+
RawFont::RawFont (const char* name, coord size, int weight, bool italic)
|
|
114
116
|
{
|
|
115
|
-
|
|
116
|
-
if (path)
|
|
117
|
-
*this = RawFont_load(path, size);
|
|
118
|
-
else
|
|
119
|
-
self->font = Win32::Font(obj.name().c_str(), size);
|
|
117
|
+
self->font = Win32::Font(name, size, weight, italic);
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
RawFont::~RawFont ()
|
|
@@ -142,8 +140,10 @@ namespace Rays
|
|
|
142
140
|
if (!*this)
|
|
143
141
|
invalid_state_error(__FILE__, __LINE__);
|
|
144
142
|
|
|
143
|
+
std::wstring wstr = String(str).to_wstr();
|
|
144
|
+
|
|
145
145
|
coord width = 0, height = 0;
|
|
146
|
-
if (!self->font.get_extent(&width, &height,
|
|
146
|
+
if (!self->font.get_extent(&width, &height, wstr.c_str()))
|
|
147
147
|
rays_error(__FILE__, __LINE__, "failed to get font extent.");
|
|
148
148
|
|
|
149
149
|
DC dc = hdc;
|
|
@@ -155,7 +155,7 @@ namespace Rays
|
|
|
155
155
|
dc.set_text_color(RGB(255, 255, 255));
|
|
156
156
|
dc.set_back_color(RGB(0, 0, 0));
|
|
157
157
|
|
|
158
|
-
BOOL ret =
|
|
158
|
+
BOOL ret = TextOutW(dc.handle(), x, y, wstr.c_str(), (int) wstr.size());
|
|
159
159
|
|
|
160
160
|
dc.set_font(font);
|
|
161
161
|
dc.set_text_color(text_color);
|
|
@@ -172,13 +172,6 @@ namespace Rays
|
|
|
172
172
|
return self->font.name();
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
coord
|
|
176
|
-
RawFont::size () const
|
|
177
|
-
{
|
|
178
|
-
if (!*this) return 0;
|
|
179
|
-
return self->font.size();
|
|
180
|
-
}
|
|
181
|
-
|
|
182
175
|
coord
|
|
183
176
|
RawFont::get_width (const char* str) const
|
|
184
177
|
{
|
|
@@ -203,24 +196,30 @@ namespace Rays
|
|
|
203
196
|
if (!*this)
|
|
204
197
|
invalid_state_error(__FILE__, __LINE__);
|
|
205
198
|
|
|
206
|
-
if (
|
|
199
|
+
if (self->height < 0)
|
|
207
200
|
{
|
|
208
201
|
Win32::DC dc(GetDC(NULL), true, Win32::DC::RELEASE_DC);
|
|
209
202
|
dc.set_font(self->font);
|
|
210
203
|
|
|
211
|
-
|
|
212
|
-
|
|
204
|
+
TEXTMETRICW tm;
|
|
205
|
+
if (!GetTextMetricsW(dc.handle(), &tm))
|
|
206
|
+
rays_error(__FILE__, __LINE__, "failed to get font metrics");
|
|
207
|
+
|
|
208
|
+
coord height;
|
|
209
|
+
if (!self->font.get_extent(NULL, &height, L"X"))
|
|
210
|
+
rays_error(__FILE__, __LINE__, "failed to get font height");
|
|
213
211
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
self->height = height;
|
|
213
|
+
self->ascent = tm.tmAscent;
|
|
214
|
+
self->descent = tm.tmDescent;
|
|
215
|
+
self->leading = tm.tmExternalLeading;
|
|
217
216
|
}
|
|
218
217
|
|
|
219
|
-
|
|
220
|
-
if (
|
|
221
|
-
|
|
218
|
+
if (ascent) *ascent = self->ascent;
|
|
219
|
+
if (descent) *descent = self->descent;
|
|
220
|
+
if (leading) *leading = self->leading;
|
|
222
221
|
|
|
223
|
-
return height;
|
|
222
|
+
return self->height;
|
|
224
223
|
}
|
|
225
224
|
|
|
226
225
|
RawFont::operator bool () const
|
data/src/win32/gdi.cpp
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
#include <assert.h>
|
|
5
|
+
#include <math.h>
|
|
6
|
+
#include <string>
|
|
5
7
|
#include <vector>
|
|
6
8
|
|
|
7
9
|
|
|
@@ -117,7 +119,7 @@ namespace Rays
|
|
|
117
119
|
return false;
|
|
118
120
|
|
|
119
121
|
LOGPEN logpen;
|
|
120
|
-
if (!
|
|
122
|
+
if (!GetObjectW(handle(), sizeof(logpen), &logpen))
|
|
121
123
|
return false;
|
|
122
124
|
|
|
123
125
|
if (red) *red = GetRValue(logpen.lopnColor);
|
|
@@ -179,7 +181,7 @@ namespace Rays
|
|
|
179
181
|
return false;
|
|
180
182
|
|
|
181
183
|
LOGBRUSH logbrush;
|
|
182
|
-
if (!
|
|
184
|
+
if (!GetObjectW(handle(), sizeof(logbrush), &logbrush))
|
|
183
185
|
return false;
|
|
184
186
|
|
|
185
187
|
if (red) *red = GetRValue(logbrush.lbColor);
|
|
@@ -215,34 +217,34 @@ namespace Rays
|
|
|
215
217
|
|
|
216
218
|
|
|
217
219
|
static HFONT
|
|
218
|
-
create_font (const char* name, coord size
|
|
220
|
+
create_font (const char* name, coord size, int weight, bool italic)
|
|
219
221
|
{
|
|
220
|
-
|
|
222
|
+
NONCLIENTMETRICSW metrics;
|
|
221
223
|
memset(&metrics, 0, sizeof(metrics));
|
|
222
224
|
metrics.cbSize = sizeof(metrics);
|
|
223
225
|
|
|
224
|
-
if (!
|
|
226
|
+
if (!SystemParametersInfoW(
|
|
225
227
|
SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0))
|
|
226
228
|
{
|
|
227
229
|
return NULL;
|
|
228
230
|
}
|
|
229
231
|
|
|
230
|
-
|
|
232
|
+
LOGFONTW& logfont = metrics.lfMessageFont;
|
|
231
233
|
|
|
232
234
|
if (name)
|
|
233
|
-
strcpy(logfont.lfFaceName, name);
|
|
234
|
-
|
|
235
|
-
if (size == 0)
|
|
236
|
-
logfont.lfHeight = 0;
|
|
237
|
-
else
|
|
238
235
|
{
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
72);
|
|
236
|
+
std::wstring wname = String(name).to_wstr();
|
|
237
|
+
wcsncpy(logfont.lfFaceName, wname.c_str(), LF_FACESIZE - 1);
|
|
238
|
+
logfont.lfFaceName[LF_FACESIZE - 1] = L'\0';
|
|
243
239
|
}
|
|
244
240
|
|
|
245
|
-
|
|
241
|
+
logfont.lfHeight = size == 0 ? 0 : -(LONG) fmax(1, round(size));
|
|
242
|
+
|
|
243
|
+
if (weight == 0) weight = 1;// 0 == FW_DONTCARE
|
|
244
|
+
if (weight >= 0) logfont.lfWeight = weight;
|
|
245
|
+
if (italic) logfont.lfItalic = TRUE;
|
|
246
|
+
|
|
247
|
+
return CreateFontIndirectW(&logfont);
|
|
246
248
|
}
|
|
247
249
|
|
|
248
250
|
|
|
@@ -252,9 +254,9 @@ namespace Rays
|
|
|
252
254
|
self->handle.reset(handle, owner);
|
|
253
255
|
}
|
|
254
256
|
|
|
255
|
-
Font::Font (const char* name, coord size)
|
|
257
|
+
Font::Font (const char* name, coord size, int weight, bool italic)
|
|
256
258
|
{
|
|
257
|
-
self->handle.reset(create_font(name, size));
|
|
259
|
+
self->handle.reset(create_font(name, size, weight, italic));
|
|
258
260
|
}
|
|
259
261
|
|
|
260
262
|
Font::~Font ()
|
|
@@ -262,16 +264,15 @@ namespace Rays
|
|
|
262
264
|
}
|
|
263
265
|
|
|
264
266
|
static bool
|
|
265
|
-
calc_size (
|
|
266
|
-
coord* width, coord* height, HDC hdc, const char* str)
|
|
267
|
+
calc_size (coord* width, coord* height, HDC hdc, const wchar_t* str)
|
|
267
268
|
{
|
|
268
269
|
if (!width || !height || !hdc || !str) return false;
|
|
269
270
|
|
|
270
|
-
bool empty = *str == '\0';
|
|
271
|
-
if (empty) str = " ";
|
|
271
|
+
bool empty = *str == L'\0';
|
|
272
|
+
if (empty) str = L" ";
|
|
272
273
|
|
|
273
274
|
RECT rect = {0, 0, 0, 0};
|
|
274
|
-
int ret =
|
|
275
|
+
int ret = DrawTextW(
|
|
275
276
|
hdc, str, -1, &rect,
|
|
276
277
|
DT_EXPANDTABS | DT_NOPREFIX | DT_CALCRECT);
|
|
277
278
|
if (!ret) return false;
|
|
@@ -282,10 +283,16 @@ namespace Rays
|
|
|
282
283
|
}
|
|
283
284
|
|
|
284
285
|
bool
|
|
285
|
-
Font::get_extent (
|
|
286
|
-
|
|
286
|
+
Font::get_extent (coord* width, coord* height, const char* str, HDC hdc)
|
|
287
|
+
{
|
|
288
|
+
if (!str) return false;
|
|
289
|
+
return get_extent(width, height, String(str).to_wstr().c_str(), hdc);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
bool
|
|
293
|
+
Font::get_extent (coord* width, coord* height, const wchar_t* str, HDC hdc)
|
|
287
294
|
{
|
|
288
|
-
if (!*this || (!width && !height))
|
|
295
|
+
if (!*this || (!width && !height) || !str)
|
|
289
296
|
return false;
|
|
290
297
|
|
|
291
298
|
if (width) *width = 0;
|
|
@@ -312,12 +319,12 @@ namespace Rays
|
|
|
312
319
|
{
|
|
313
320
|
if (!*this) return "";
|
|
314
321
|
|
|
315
|
-
|
|
322
|
+
LOGFONTW logfont;
|
|
316
323
|
int size = sizeof(logfont);
|
|
317
|
-
if (
|
|
324
|
+
if (GetObjectW(self->handle.handle(), size, &logfont) != size)
|
|
318
325
|
return "";
|
|
319
326
|
|
|
320
|
-
return logfont.lfFaceName;
|
|
327
|
+
return String(logfont.lfFaceName, wcsnlen(logfont.lfFaceName, LF_FACESIZE));
|
|
321
328
|
}
|
|
322
329
|
|
|
323
330
|
coord
|
|
@@ -325,22 +332,12 @@ namespace Rays
|
|
|
325
332
|
{
|
|
326
333
|
if (!*this) return 0;
|
|
327
334
|
|
|
328
|
-
|
|
335
|
+
LOGFONTW logfont;
|
|
329
336
|
int size = sizeof(logfont);
|
|
330
|
-
if (
|
|
337
|
+
if (GetObjectW(self->handle.handle(), size, &logfont) != size)
|
|
331
338
|
return 0;
|
|
332
339
|
|
|
333
|
-
|
|
334
|
-
return logfont.lfHeight;
|
|
335
|
-
|
|
336
|
-
if (logfont.lfHeight < 0)
|
|
337
|
-
{
|
|
338
|
-
return -MulDiv(
|
|
339
|
-
logfont.lfHeight, 72,
|
|
340
|
-
GetDeviceCaps(screen_dc().handle(), LOGPIXELSY));
|
|
341
|
-
}
|
|
342
|
-
else
|
|
343
|
-
return logfont.lfHeight;
|
|
340
|
+
return logfont.lfHeight >= 0 ? logfont.lfHeight : -logfont.lfHeight;
|
|
344
341
|
}
|
|
345
342
|
|
|
346
343
|
HFONT
|
|
@@ -373,8 +370,8 @@ namespace Rays
|
|
|
373
370
|
static bool
|
|
374
371
|
load_bitmap (uint id, HINSTANCE hinst = NULL)
|
|
375
372
|
{
|
|
376
|
-
if (!hinst) hinst = (HINSTANCE)
|
|
377
|
-
self->handle.reset(
|
|
373
|
+
if (!hinst) hinst = (HINSTANCE) GetModuleHandleW(NULL);
|
|
374
|
+
self->handle.reset(LoadBitmapW(hinst, MAKEINTRESOURCEW(id)));
|
|
378
375
|
return !!self->handle;
|
|
379
376
|
}
|
|
380
377
|
#endif
|
|
@@ -398,7 +395,7 @@ namespace Rays
|
|
|
398
395
|
Bitmap::width () const
|
|
399
396
|
{
|
|
400
397
|
BITMAP bmp;
|
|
401
|
-
if (!*this || !
|
|
398
|
+
if (!*this || !GetObjectW(handle(), sizeof(bmp), &bmp))
|
|
402
399
|
return 0;
|
|
403
400
|
return bmp.bmWidth;
|
|
404
401
|
}
|
|
@@ -407,7 +404,7 @@ namespace Rays
|
|
|
407
404
|
Bitmap::height () const
|
|
408
405
|
{
|
|
409
406
|
BITMAP bmp;
|
|
410
|
-
if (!*this || !
|
|
407
|
+
if (!*this || !GetObjectW(handle(), sizeof(bmp), &bmp))
|
|
411
408
|
return 0;
|
|
412
409
|
return bmp.bmHeight;
|
|
413
410
|
}
|