Werner Lemberg pushed to branch wl/freetype-demos-support-ot-svg-glyphs-new at FreeType / FreeType Demo Programs
Commits:
-
acf418a6
by Alexei Podtelezhnikov at 2021-12-31T09:21:43-05:00
-
c8e4f6d4
by Alexei Podtelezhnikov at 2021-12-31T09:27:50-05:00
-
c51b0d31
by Alexei Podtelezhnikov at 2021-12-31T09:36:02-05:00
-
8d421a4c
by Alexei Podtelezhnikov at 2021-12-31T13:26:48-05:00
-
3445f436
by Alexei Podtelezhnikov at 2021-12-31T14:00:29-05:00
-
7706a595
by Alexei Podtelezhnikov at 2022-01-01T14:54:59-05:00
-
4484fd1b
by Werner Lemberg at 2022-01-07T06:40:22+01:00
-
7f36c5e4
by Werner Lemberg at 2022-01-07T06:40:22+01:00
-
1cb6e3d6
by Alexei Podtelezhnikov at 2022-01-08T09:41:55-05:00
-
15e03586
by Alexei Podtelezhnikov at 2022-01-08T21:52:20-05:00
-
f5868a5e
by Werner Lemberg at 2022-01-11T05:40:57+01:00
-
ad9c7166
by Moazin Khatti at 2022-01-11T09:53:50+01:00
-
8f964ca1
by Moazin Khatti at 2022-01-11T09:53:50+01:00
-
b4146f19
by Moazin Khatti at 2022-01-11T09:53:50+01:00
-
261ac1a8
by Moazin Khatti at 2022-01-11T09:53:50+01:00
-
36fde294
by Werner Lemberg at 2022-01-11T09:53:50+01:00
-
0f12ca8d
by Werner Lemberg at 2022-01-11T09:53:50+01:00
11 changed files:
- Makefile
- graph/gblblit.c
- graph/gblblit.h
- graph/gblender.h
- graph/grobjs.c
- graph/win32/grwin32.c
- src/ftcommon.c
- + src/rsvg-port.c
- + src/rsvg-port.h
- subprojects/libpng.wrap
- subprojects/zlib.wrap
Changes:
... | ... | @@ -125,6 +125,16 @@ else |
125 | 125 |
SRC_DIR := $(TOP_DIR_2)/src
|
126 | 126 |
endif
|
127 | 127 |
|
128 |
+ ifeq ($(PLATFORM),unixdev)
|
|
129 |
+ # `FT_DEMO_CFLAGS` comes from FreeType's `configure` script (via
|
|
130 |
+ # `builds/unix/unix-cc.mk`), holding additional flags to compile the
|
|
131 |
+ # FreeType demo programs.
|
|
132 |
+ #
|
|
133 |
+ # For the pure `make` call (without using `configure`) we have to add
|
|
134 |
+ # all needed cflags manually.
|
|
135 |
+ FT_DEMO_CFLAGS := $(shell pkg-config --cflags librsvg-2.0)
|
|
136 |
+ endif
|
|
137 |
+ |
|
128 | 138 |
FT_INCLUDES := $(OBJ_BUILD) \
|
129 | 139 |
$(DEVEL_DIR) \
|
130 | 140 |
$(TOP_DIR)/include \
|
... | ... | @@ -133,7 +143,8 @@ else |
133 | 143 |
COMPILE = $(CC) $(ANSIFLAGS) \
|
134 | 144 |
$(INCLUDES:%=$I%) \
|
135 | 145 |
$(CPPFLAGS) \
|
136 |
- $(CFLAGS)
|
|
146 |
+ $(CFLAGS) \
|
|
147 |
+ $(FT_DEMO_CFLAGS)
|
|
137 | 148 |
|
138 | 149 |
# Enable C99 for gcc to avoid warnings.
|
139 | 150 |
# Note that clang++ aborts with an error if we use `-std=C99',
|
... | ... | @@ -164,17 +175,27 @@ else |
164 | 175 |
LINK_ITEMS = $T$(subst /,$(COMPILER_SEP),$@ $<)
|
165 | 176 |
|
166 | 177 |
ifeq ($(PLATFORM),unix)
|
178 |
+ # `LDFLAGS` comes from the `configure` script (via FreeType's
|
|
179 |
+ # `builds/unix/unix-cc.mk`), holding all linker flags necessary to
|
|
180 |
+ # link the FreeType library.
|
|
181 |
+ #
|
|
182 |
+ # `FT_DEMO_LDFLAGS` has been set in `unix-cc.mk`, too.
|
|
167 | 183 |
override CC = $(CCraw)
|
168 | 184 |
LINK_CMD = $(LIBTOOL) --mode=link $(CC) \
|
169 | 185 |
$(subst /,$(COMPILER_SEP),$(LDFLAGS))
|
170 |
- LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) $(LIB_CLOCK_GETTIME)
|
|
186 |
+ LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) \
|
|
187 |
+ $(FT_DEMO_LDFLAGS)
|
|
171 | 188 |
else
|
172 | 189 |
LINK_CMD = $(CC) $(subst /,$(COMPILER_SEP),$(LDFLAGS))
|
173 | 190 |
ifeq ($(PLATFORM),unixdev)
|
174 |
- LINK_LIBS := $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) -lm -lrt -lz -lbz2 -lpthread
|
|
191 |
+ # For the pure `make` call (without using `configure`) we have to add
|
|
192 |
+ # all needed libraries manually.
|
|
193 |
+ LINK_LIBS := $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE)) \
|
|
194 |
+ -lm -lrt -lz -lbz2 -lpthread
|
|
175 | 195 |
LINK_LIBS += $(shell pkg-config --libs libpng)
|
176 | 196 |
LINK_LIBS += $(shell pkg-config --libs harfbuzz)
|
177 | 197 |
LINK_LIBS += $(shell pkg-config --libs libbrotlidec)
|
198 |
+ LINK_LIBS += $(shell pkg-config --libs librsvg-2.0)
|
|
178 | 199 |
else
|
179 | 200 |
LINK_LIBS = $(subst /,$(COMPILER_SEP),$(FTLIB) $(EFENCE))
|
180 | 201 |
endif
|
... | ... | @@ -349,6 +370,7 @@ else |
349 | 370 |
$(OBJ_DIR_2)/mlgetopt.$(SO): $(SRC_DIR)/mlgetopt.c
|
350 | 371 |
COMMON_OBJ := $(OBJ_DIR_2)/common.$(SO) \
|
351 | 372 |
$(OBJ_DIR_2)/strbuf.$(SO) \
|
373 |
+ $(OBJ_DIR_2)/rsvg-port.$(SO) \
|
|
352 | 374 |
$(OBJ_DIR_2)/output.$(SO) \
|
353 | 375 |
$(OBJ_DIR_2)/md5.$(SO) \
|
354 | 376 |
$(OBJ_DIR_2)/mlgetopt.$(SO)
|
... | ... | @@ -361,6 +383,9 @@ else |
361 | 383 |
$(COMPILE) $(GRAPH_INCLUDES:%=$I%) \
|
362 | 384 |
$T$(subst /,$(COMPILER_SEP),$@ $<)
|
363 | 385 |
|
386 |
+ $(OBJ_DIR_2)/rsvg-port.$(SO): $(SRC_DIR)/rsvg-port.c $(SRC_DIR)/rsvg-port.h
|
|
387 |
+ $(COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
|
|
388 |
+ |
|
364 | 389 |
FTCOMMON_OBJ := $(OBJ_DIR_2)/ftcommon.$(SO) \
|
365 | 390 |
$(OBJ_DIR_2)/ftpngout.$(SO)
|
366 | 391 |
|
... | ... | @@ -237,17 +237,6 @@ |
237 | 237 |
|
238 | 238 |
/* */
|
239 | 239 |
|
240 |
-static const GBlenderBlitFunc*
|
|
241 |
-blit_funcs[GBLENDER_TARGET_MAX] =
|
|
242 |
-{
|
|
243 |
- blit_funcs_gray8,
|
|
244 |
- blit_funcs_rgb32,
|
|
245 |
- blit_funcs_rgb24,
|
|
246 |
- blit_funcs_rgb565,
|
|
247 |
- blit_funcs_rgb555
|
|
248 |
-};
|
|
249 |
- |
|
250 |
- |
|
251 | 240 |
static int
|
252 | 241 |
gblender_blit_init( GBlenderBlit blit,
|
253 | 242 |
int dst_x,
|
... | ... | @@ -263,14 +252,13 @@ gblender_blit_init( GBlenderBlit blit, |
263 | 252 |
|
264 | 253 |
GBlenderSourceFormat src_format;
|
265 | 254 |
const unsigned char* src_buffer = glyph->buffer;
|
266 |
- int src_pitch = glyph->pitch;
|
|
255 |
+ const int src_pitch = glyph->pitch;
|
|
267 | 256 |
int src_width = glyph->width;
|
268 | 257 |
int src_height = glyph->rows;
|
269 |
- GBlenderTargetFormat dst_format;
|
|
270 | 258 |
unsigned char* dst_buffer = target->buffer;
|
271 |
- int dst_pitch = target->pitch;
|
|
272 |
- int dst_width = target->width;
|
|
273 |
- int dst_height = target->rows;
|
|
259 |
+ const int dst_pitch = target->pitch;
|
|
260 |
+ const int dst_width = target->width;
|
|
261 |
+ const int dst_height = target->rows;
|
|
274 | 262 |
|
275 | 263 |
|
276 | 264 |
switch ( glyph->mode )
|
... | ... | @@ -305,18 +293,27 @@ gblender_blit_init( GBlenderBlit blit, |
305 | 293 |
|
306 | 294 |
switch ( target->mode )
|
307 | 295 |
{
|
308 |
- case gr_pixel_mode_gray: dst_format = GBLENDER_TARGET_GRAY8; break;
|
|
309 |
- case gr_pixel_mode_rgb32: dst_format = GBLENDER_TARGET_RGB32; break;
|
|
310 |
- case gr_pixel_mode_rgb24: dst_format = GBLENDER_TARGET_RGB24; break;
|
|
311 |
- case gr_pixel_mode_rgb565: dst_format = GBLENDER_TARGET_RGB565; break;
|
|
312 |
- case gr_pixel_mode_rgb555: dst_format = GBLENDER_TARGET_RGB555; break;
|
|
296 |
+ case gr_pixel_mode_gray:
|
|
297 |
+ blit->blit_func = blit_funcs_gray8[src_format];
|
|
298 |
+ break;
|
|
299 |
+ case gr_pixel_mode_rgb32:
|
|
300 |
+ blit->blit_func = blit_funcs_rgb32[src_format];
|
|
301 |
+ break;
|
|
302 |
+ case gr_pixel_mode_rgb24:
|
|
303 |
+ blit->blit_func = blit_funcs_rgb24[src_format];
|
|
304 |
+ break;
|
|
305 |
+ case gr_pixel_mode_rgb565:
|
|
306 |
+ blit->blit_func = blit_funcs_rgb565[src_format];
|
|
307 |
+ break;
|
|
308 |
+ case gr_pixel_mode_rgb555:
|
|
309 |
+ blit->blit_func = blit_funcs_rgb555[src_format];
|
|
310 |
+ break;
|
|
313 | 311 |
default:
|
314 | 312 |
grError = gr_err_bad_target_depth;
|
315 | 313 |
return -2;
|
316 | 314 |
}
|
317 | 315 |
|
318 | 316 |
blit->blender = surface->gblender;
|
319 |
- blit->blit_func = blit_funcs[dst_format][src_format];
|
|
320 | 317 |
|
321 | 318 |
if ( dst_x < 0 )
|
322 | 319 |
{
|
... | ... | @@ -345,24 +342,20 @@ gblender_blit_init( GBlenderBlit blit, |
345 | 342 |
if ( src_width <= 0 || src_height <= 0 )
|
346 | 343 |
return -1;
|
347 | 344 |
|
348 |
- blit->width = src_width;
|
|
349 |
- blit->height = src_height;
|
|
350 |
- blit->src_format = src_format;
|
|
351 |
- blit->dst_format = dst_format;
|
|
345 |
+ blit->width = src_width;
|
|
346 |
+ blit->height = src_height;
|
|
352 | 347 |
|
353 |
- blit->src_x = src_x;
|
|
354 |
- blit->src_y = src_y;
|
|
355 |
- blit->src_line = src_buffer + src_pitch*src_y;
|
|
356 | 348 |
blit->src_pitch = src_pitch;
|
357 | 349 |
if ( src_pitch < 0 )
|
358 |
- blit->src_line -= (src_height-1)*src_pitch;
|
|
350 |
+ src_y -= glyph->rows - 1;
|
|
351 |
+ blit->src_line = src_buffer + src_pitch * src_y;
|
|
352 |
+ blit->src_x = src_x;
|
|
359 | 353 |
|
360 |
- blit->dst_x = dst_x;
|
|
361 |
- blit->dst_y = dst_y;
|
|
362 |
- blit->dst_line = dst_buffer + dst_pitch*dst_y;
|
|
363 | 354 |
blit->dst_pitch = dst_pitch;
|
364 | 355 |
if ( dst_pitch < 0 )
|
365 |
- blit->dst_line -= (dst_height-1)*dst_pitch;
|
|
356 |
+ dst_y -= dst_height - 1;
|
|
357 |
+ blit->dst_line = dst_buffer + dst_pitch * dst_y;
|
|
358 |
+ blit->dst_x = dst_x;
|
|
366 | 359 |
|
367 | 360 |
return 0;
|
368 | 361 |
}
|
... | ... | @@ -48,13 +48,9 @@ typedef struct GBlenderBlitRec_ |
48 | 48 |
const unsigned char* src_line;
|
49 | 49 |
int src_pitch;
|
50 | 50 |
int src_x;
|
51 |
- int src_y;
|
|
52 | 51 |
unsigned char* dst_line;
|
53 | 52 |
int dst_pitch;
|
54 | 53 |
int dst_x;
|
55 |
- int dst_y;
|
|
56 |
- GBlenderSourceFormat src_format;
|
|
57 |
- GBlenderTargetFormat dst_format;
|
|
58 | 54 |
|
59 | 55 |
GBlender blender;
|
60 | 56 |
GBlenderBlitFunc blit_func;
|
... | ... | @@ -145,7 +145,7 @@ |
145 | 145 |
GBLENDER_API( void )
|
146 | 146 |
gblender_dump_stats( GBlender blender );
|
147 | 147 |
#else
|
148 |
-# define gblender_dump_stats(b) do { } while (0);
|
|
148 |
+# define gblender_dump_stats(b) do { } while (0)
|
|
149 | 149 |
#endif
|
150 | 150 |
|
151 | 151 |
#ifdef GBLENDER_STATS
|
... | ... | @@ -14,31 +14,32 @@ |
14 | 14 |
{
|
15 | 15 |
grColor color;
|
16 | 16 |
|
17 |
+ |
|
17 | 18 |
color.value = 0;
|
18 | 19 |
|
19 |
- switch (target->mode)
|
|
20 |
+ switch ( target->mode )
|
|
20 | 21 |
{
|
21 | 22 |
case gr_pixel_mode_mono:
|
22 |
- if ( (red|green|blue) )
|
|
23 |
+ if ( ( red | green | blue ) )
|
|
23 | 24 |
color.value = 1;
|
24 | 25 |
break;
|
25 | 26 |
|
26 | 27 |
case gr_pixel_mode_gray:
|
27 |
- color.value = ( 3*(red & 0xFF) +
|
|
28 |
- 6*(green & 0xFF) +
|
|
29 |
- (blue & 0xFF) ) / 10;
|
|
28 |
+ color.value = ( 3 * ( red & 0xFF ) +
|
|
29 |
+ 6 * ( green & 0xFF ) +
|
|
30 |
+ ( blue & 0xFF ) ) / 10;
|
|
30 | 31 |
break;
|
31 | 32 |
|
32 | 33 |
case gr_pixel_mode_rgb555:
|
33 |
- color.value = (uint32_t)( ( red & 0xF8 ) << 7 ) |
|
|
34 |
- (uint32_t)( ( green & 0xF8 ) << 2 ) |
|
|
35 |
- (uint32_t)( ( blue & 0xF8 ) >> 3 );
|
|
34 |
+ color.value = ( ( (uint32_t)red & 0xF8 ) << 7 ) |
|
|
35 |
+ ( ( (uint32_t)green & 0xF8 ) << 2 ) |
|
|
36 |
+ ( ( (uint32_t)blue & 0xF8 ) >> 3 );
|
|
36 | 37 |
break;
|
37 | 38 |
|
38 | 39 |
case gr_pixel_mode_rgb565:
|
39 |
- color.value = (uint32_t)( ( red & 0xF8 ) << 8 ) |
|
|
40 |
- (uint32_t)( ( green & 0xFC ) << 3 ) |
|
|
41 |
- (uint32_t)( ( blue & 0xF8 ) >> 3 );
|
|
40 |
+ color.value = ( ( (uint32_t)red & 0xF8 ) << 8 ) |
|
|
41 |
+ ( ( (uint32_t)green & 0xFC ) << 3 ) |
|
|
42 |
+ ( ( (uint32_t)blue & 0xF8 ) >> 3 );
|
|
42 | 43 |
break;
|
43 | 44 |
|
44 | 45 |
case gr_pixel_mode_rgb24:
|
... | ... | @@ -48,15 +49,16 @@ |
48 | 49 |
break;
|
49 | 50 |
|
50 | 51 |
case gr_pixel_mode_rgb32:
|
51 |
- color.value = (uint32_t)( ( alpha & 0xFF ) << 24 ) |
|
|
52 |
- (uint32_t)( ( red & 0xFF ) << 16 ) |
|
|
53 |
- (uint32_t)( ( green & 0xFF ) << 8 ) |
|
|
54 |
- (uint32_t)( ( blue & 0xFF ) );
|
|
52 |
+ color.value = ( ( (uint32_t)alpha & 0xFF ) << 24 ) |
|
|
53 |
+ ( ( (uint32_t)red & 0xFF ) << 16 ) |
|
|
54 |
+ ( ( (uint32_t)green & 0xFF ) << 8 ) |
|
|
55 |
+ ( ( (uint32_t)blue & 0xFF ) );
|
|
55 | 56 |
break;
|
56 | 57 |
|
57 | 58 |
default:
|
58 | 59 |
;
|
59 | 60 |
}
|
61 |
+ |
|
60 | 62 |
return color;
|
61 | 63 |
}
|
62 | 64 |
|
... | ... | @@ -57,6 +57,7 @@ |
57 | 57 |
#endif
|
58 | 58 |
|
59 | 59 |
/* Custom messages. */
|
60 |
+#define WM_STATUS WM_USER+512
|
|
60 | 61 |
#define WM_RESIZE WM_USER+517
|
61 | 62 |
|
62 | 63 |
|
... | ... | @@ -99,6 +100,7 @@ |
99 | 100 |
typedef struct grWin32SurfaceRec_
|
100 | 101 |
{
|
101 | 102 |
grSurface root;
|
103 |
+ DWORD host;
|
|
102 | 104 |
HWND window;
|
103 | 105 |
HICON sIcon;
|
104 | 106 |
HICON bIcon;
|
... | ... | @@ -148,7 +150,7 @@ gr_win32_surface_refresh_rectangle( |
148 | 150 |
grBitmap* bitmap = &surface->root.bitmap;
|
149 | 151 |
|
150 | 152 |
LOG(( "gr_win32_surface_refresh_rectangle: ( %p, %d, %d, %d, %d )\n",
|
151 |
- (long)surface, x, y, w, h ));
|
|
153 |
+ surface->root.bitmap.buffer, x, y, w, h ));
|
|
152 | 154 |
|
153 | 155 |
/* clip update rectangle */
|
154 | 156 |
|
... | ... | @@ -305,8 +307,6 @@ gr_win32_surface_set_icon( grWin32Surface* surface, |
305 | 307 |
return 0;
|
306 | 308 |
case ICON_BIG:
|
307 | 309 |
surface->bIcon = hIcon;
|
308 |
- SetClassLongPtr( surface->window, GCLP_HBRBACKGROUND,
|
|
309 |
- (LONG_PTR)CreatePatternBrush( ici.hbmColor ) );
|
|
310 | 310 |
return s[0];
|
311 | 311 |
default:
|
312 | 312 |
return 0; /* should not happen */
|
... | ... | @@ -373,11 +373,14 @@ gr_win32_surface_listen_event( grWin32Surface* surface, |
373 | 373 |
|
374 | 374 |
event_mask=event_mask; /* unused parameter */
|
375 | 375 |
|
376 |
- while ( GetMessage( &msg, NULL, 0, 0 ) > 0 )
|
|
376 |
+ while ( GetMessage( &msg, (HWND)-1, 0, 0 ) > 0 )
|
|
377 | 377 |
{
|
378 | 378 |
switch ( msg.message )
|
379 | 379 |
{
|
380 | 380 |
case WM_RESIZE:
|
381 |
+ while( PeekMessage( &msg, (HWND)-1, WM_RESIZE, WM_RESIZE, PM_REMOVE ) )
|
|
382 |
+ continue;
|
|
383 |
+ |
|
381 | 384 |
{
|
382 | 385 |
int width = LOWORD(msg.lParam);
|
383 | 386 |
int height = HIWORD(msg.lParam);
|
... | ... | @@ -423,16 +426,63 @@ gr_win32_surface_listen_event( grWin32Surface* surface, |
423 | 426 |
}
|
424 | 427 |
break;
|
425 | 428 |
}
|
429 |
+ }
|
|
430 |
+}
|
|
431 |
+ |
|
426 | 432 |
|
433 |
+DWORD WINAPI Window_ThreadProc( LPVOID lpParameter )
|
|
434 |
+{
|
|
435 |
+ grWin32Surface* surface = (grWin32Surface*)lpParameter;
|
|
436 |
+ DWORD style = WS_OVERLAPPEDWINDOW;
|
|
437 |
+ RECT WndRect;
|
|
438 |
+ MSG msg;
|
|
439 |
+ |
|
440 |
+ WndRect.left = 0;
|
|
441 |
+ WndRect.top = 0;
|
|
442 |
+ WndRect.right = surface->root.bitmap.width;
|
|
443 |
+ WndRect.bottom = surface->root.bitmap.rows;
|
|
444 |
+ |
|
445 |
+ AdjustWindowRect( &WndRect, style, FALSE );
|
|
446 |
+ |
|
447 |
+ surface->window = CreateWindow(
|
|
448 |
+ /* LPCSTR lpszClassName; */ "FreeTypeTestGraphicDriver",
|
|
449 |
+ /* LPCSTR lpszWindowName; */ "FreeType Test Graphic Driver",
|
|
450 |
+ /* DWORD dwStyle; */ style,
|
|
451 |
+ /* int x; */ CW_USEDEFAULT,
|
|
452 |
+ /* int y; */ CW_USEDEFAULT,
|
|
453 |
+ /* int nWidth; */ WndRect.right - WndRect.left,
|
|
454 |
+ /* int nHeight; */ WndRect.bottom - WndRect.top,
|
|
455 |
+ /* HWND hwndParent; */ HWND_DESKTOP,
|
|
456 |
+ /* HMENU hmenu; */ 0,
|
|
457 |
+ /* HINSTANCE hinst; */ GetModuleHandle( NULL ),
|
|
458 |
+ /* void FAR* lpvParam; */ surface );
|
|
459 |
+ |
|
460 |
+ PostThreadMessage( surface->host, WM_STATUS, (WPARAM)surface->window, 0 );
|
|
461 |
+ |
|
462 |
+ if ( surface->window == 0 )
|
|
463 |
+ return -1;
|
|
464 |
+ |
|
465 |
+ ShowWindow( surface->window, SW_SHOWNORMAL );
|
|
466 |
+ |
|
467 |
+ while ( GetMessage( &msg, surface->window, 0, 0 ) > 0 )
|
|
468 |
+ {
|
|
427 | 469 |
TranslateMessage( &msg );
|
428 | 470 |
DispatchMessage( &msg );
|
429 | 471 |
}
|
472 |
+ |
|
473 |
+ LOG(("Window thread done.\n"));
|
|
474 |
+ return 0;
|
|
430 | 475 |
}
|
431 | 476 |
|
477 |
+ |
|
432 | 478 |
static grWin32Surface*
|
433 | 479 |
gr_win32_surface_init( grWin32Surface* surface,
|
434 | 480 |
grBitmap* bitmap )
|
435 | 481 |
{
|
482 |
+ MSG msg;
|
|
483 |
+ |
|
484 |
+ surface->root.bitmap.grays = bitmap->grays;
|
|
485 |
+ |
|
436 | 486 |
/* Set default mode */
|
437 | 487 |
if ( bitmap->mode == gr_pixel_mode_none )
|
438 | 488 |
{
|
... | ... | @@ -446,64 +496,29 @@ gr_win32_surface_init( grWin32Surface* surface, |
446 | 496 |
switch ( bpp )
|
447 | 497 |
{
|
448 | 498 |
case 8:
|
449 |
- bitmap->mode = gr_pixel_mode_gray;
|
|
499 |
+ surface->root.bitmap.mode = gr_pixel_mode_gray;
|
|
450 | 500 |
break;
|
451 | 501 |
case 16:
|
452 |
- bitmap->mode = gr_pixel_mode_rgb565;
|
|
502 |
+ surface->root.bitmap.mode = gr_pixel_mode_rgb565;
|
|
453 | 503 |
break;
|
454 | 504 |
case 24:
|
455 |
- bitmap->mode = gr_pixel_mode_rgb24;
|
|
505 |
+ surface->root.bitmap.mode = gr_pixel_mode_rgb24;
|
|
456 | 506 |
break;
|
457 | 507 |
case 32:
|
458 | 508 |
default:
|
459 |
- bitmap->mode = gr_pixel_mode_rgb32;
|
|
509 |
+ surface->root.bitmap.mode = gr_pixel_mode_rgb32;
|
|
460 | 510 |
}
|
461 | 511 |
}
|
512 |
+ else
|
|
513 |
+ surface->root.bitmap.mode = bitmap->mode;
|
|
462 | 514 |
|
463 |
- LOG(( "Win32: init_surface( %p, %p )\n", surface, bitmap ));
|
|
464 |
- |
|
465 |
- LOG(( " -- mode = %d\n", bitmap->mode ));
|
|
466 |
- LOG(( " -- grays = %d\n", bitmap->grays ));
|
|
467 |
- LOG(( " -- width = %d\n", bitmap->width ));
|
|
468 |
- LOG(( " -- height = %d\n", bitmap->rows ));
|
|
469 |
- |
|
470 |
- /* create the bitmap - under Win32, we support all modes as the GDI */
|
|
471 |
- /* handles all conversions automatically.. */
|
|
472 |
- if ( grNewBitmap( bitmap->mode,
|
|
473 |
- bitmap->grays,
|
|
474 |
- bitmap->width,
|
|
475 |
- bitmap->rows,
|
|
476 |
- bitmap ) )
|
|
515 |
+ if ( !gr_win32_surface_resize( surface, bitmap->width, bitmap->rows ) )
|
|
477 | 516 |
return 0;
|
478 | 517 |
|
479 |
- /* allocate the BGR shadow bitmap */
|
|
480 |
- if ( bitmap->mode == gr_pixel_mode_rgb24 )
|
|
481 |
- {
|
|
482 |
- if ( grNewBitmap( bitmap->mode,
|
|
483 |
- bitmap->grays,
|
|
484 |
- bitmap->width,
|
|
485 |
- bitmap->rows,
|
|
486 |
- &surface->shadow_bitmap ) )
|
|
487 |
- return 0;
|
|
488 |
- |
|
489 |
-#ifdef SWIZZLE
|
|
490 |
- if ( grNewBitmap( bitmap->mode,
|
|
491 |
- bitmap->grays,
|
|
492 |
- bitmap->width,
|
|
493 |
- bitmap->rows,
|
|
494 |
- &surface->swizzle_bitmap ) )
|
|
495 |
- return 0;
|
|
496 |
-#endif
|
|
497 |
- }
|
|
498 |
- else
|
|
499 |
- surface->shadow_bitmap.buffer = bitmap->buffer;
|
|
500 |
- |
|
501 | 518 |
surface->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
|
502 |
- surface->bmiHeader.biWidth = bitmap->width;
|
|
503 |
- surface->bmiHeader.biHeight = -bitmap->rows;
|
|
504 | 519 |
surface->bmiHeader.biPlanes = 1;
|
505 | 520 |
|
506 |
- switch ( bitmap->mode )
|
|
521 |
+ switch ( surface->root.bitmap.mode )
|
|
507 | 522 |
{
|
508 | 523 |
case gr_pixel_mode_mono:
|
509 | 524 |
surface->bmiHeader.biBitCount = 1;
|
... | ... | @@ -565,43 +580,28 @@ gr_win32_surface_init( grWin32Surface* surface, |
565 | 580 |
return 0; /* Unknown mode */
|
566 | 581 |
}
|
567 | 582 |
|
568 |
- {
|
|
569 |
- DWORD style = WS_OVERLAPPEDWINDOW;
|
|
570 |
- RECT WndRect;
|
|
571 |
- |
|
572 |
- WndRect.left = 0;
|
|
573 |
- WndRect.top = 0;
|
|
574 |
- WndRect.right = bitmap->width;
|
|
575 |
- WndRect.bottom = bitmap->rows;
|
|
576 |
- |
|
577 |
- AdjustWindowRect( &WndRect, style, FALSE );
|
|
578 |
- |
|
579 |
- surface->window = CreateWindow(
|
|
580 |
- /* LPCSTR lpszClassName; */ "FreeTypeTestGraphicDriver",
|
|
581 |
- /* LPCSTR lpszWindowName; */ "FreeType Test Graphic Driver",
|
|
582 |
- /* DWORD dwStyle; */ style,
|
|
583 |
- /* int x; */ CW_USEDEFAULT,
|
|
584 |
- /* int y; */ CW_USEDEFAULT,
|
|
585 |
- /* int nWidth; */ WndRect.right - WndRect.left,
|
|
586 |
- /* int nHeight; */ WndRect.bottom - WndRect.top,
|
|
587 |
- /* HWND hwndParent; */ HWND_DESKTOP,
|
|
588 |
- /* HMENU hmenu; */ 0,
|
|
589 |
- /* HINSTANCE hinst; */ GetModuleHandle( NULL ),
|
|
590 |
- /* void FAR* lpvParam; */ surface );
|
|
591 |
- }
|
|
583 |
+ /* set up the main message queue and spin off the window thread */
|
|
584 |
+ PeekMessage( &msg, (HWND)-1, WM_USER, WM_USER, PM_NOREMOVE );
|
|
585 |
+ surface->host = GetCurrentThreadId();
|
|
592 | 586 |
|
593 |
- if ( surface->window == 0 )
|
|
594 |
- return 0;
|
|
587 |
+ CreateThread( NULL, 0, Window_ThreadProc, (LPVOID)surface, 0, NULL );
|
|
595 | 588 |
|
596 |
- ShowWindow( surface->window, SW_SHOWNORMAL );
|
|
589 |
+ /* listen if window is created */
|
|
590 |
+ if ( GetMessage ( &msg, (HWND)-1, WM_STATUS, WM_STATUS ) < 0 ||
|
|
591 |
+ !msg.wParam )
|
|
592 |
+ return 0;
|
|
597 | 593 |
|
598 |
- surface->root.bitmap = *bitmap;
|
|
594 |
+ /* wrap up */
|
|
599 | 595 |
surface->root.done = (grDoneSurfaceFunc) gr_win32_surface_done;
|
600 | 596 |
surface->root.refresh_rect = (grRefreshRectFunc) gr_win32_surface_refresh_rectangle;
|
601 | 597 |
surface->root.set_title = (grSetTitleFunc) gr_win32_surface_set_title;
|
602 | 598 |
surface->root.set_icon = (grSetIconFunc) gr_win32_surface_set_icon;
|
603 | 599 |
surface->root.listen_event = (grListenEventFunc) gr_win32_surface_listen_event;
|
604 | 600 |
|
601 |
+ LOG(( "Surface initialized: %dx%dx%d\n",
|
|
602 |
+ surface->root.bitmap.width, surface->root.bitmap.rows,
|
|
603 |
+ surface->bmiHeader.biBitCount ));
|
|
604 |
+ |
|
605 | 605 |
return surface;
|
606 | 606 |
}
|
607 | 607 |
|
... | ... | @@ -637,15 +637,14 @@ LRESULT CALLBACK Message_Process( HWND handle, UINT mess, |
637 | 637 |
{
|
638 | 638 |
case WM_CLOSE:
|
639 | 639 |
/* warn the main thread to quit if it didn't know */
|
640 |
- PostMessage( handle, WM_CHAR, (WPARAM)grKeyEsc, 0 );
|
|
640 |
+ PostThreadMessage( surface->host, WM_CHAR, (WPARAM)grKeyEsc, 0 );
|
|
641 | 641 |
break;
|
642 | 642 |
|
643 | 643 |
case WM_SIZE:
|
644 | 644 |
if ( wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED )
|
645 |
- PostMessage( handle, WM_RESIZE, wParam, lParam );
|
|
645 |
+ PostThreadMessage( surface->host, WM_RESIZE, wParam, lParam );
|
|
646 | 646 |
break;
|
647 | 647 |
|
648 |
-#ifdef DEBUG
|
|
649 | 648 |
case WM_SIZING:
|
650 | 649 |
{
|
651 | 650 |
PRECT r = (PRECT)lParam;
|
... | ... | @@ -664,27 +663,34 @@ LRESULT CALLBACK Message_Process( HWND handle, UINT mess, |
664 | 663 |
y, x, r->left, r->top, r->right, r->bottom,
|
665 | 664 |
WndRect.right, WndRect.bottom ));
|
666 | 665 |
|
667 |
- /* XXX: We cannot simply interrupt here and resize the image. */
|
|
666 |
+ PostThreadMessage( surface->host, WM_RESIZE, SIZE_RESTORED,
|
|
667 |
+ MAKELPARAM( WndRect.right, WndRect.bottom ) );
|
|
668 | 668 |
}
|
669 | 669 |
break;
|
670 |
-#endif
|
|
671 | 670 |
|
672 | 671 |
case WM_EXITSIZEMOVE:
|
673 | 672 |
{
|
674 | 673 |
RECT WndRect;
|
675 | 674 |
|
676 | 675 |
GetClientRect( handle, &WndRect );
|
677 |
- PostMessage( handle, WM_RESIZE, SIZE_RESTORED,
|
|
678 |
- MAKELPARAM( WndRect.right, WndRect.bottom ) );
|
|
676 |
+ PostThreadMessage( surface->host, WM_RESIZE, SIZE_RESTORED,
|
|
677 |
+ MAKELPARAM( WndRect.right, WndRect.bottom ) );
|
|
679 | 678 |
}
|
680 | 679 |
break;
|
681 | 680 |
|
681 |
+ case WM_KEYDOWN:
|
|
682 |
+ case WM_SYSKEYDOWN:
|
|
683 |
+ case WM_CHAR:
|
|
684 |
+ /* repost to the main thread */
|
|
685 |
+ PostThreadMessage( surface->host, mess, wParam, lParam );
|
|
686 |
+ break;
|
|
687 |
+ |
|
682 | 688 |
case WM_PAINT:
|
683 | 689 |
{
|
684 |
- HDC hDC;
|
|
685 |
- PAINTSTRUCT ps;
|
|
690 |
+ HDC hDC;
|
|
691 |
+ PAINTSTRUCT ps;
|
|
686 | 692 |
|
687 |
- hDC = BeginPaint ( handle, &ps );
|
|
693 |
+ hDC = BeginPaint ( handle, &ps );
|
|
688 | 694 |
SetDIBitsToDevice( hDC, 0, 0,
|
689 | 695 |
surface->root.bitmap.width,
|
690 | 696 |
surface->root.bitmap.rows,
|
... | ... | @@ -27,6 +27,8 @@ |
27 | 27 |
|
28 | 28 |
#include FT_BITMAP_H
|
29 | 29 |
#include FT_FONT_FORMATS_H
|
30 |
+#include FT_OTSVG_H
|
|
31 |
+ |
|
30 | 32 |
|
31 | 33 |
/* error messages */
|
32 | 34 |
#undef FTERRORS_H_
|
... | ... | @@ -37,6 +39,7 @@ |
37 | 39 |
#include "common.h"
|
38 | 40 |
#include "strbuf.h"
|
39 | 41 |
#include "ftcommon.h"
|
42 |
+#include "rsvg-port.h"
|
|
40 | 43 |
|
41 | 44 |
#include <stdio.h>
|
42 | 45 |
#include <stdlib.h>
|
... | ... | @@ -337,6 +340,12 @@ |
337 | 340 |
{
|
338 | 341 |
FTDemo_Handle* handle;
|
339 | 342 |
|
343 |
+ SVG_RendererHooks hooks = {
|
|
344 |
+ (SVG_Lib_Init_Func)rsvg_port_init,
|
|
345 |
+ (SVG_Lib_Free_Func)rsvg_port_free,
|
|
346 |
+ (SVG_Lib_Render_Func)rsvg_port_render,
|
|
347 |
+ (SVG_Lib_Preset_Slot_Func)rsvg_port_preset_slot };
|
|
348 |
+ |
|
340 | 349 |
|
341 | 350 |
handle = (FTDemo_Handle *)malloc( sizeof ( FTDemo_Handle ) );
|
342 | 351 |
if ( !handle )
|
... | ... | @@ -348,6 +357,9 @@ |
348 | 357 |
if ( error )
|
349 | 358 |
PanicZ( "could not initialize FreeType" );
|
350 | 359 |
|
360 |
+ /* XXX error handling? */
|
|
361 |
+ FT_Property_Set( handle->library, "ot-svg", "svg_hooks", &hooks );
|
|
362 |
+ |
|
351 | 363 |
error = FTC_Manager_New( handle->library, 0, 0, 0,
|
352 | 364 |
my_face_requester, 0, &handle->cache_manager );
|
353 | 365 |
if ( error )
|
... | ... | @@ -424,6 +436,8 @@ |
424 | 436 |
FT_Done_FreeType( handle->library );
|
425 | 437 |
|
426 | 438 |
free( handle );
|
439 |
+ |
|
440 |
+ fflush( stdout ); /* clean mintty pipes */
|
|
427 | 441 |
}
|
428 | 442 |
|
429 | 443 |
|
... | ... | @@ -466,7 +480,7 @@ |
466 | 480 |
|
467 | 481 |
for ( ; count--; spans++ )
|
468 | 482 |
for ( dst = dst_line + spans->x, w = spans->len; w--; dst++ )
|
469 |
- *dst = (FT_UInt32)( spans->coverage << 24 ) | color;
|
|
483 |
+ *dst = ( (FT_UInt32)spans->coverage << 24 ) | color;
|
|
470 | 484 |
}
|
471 | 485 |
|
472 | 486 |
|
... | ... | @@ -1331,7 +1345,8 @@ |
1331 | 1345 |
|
1332 | 1346 |
error = FT_Err_Ok;
|
1333 | 1347 |
|
1334 |
- if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE )
|
|
1348 |
+ if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE ||
|
|
1349 |
+ glyf->format == FT_GLYPH_FORMAT_SVG )
|
|
1335 | 1350 |
{
|
1336 | 1351 |
FT_Render_Mode render_mode;
|
1337 | 1352 |
|
1 |
+/****************************************************************************
|
|
2 |
+ *
|
|
3 |
+ * rsvg-port.c
|
|
4 |
+ *
|
|
5 |
+ * Librsvg-based hook functions for OT-SVG rendering in FreeType
|
|
6 |
+ * (implementation).
|
|
7 |
+ *
|
|
8 |
+ * Copyright (C) 2021 by
|
|
9 |
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
|
|
10 |
+ *
|
|
11 |
+ * This file is part of the FreeType project, and may only be used,
|
|
12 |
+ * modified, and distributed under the terms of the FreeType project
|
|
13 |
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
|
|
14 |
+ * this file you indicate that you have read the license and
|
|
15 |
+ * understand and accept it fully.
|
|
16 |
+ *
|
|
17 |
+ */
|
|
18 |
+ |
|
19 |
+#include <cairo.h>
|
|
20 |
+#include <librsvg/rsvg.h>
|
|
21 |
+#include <stdlib.h>
|
|
22 |
+#include <math.h>
|
|
23 |
+ |
|
24 |
+#include <ft2build.h>
|
|
25 |
+#include <freetype/freetype.h>
|
|
26 |
+#include <freetype/ftbbox.h>
|
|
27 |
+#include <freetype/otsvg.h>
|
|
28 |
+ |
|
29 |
+#include "rsvg-port.h"
|
|
30 |
+ |
|
31 |
+ |
|
32 |
+ /*
|
|
33 |
+ * The init hook is called when the first OT-SVG glyph is rendered. All
|
|
34 |
+ * we do is to allocate an internal state structure and set the pointer in
|
|
35 |
+ * `library->svg_renderer_state`. This state structure becomes very
|
|
36 |
+ * useful to cache some of the results obtained by one hook function that
|
|
37 |
+ * the other one might use.
|
|
38 |
+ */
|
|
39 |
+ FT_Error
|
|
40 |
+ rsvg_port_init( FT_Pointer *state )
|
|
41 |
+ {
|
|
42 |
+ /* allocate the memory upon initialization */
|
|
43 |
+ *state = malloc( sizeof( Rsvg_Port_StateRec ) ); /* XXX error handling */
|
|
44 |
+ |
|
45 |
+ return FT_Err_Ok;
|
|
46 |
+ }
|
|
47 |
+ |
|
48 |
+ |
|
49 |
+ /*
|
|
50 |
+ * Deallocate the state structure.
|
|
51 |
+ */
|
|
52 |
+ void
|
|
53 |
+ rsvg_port_free( FT_Pointer *state )
|
|
54 |
+ {
|
|
55 |
+ free( *state );
|
|
56 |
+ }
|
|
57 |
+ |
|
58 |
+ |
|
59 |
+ /*
|
|
60 |
+ * The render hook. The job of this hook is to simply render the glyph in
|
|
61 |
+ * the buffer that has been allocated on the FreeType side. Here we
|
|
62 |
+ * simply use the recording surface by playing it back against the
|
|
63 |
+ * surface.
|
|
64 |
+ */
|
|
65 |
+ FT_Error
|
|
66 |
+ rsvg_port_render( FT_GlyphSlot slot,
|
|
67 |
+ FT_Pointer *_state )
|
|
68 |
+ {
|
|
69 |
+ FT_Error error = FT_Err_Ok;
|
|
70 |
+ |
|
71 |
+ Rsvg_Port_State state;
|
|
72 |
+ cairo_status_t status;
|
|
73 |
+ cairo_t *cr;
|
|
74 |
+ cairo_surface_t *surface;
|
|
75 |
+ |
|
76 |
+ |
|
77 |
+ state = *(Rsvg_Port_State*)_state;
|
|
78 |
+ |
|
79 |
+ /* Create an image surface to store the rendered image. However, */
|
|
80 |
+ /* don't allocate memory; instead use the space already provided in */
|
|
81 |
+ /* `slot->bitmap.buffer`. */
|
|
82 |
+ surface = cairo_image_surface_create_for_data( slot->bitmap.buffer,
|
|
83 |
+ CAIRO_FORMAT_ARGB32,
|
|
84 |
+ (int)slot->bitmap.width,
|
|
85 |
+ (int)slot->bitmap.rows,
|
|
86 |
+ slot->bitmap.pitch );
|
|
87 |
+ status = cairo_surface_status( surface );
|
|
88 |
+ |
|
89 |
+ if ( status != CAIRO_STATUS_SUCCESS )
|
|
90 |
+ {
|
|
91 |
+ if ( status == CAIRO_STATUS_NO_MEMORY )
|
|
92 |
+ return FT_Err_Out_Of_Memory;
|
|
93 |
+ else
|
|
94 |
+ return FT_Err_Invalid_Outline;
|
|
95 |
+ }
|
|
96 |
+ |
|
97 |
+ cr = cairo_create( surface );
|
|
98 |
+ status = cairo_status( cr );
|
|
99 |
+ |
|
100 |
+ if ( status != CAIRO_STATUS_SUCCESS )
|
|
101 |
+ {
|
|
102 |
+ if ( status == CAIRO_STATUS_NO_MEMORY )
|
|
103 |
+ return FT_Err_Out_Of_Memory;
|
|
104 |
+ else
|
|
105 |
+ return FT_Err_Invalid_Outline;
|
|
106 |
+ }
|
|
107 |
+ |
|
108 |
+ /* Set a translate transform that translates the points in such a way */
|
|
109 |
+ /* that we get a tight rendering with least redundant white spac. */
|
|
110 |
+ cairo_translate( cr, -state->x, -state->y );
|
|
111 |
+ |
|
112 |
+ /* Replay from the recorded surface. This saves us from parsing the */
|
|
113 |
+ /* document again and redoing what was already done in the preset */
|
|
114 |
+ /* hook. */
|
|
115 |
+ cairo_set_source_surface( cr, state->rec_surface, 0.0, 0.0 );
|
|
116 |
+ cairo_paint( cr );
|
|
117 |
+ |
|
118 |
+ cairo_surface_flush( surface );
|
|
119 |
+ |
|
120 |
+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
|
|
121 |
+ slot->bitmap.num_grays = 256;
|
|
122 |
+ slot->format = FT_GLYPH_FORMAT_BITMAP;
|
|
123 |
+ |
|
124 |
+ /* Clean up everything. */
|
|
125 |
+ cairo_surface_destroy( surface );
|
|
126 |
+ cairo_destroy( cr );
|
|
127 |
+ cairo_surface_destroy( state->rec_surface );
|
|
128 |
+ |
|
129 |
+ return error;
|
|
130 |
+ }
|
|
131 |
+ |
|
132 |
+ |
|
133 |
+ /*
|
|
134 |
+ * This hook is called at two different locations. Firstly, it is called
|
|
135 |
+ * when presetting the glyphslot when `FT_Load_Glyph` is called.
|
|
136 |
+ * Secondly, it is called right before the render hook is called. When
|
|
137 |
+ * `cache` is false, it is the former, when `cache` is true, it is the
|
|
138 |
+ * latter.
|
|
139 |
+ *
|
|
140 |
+ * The job of this function is to preset the slot setting the width,
|
|
141 |
+ * height, pitch, `bitmap.left`, and `bitmap.top`. These are all
|
|
142 |
+ * necessary for appropriate memory allocation, as well as ultimately
|
|
143 |
+ * compositing the glyph later on by client applications.
|
|
144 |
+ */
|
|
145 |
+ FT_Error
|
|
146 |
+ rsvg_port_preset_slot( FT_GlyphSlot slot,
|
|
147 |
+ FT_Bool cache,
|
|
148 |
+ FT_Pointer *_state )
|
|
149 |
+ {
|
|
150 |
+ /* FreeType variables. */
|
|
151 |
+ FT_Error error = FT_Err_Ok;
|
|
152 |
+ |
|
153 |
+ FT_SVG_Document document = (FT_SVG_Document)slot->other;
|
|
154 |
+ FT_Size_Metrics metrics = document->metrics;
|
|
155 |
+ |
|
156 |
+ FT_UShort units_per_EM = document->units_per_EM;
|
|
157 |
+ FT_UShort end_glyph_id = document->end_glyph_id;
|
|
158 |
+ FT_UShort start_glyph_id = document->start_glyph_id;
|
|
159 |
+ |
|
160 |
+ /* Librsvg variables. */
|
|
161 |
+ GError *gerror = NULL;
|
|
162 |
+ gboolean ret;
|
|
163 |
+ |
|
164 |
+ gboolean out_has_width;
|
|
165 |
+ gboolean out_has_height;
|
|
166 |
+ gboolean out_has_viewbox;
|
|
167 |
+ |
|
168 |
+ RsvgHandle *handle;
|
|
169 |
+ RsvgLength out_width;
|
|
170 |
+ RsvgLength out_height;
|
|
171 |
+ RsvgRectangle out_viewbox;
|
|
172 |
+ RsvgDimensionData dimension_svg;
|
|
173 |
+ |
|
174 |
+ cairo_t *rec_cr;
|
|
175 |
+ cairo_matrix_t transform_matrix;
|
|
176 |
+ |
|
177 |
+ /* Rendering port's state. */
|
|
178 |
+ Rsvg_Port_State state;
|
|
179 |
+ Rsvg_Port_StateRec state_dummy;
|
|
180 |
+ |
|
181 |
+ /* General variables. */
|
|
182 |
+ double x, y;
|
|
183 |
+ double xx, xy, yx, yy;
|
|
184 |
+ double x0, y0;
|
|
185 |
+ double width, height;
|
|
186 |
+ double x_svg_to_out, y_svg_to_out;
|
|
187 |
+ double tmpd;
|
|
188 |
+ |
|
189 |
+ float metrics_width, metrics_height;
|
|
190 |
+ float horiBearingX, horiBearingY;
|
|
191 |
+ float vertBearingX, vertBearingY;
|
|
192 |
+ float tmpf;
|
|
193 |
+ |
|
194 |
+ |
|
195 |
+ /* If `cache` is `TRUE` we store calculations in the actual port */
|
|
196 |
+ /* state variable, otherwise we just create a dummy variable and */
|
|
197 |
+ /* store there. This saves us from too many 'if' statements. */
|
|
198 |
+ if ( cache )
|
|
199 |
+ state = *(Rsvg_Port_State*)_state;
|
|
200 |
+ else
|
|
201 |
+ state = &state_dummy;
|
|
202 |
+ |
|
203 |
+ /* Form an `RsvgHandle` by loading the SVG document. */
|
|
204 |
+ handle = rsvg_handle_new_from_data( document->svg_document,
|
|
205 |
+ document->svg_document_length,
|
|
206 |
+ &gerror );
|
|
207 |
+ if ( handle == NULL )
|
|
208 |
+ {
|
|
209 |
+ error = FT_Err_Invalid_SVG_Document;
|
|
210 |
+ goto CleanLibrsvg;
|
|
211 |
+ }
|
|
212 |
+ |
|
213 |
+ /* Get attributes like `viewBox` and `width`/`height`. */
|
|
214 |
+ rsvg_handle_get_intrinsic_dimensions( handle,
|
|
215 |
+ &out_has_width,
|
|
216 |
+ &out_width,
|
|
217 |
+ &out_has_height,
|
|
218 |
+ &out_height,
|
|
219 |
+ &out_has_viewbox,
|
|
220 |
+ &out_viewbox );
|
|
221 |
+ |
|
222 |
+ /*
|
|
223 |
+ * Figure out the units in the EM square in the SVG document. This is
|
|
224 |
+ * specified by the `ViewBox` or the `width`/`height` attributes, if
|
|
225 |
+ * present, otherwise it should be assumed that the units in the EM
|
|
226 |
+ * square are the same as in the TTF/CFF outlines.
|
|
227 |
+ *
|
|
228 |
+ * TODO: I'm not sure what the standard says about the situation if
|
|
229 |
+ * `ViewBox` as well as `width`/`height` are present; however, I've
|
|
230 |
+ * never seen that situation in real fonts.
|
|
231 |
+ */
|
|
232 |
+ if ( out_has_viewbox == TRUE )
|
|
233 |
+ {
|
|
234 |
+ dimension_svg.width = (int)out_viewbox.width; /* XXX rounding? */
|
|
235 |
+ dimension_svg.height = (int)out_viewbox.height;
|
|
236 |
+ }
|
|
237 |
+ else if ( out_has_width == TRUE && out_has_height == TRUE )
|
|
238 |
+ {
|
|
239 |
+ dimension_svg.width = (int)out_width.length; /* XXX rounding? */
|
|
240 |
+ dimension_svg.height = (int)out_height.length;
|
|
241 |
+ }
|
|
242 |
+ else
|
|
243 |
+ {
|
|
244 |
+ /* If neither `ViewBox` nor `width`/`height` are present, the */
|
|
245 |
+ /* `units_per_EM` in SVG coordinates must be the same as */
|
|
246 |
+ /* `units_per_EM` of the TTF/CFF outlines. */
|
|
247 |
+ dimension_svg.width = units_per_EM;
|
|
248 |
+ dimension_svg.height = units_per_EM;
|
|
249 |
+ }
|
|
250 |
+ |
|
251 |
+ /* Scale factors from SVG coordinates to the needed output size. */
|
|
252 |
+ x_svg_to_out = (float)metrics.x_ppem / dimension_svg.width;
|
|
253 |
+ y_svg_to_out = (float)metrics.y_ppem / dimension_svg.height;
|
|
254 |
+ |
|
255 |
+ /*
|
|
256 |
+ * Create a cairo recording surface. This is done for two reasons.
|
|
257 |
+ * Firstly, it is required to get the bounding box of the final drawing
|
|
258 |
+ * so we can use an appropriate translate transform to get a tight
|
|
259 |
+ * rendering. Secondly, if `cache` is true, we can save this surface
|
|
260 |
+ * and later replay it against an image surface for the final rendering.
|
|
261 |
+ * This saves us from loading and parsing the document again.
|
|
262 |
+ */
|
|
263 |
+ state->rec_surface =
|
|
264 |
+ cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL );
|
|
265 |
+ |
|
266 |
+ rec_cr = cairo_create( state->rec_surface );
|
|
267 |
+ |
|
268 |
+ /*
|
|
269 |
+ * We need to take into account any transformations applied. The end
|
|
270 |
+ * user who applied the transformation doesn't know the internal details
|
|
271 |
+ * of the SVG document. Thus, we expect that the end user should just
|
|
272 |
+ * write the transformation as if the glyph is a traditional one. We
|
|
273 |
+ * then do some maths on this to get the equivalent transformation in
|
|
274 |
+ * SVG coordinates.
|
|
275 |
+ */
|
|
276 |
+ xx = (double)document->transform.xx / ( 1 << 16 );
|
|
277 |
+ xy = -(double)document->transform.xy / ( 1 << 16 );
|
|
278 |
+ yx = -(double)document->transform.yx / ( 1 << 16 );
|
|
279 |
+ yy = (double)document->transform.yy / ( 1 << 16 );
|
|
280 |
+ |
|
281 |
+ x0 = (double)document->delta.x / 64 *
|
|
282 |
+ dimension_svg.width / metrics.x_ppem;
|
|
283 |
+ y0 = -(double)document->delta.y / 64 *
|
|
284 |
+ dimension_svg.height / metrics.y_ppem;
|
|
285 |
+ |
|
286 |
+ /* Cairo stores both transformation and translation in one matrix. */
|
|
287 |
+ transform_matrix.xx = xx;
|
|
288 |
+ transform_matrix.yx = yx;
|
|
289 |
+ transform_matrix.xy = xy;
|
|
290 |
+ transform_matrix.yy = yy;
|
|
291 |
+ transform_matrix.x0 = x0;
|
|
292 |
+ transform_matrix.y0 = y0;
|
|
293 |
+ |
|
294 |
+ /* Set up a scale transformation to scale up the document to the */
|
|
295 |
+ /* required output size. */
|
|
296 |
+ cairo_scale( rec_cr, x_svg_to_out, y_svg_to_out );
|
|
297 |
+ /* Set up a transformation matrix. */
|
|
298 |
+ cairo_transform( rec_cr, &transform_matrix );
|
|
299 |
+ |
|
300 |
+ /* If the document contains only one glyph, `start_glyph_id` and */
|
|
301 |
+ /* `end_glyph_id` have the same value. Otherwise `end_glyph_id` */
|
|
302 |
+ /* is larger. */
|
|
303 |
+ if ( start_glyph_id == end_glyph_id )
|
|
304 |
+ {
|
|
305 |
+ /* Render the whole document to the recording surface. */
|
|
306 |
+ ret = rsvg_handle_render_cairo ( handle, rec_cr );
|
|
307 |
+ if ( ret == FALSE )
|
|
308 |
+ {
|
|
309 |
+ error = FT_Err_Invalid_SVG_Document;
|
|
310 |
+ goto CleanCairo;
|
|
311 |
+ }
|
|
312 |
+ }
|
|
313 |
+ else if ( start_glyph_id < end_glyph_id )
|
|
314 |
+ {
|
|
315 |
+ char str[32] = "#glyph";
|
|
316 |
+ |
|
317 |
+ |
|
318 |
+ /* Render only the element with its ID equal to `glyph<ID>`. */
|
|
319 |
+ sprintf( str + 6, "%u", slot->glyph_index );
|
|
320 |
+ ret = rsvg_handle_render_cairo_sub( handle, rec_cr, str );
|
|
321 |
+ if ( ret == FALSE )
|
|
322 |
+ {
|
|
323 |
+ error = FT_Err_Invalid_SVG_Document;
|
|
324 |
+ goto CleanCairo;
|
|
325 |
+ }
|
|
326 |
+ }
|
|
327 |
+ |
|
328 |
+ /* Get the bounding box of the drawing. */
|
|
329 |
+ cairo_recording_surface_ink_extents( state->rec_surface, &x, &y,
|
|
330 |
+ &width, &height );
|
|
331 |
+ |
|
332 |
+ /* We store the bounding box's `x` and `y` values so that the render */
|
|
333 |
+ /* hook can apply a translation to get a tight rendering. */
|
|
334 |
+ state->x = x;
|
|
335 |
+ state->y = y;
|
|
336 |
+ |
|
337 |
+ /* Preset the values. */
|
|
338 |
+ slot->bitmap_left = (FT_Int) state->x; /* XXX rounding? */
|
|
339 |
+ slot->bitmap_top = (FT_Int)-state->y;
|
|
340 |
+ |
|
341 |
+ /* Do conversion in two steps to avoid 'bad function cast' warning. */
|
|
342 |
+ tmpd = ceil( height );
|
|
343 |
+ slot->bitmap.rows = (unsigned int)tmpd;
|
|
344 |
+ tmpd = ceil( width );
|
|
345 |
+ slot->bitmap.width = (unsigned int)tmpd;
|
|
346 |
+ |
|
347 |
+ slot->bitmap.pitch = (int)slot->bitmap.width * 4;
|
|
348 |
+ |
|
349 |
+ slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
|
|
350 |
+ |
|
351 |
+ /* Compute all the bearings and set them correctly. The outline is */
|
|
352 |
+ /* scaled already, we just need to use the bounding box. */
|
|
353 |
+ metrics_width = (float)width;
|
|
354 |
+ metrics_height = (float)height;
|
|
355 |
+ |
|
356 |
+ horiBearingX = (float) state->x;
|
|
357 |
+ horiBearingY = (float)-state->y;
|
|
358 |
+ |
|
359 |
+ vertBearingX = slot->metrics.horiBearingX / 64.0f -
|
|
360 |
+ slot->metrics.horiAdvance / 64.0f / 2;
|
|
361 |
+ vertBearingY = ( slot->metrics.vertAdvance / 64.0f -
|
|
362 |
+ slot->metrics.height / 64.0f ) / 2; /* XXX parentheses correct? */
|
|
363 |
+ |
|
364 |
+ /* Do conversion in two steps to avoid 'bad function cast' warning. */
|
|
365 |
+ tmpf = roundf( metrics_width * 64 );
|
|
366 |
+ slot->metrics.width = (FT_Pos)tmpf;
|
|
367 |
+ tmpf = roundf( metrics_height * 64 );
|
|
368 |
+ slot->metrics.height = (FT_Pos)tmpf;
|
|
369 |
+ |
|
370 |
+ slot->metrics.horiBearingX = (FT_Pos)( horiBearingX * 64 ); /* XXX rounding? */
|
|
371 |
+ slot->metrics.horiBearingY = (FT_Pos)( horiBearingY * 64 );
|
|
372 |
+ slot->metrics.vertBearingX = (FT_Pos)( vertBearingX * 64 );
|
|
373 |
+ slot->metrics.vertBearingY = (FT_Pos)( vertBearingY * 64 );
|
|
374 |
+ |
|
375 |
+ if ( slot->metrics.vertAdvance == 0 )
|
|
376 |
+ slot->metrics.vertAdvance = (FT_Pos)( metrics_height * 1.2 * 64 );
|
|
377 |
+ |
|
378 |
+ /* If a render call is to follow, just destroy the context for the */
|
|
379 |
+ /* recording surface since no more drawing will be done on it. */
|
|
380 |
+ /* However, keep the surface itself for use by the render hook. */
|
|
381 |
+ if ( cache == TRUE )
|
|
382 |
+ {
|
|
383 |
+ cairo_destroy( rec_cr );
|
|
384 |
+ goto CleanLibrsvg;
|
|
385 |
+ }
|
|
386 |
+ |
|
387 |
+ /* Destroy the recording surface as well as the context. */
|
|
388 |
+ CleanCairo:
|
|
389 |
+ cairo_surface_destroy( state->rec_surface );
|
|
390 |
+ cairo_destroy( rec_cr );
|
|
391 |
+ |
|
392 |
+ CleanLibrsvg:
|
|
393 |
+ /* Destroy the handle. */
|
|
394 |
+ g_object_unref( handle );
|
|
395 |
+ |
|
396 |
+ return error;
|
|
397 |
+ }
|
|
398 |
+ |
|
399 |
+ |
|
400 |
+/* End */
|
1 |
+/****************************************************************************
|
|
2 |
+ *
|
|
3 |
+ * rsvg-port.h
|
|
4 |
+ *
|
|
5 |
+ * Librsvg based hook functions for OT-SVG rendering in FreeType
|
|
6 |
+ * (headers).
|
|
7 |
+ *
|
|
8 |
+ * Copyright (C) 2021 by
|
|
9 |
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
|
|
10 |
+ *
|
|
11 |
+ * This file is part of the FreeType project, and may only be used,
|
|
12 |
+ * modified, and distributed under the terms of the FreeType project
|
|
13 |
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
|
|
14 |
+ * this file you indicate that you have read the license and
|
|
15 |
+ * understand and accept it fully.
|
|
16 |
+ *
|
|
17 |
+ */
|
|
18 |
+ |
|
19 |
+#ifndef RSVG_PORT_H
|
|
20 |
+#define RSVG_PORT_H
|
|
21 |
+ |
|
22 |
+#include <cairo.h>
|
|
23 |
+#include <librsvg/rsvg.h>
|
|
24 |
+#include <ft2build.h>
|
|
25 |
+#include <freetype/freetype.h>
|
|
26 |
+ |
|
27 |
+ |
|
28 |
+ /*
|
|
29 |
+ * Different hook functions can access persisting data by creating a state
|
|
30 |
+ * structure and putting its address in `library->svg_renderer_state`.
|
|
31 |
+ * Functions can then store and retrieve data from this structure.
|
|
32 |
+ */
|
|
33 |
+ typedef struct Rsvg_Port_StateRec_
|
|
34 |
+ {
|
|
35 |
+ cairo_surface_t *rec_surface;
|
|
36 |
+ |
|
37 |
+ double x;
|
|
38 |
+ double y;
|
|
39 |
+ |
|
40 |
+ } Rsvg_Port_StateRec;
|
|
41 |
+ |
|
42 |
+ typedef struct Rsvg_Port_StateRec_* Rsvg_Port_State;
|
|
43 |
+ |
|
44 |
+ |
|
45 |
+ FT_Error
|
|
46 |
+ rsvg_port_init( FT_Pointer *state );
|
|
47 |
+ |
|
48 |
+ void
|
|
49 |
+ rsvg_port_free( FT_Pointer *state );
|
|
50 |
+ |
|
51 |
+ FT_Error
|
|
52 |
+ rsvg_port_render( FT_GlyphSlot slot,
|
|
53 |
+ FT_Pointer *state );
|
|
54 |
+ |
|
55 |
+ FT_Error
|
|
56 |
+ rsvg_port_preset_slot( FT_GlyphSlot slot,
|
|
57 |
+ FT_Bool cache,
|
|
58 |
+ FT_Pointer *state );
|
|
59 |
+ |
|
60 |
+#endif /* RSVG_PORT_H */
|
|
61 |
+ |
|
62 |
+ |
|
63 |
+/* End */
|
... | ... | @@ -3,9 +3,10 @@ directory = libpng-1.6.37 |
3 | 3 |
source_url = https://github.com/glennrp/libpng/archive/v1.6.37.tar.gz
|
4 | 4 |
source_filename = libpng-1.6.37.tar.gz
|
5 | 5 |
source_hash = ca74a0dace179a8422187671aee97dd3892b53e168627145271cad5b5ac81307
|
6 |
-patch_url = "">libpng/1.6.37/3/get_zip
|
|
7 |
-patch_filename = libpng-1.6.37-3-wrap.zip
|
|
8 |
-patch_hash = 6c9f32fd9150b3a96ab89be52af664e32207e10aa9f5fb9aa015989ee2dd7100
|
|
6 |
+patch_filename = libpng_1.6.37-5_patch.zip
|
|
7 |
+patch_url = "">libpng_1.6.37-5/get_patch
|
|
8 |
+patch_hash = 822200906ad2e82dc8b44e79fe960e980ccad96263548c35eef721086a9926f1
|
|
9 | 9 |
|
10 | 10 |
[provide]
|
11 | 11 |
libpng = libpng_dep
|
12 |
+ |
... | ... | @@ -3,7 +3,7 @@ directory = zlib-1.2.11 |
3 | 3 |
source_url = http://zlib.net/fossils/zlib-1.2.11.tar.gz
|
4 | 4 |
source_filename = zlib-1.2.11.tar.gz
|
5 | 5 |
source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
|
6 |
-patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/5/get_zip
|
|
6 |
+patch_url = https://wrapdb.mesonbuild.com/v2/zlib_1.2.11-5/get_patch
|
|
7 | 7 |
patch_filename = zlib-1.2.11-5-wrap.zip
|
8 | 8 |
patch_hash = 728c8e24acbc2e6682fbd950fec39e2fc77528af361adb87259f8a8511434004
|
9 | 9 |
|