1 /***************************************************************************/
2 /* */
3 /* ftstroke.c */
4 /* */
5 /* FreeType path stroker (body). */
6 /* */
7 /* Copyright 2002-2018 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
17
18
19 #include <ft2build.h>
20 #include FT_STROKER_H
21 #include FT_TRIGONOMETRY_H
22 #include FT_OUTLINE_H
23 #include FT_INTERNAL_MEMORY_H
24 #include FT_INTERNAL_DEBUG_H
25 #include FT_INTERNAL_OBJECTS_H
26
27 #include "basepic.h"
28
29
30 /* declare an extern to access `ft_outline_glyph_class' globally */
31 /* allocated in `ftglyph.c', and use the FT_OUTLINE_GLYPH_CLASS_GET */
32 /* macro to access it when FT_CONFIG_OPTION_PIC is defined */
33 #ifndef FT_CONFIG_OPTION_PIC
34 FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class;
35 #endif
36
37
38 /* documentation is in ftstroke.h */
39
40 FT_EXPORT_DEF( FT_StrokerBorder )
41 FT_Outline_GetInsideBorder( FT_Outline* outline )
42 {
43 FT_Orientation o = FT_Outline_Get_Orientation( outline );
44
45
46 return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
47 : FT_STROKER_BORDER_LEFT;
48 }
49
50
51 /* documentation is in ftstroke.h */
52
53 FT_EXPORT_DEF( FT_StrokerBorder )
54 FT_Outline_GetOutsideBorder( FT_Outline* outline )
55 {
355
356 static void
357 ft_stroke_border_close( FT_StrokeBorder border,
358 FT_Bool reverse )
359 {
360 FT_UInt start = (FT_UInt)border->start;
361 FT_UInt count = border->num_points;
362
363
364 FT_ASSERT( border->start >= 0 );
365
366 /* don't record empty paths! */
367 if ( count <= start + 1U )
368 border->num_points = start;
369 else
370 {
371 /* copy the last point to the start of this sub-path, since */
372 /* it contains the `adjusted' starting coordinates */
373 border->num_points = --count;
374 border->points[start] = border->points[count];
375
376 if ( reverse )
377 {
378 /* reverse the points */
379 {
380 FT_Vector* vec1 = border->points + start + 1;
381 FT_Vector* vec2 = border->points + count - 1;
382
383
384 for ( ; vec1 < vec2; vec1++, vec2-- )
385 {
386 FT_Vector tmp;
387
388
389 tmp = *vec1;
390 *vec1 = *vec2;
391 *vec2 = tmp;
392 }
393 }
394
419 }
420
421
422 static FT_Error
423 ft_stroke_border_lineto( FT_StrokeBorder border,
424 FT_Vector* to,
425 FT_Bool movable )
426 {
427 FT_Error error = FT_Err_Ok;
428
429
430 FT_ASSERT( border->start >= 0 );
431
432 if ( border->movable )
433 {
434 /* move last point */
435 border->points[border->num_points - 1] = *to;
436 }
437 else
438 {
439 /* don't add zero-length lineto */
440 if ( border->num_points > 0 &&
441 FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
442 FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
443 return error;
444
445 /* add one point */
446 error = ft_stroke_border_grow( border, 1 );
447 if ( !error )
448 {
449 FT_Vector* vec = border->points + border->num_points;
450 FT_Byte* tag = border->tags + border->num_points;
451
452
453 vec[0] = *to;
454 tag[0] = FT_STROKE_TAG_ON;
455
456 border->num_points += 1;
457 }
458 }
459 border->movable = movable;
460 return error;
2289 return FT_Err_Ok;
2290
2291 Exit:
2292 return error;
2293
2294 Invalid_Outline:
2295 return FT_THROW( Invalid_Outline );
2296 }
2297
2298
2299 /* documentation is in ftstroke.h */
2300
2301 FT_EXPORT_DEF( FT_Error )
2302 FT_Glyph_Stroke( FT_Glyph *pglyph,
2303 FT_Stroker stroker,
2304 FT_Bool destroy )
2305 {
2306 FT_Error error = FT_ERR( Invalid_Argument );
2307 FT_Glyph glyph = NULL;
2308
2309 /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
2310 FT_Library library = stroker->library;
2311
2312 FT_UNUSED( library );
2313
2314
2315 if ( !pglyph )
2316 goto Exit;
2317
2318 glyph = *pglyph;
2319 if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
2320 goto Exit;
2321
2322 {
2323 FT_Glyph copy;
2324
2325
2326 error = FT_Glyph_Copy( glyph, © );
2327 if ( error )
2328 goto Exit;
2329
2330 glyph = copy;
2331 }
2332
2333 {
2334 FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
2335 FT_Outline* outline = &oglyph->outline;
2336 FT_UInt num_points, num_contours;
2337
2338
2339 error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
2369
2370 if ( !destroy )
2371 *pglyph = NULL;
2372
2373 Exit:
2374 return error;
2375 }
2376
2377
2378 /* documentation is in ftstroke.h */
2379
2380 FT_EXPORT_DEF( FT_Error )
2381 FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
2382 FT_Stroker stroker,
2383 FT_Bool inside,
2384 FT_Bool destroy )
2385 {
2386 FT_Error error = FT_ERR( Invalid_Argument );
2387 FT_Glyph glyph = NULL;
2388
2389 /* for FT_OUTLINE_GLYPH_CLASS_GET (in PIC mode) */
2390 FT_Library library = stroker->library;
2391
2392 FT_UNUSED( library );
2393
2394
2395 if ( !pglyph )
2396 goto Exit;
2397
2398 glyph = *pglyph;
2399 if ( !glyph || glyph->clazz != FT_OUTLINE_GLYPH_CLASS_GET )
2400 goto Exit;
2401
2402 {
2403 FT_Glyph copy;
2404
2405
2406 error = FT_Glyph_Copy( glyph, © );
2407 if ( error )
2408 goto Exit;
2409
2410 glyph = copy;
2411 }
2412
2413 {
2414 FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
2415 FT_StrokerBorder border;
2416 FT_Outline* outline = &oglyph->outline;
2417 FT_UInt num_points, num_contours;
2418
2419
|
1 /****************************************************************************
2 *
3 * ftstroke.c
4 *
5 * FreeType path stroker (body).
6 *
7 * Copyright (C) 2002-2019 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
19 #include <ft2build.h>
20 #include FT_STROKER_H
21 #include FT_TRIGONOMETRY_H
22 #include FT_OUTLINE_H
23 #include FT_INTERNAL_MEMORY_H
24 #include FT_INTERNAL_DEBUG_H
25 #include FT_INTERNAL_OBJECTS_H
26
27
28 /* declare an extern to access `ft_outline_glyph_class' globally */
29 /* allocated in `ftglyph.c' */
30 FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class;
31
32
33 /* documentation is in ftstroke.h */
34
35 FT_EXPORT_DEF( FT_StrokerBorder )
36 FT_Outline_GetInsideBorder( FT_Outline* outline )
37 {
38 FT_Orientation o = FT_Outline_Get_Orientation( outline );
39
40
41 return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
42 : FT_STROKER_BORDER_LEFT;
43 }
44
45
46 /* documentation is in ftstroke.h */
47
48 FT_EXPORT_DEF( FT_StrokerBorder )
49 FT_Outline_GetOutsideBorder( FT_Outline* outline )
50 {
350
351 static void
352 ft_stroke_border_close( FT_StrokeBorder border,
353 FT_Bool reverse )
354 {
355 FT_UInt start = (FT_UInt)border->start;
356 FT_UInt count = border->num_points;
357
358
359 FT_ASSERT( border->start >= 0 );
360
361 /* don't record empty paths! */
362 if ( count <= start + 1U )
363 border->num_points = start;
364 else
365 {
366 /* copy the last point to the start of this sub-path, since */
367 /* it contains the `adjusted' starting coordinates */
368 border->num_points = --count;
369 border->points[start] = border->points[count];
370 border->tags[start] = border->tags[count];
371
372 if ( reverse )
373 {
374 /* reverse the points */
375 {
376 FT_Vector* vec1 = border->points + start + 1;
377 FT_Vector* vec2 = border->points + count - 1;
378
379
380 for ( ; vec1 < vec2; vec1++, vec2-- )
381 {
382 FT_Vector tmp;
383
384
385 tmp = *vec1;
386 *vec1 = *vec2;
387 *vec2 = tmp;
388 }
389 }
390
415 }
416
417
418 static FT_Error
419 ft_stroke_border_lineto( FT_StrokeBorder border,
420 FT_Vector* to,
421 FT_Bool movable )
422 {
423 FT_Error error = FT_Err_Ok;
424
425
426 FT_ASSERT( border->start >= 0 );
427
428 if ( border->movable )
429 {
430 /* move last point */
431 border->points[border->num_points - 1] = *to;
432 }
433 else
434 {
435 /* don't add zero-length lineto, but always add moveto */
436 if ( border->num_points > (FT_UInt)border->start &&
437 FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
438 FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
439 return error;
440
441 /* add one point */
442 error = ft_stroke_border_grow( border, 1 );
443 if ( !error )
444 {
445 FT_Vector* vec = border->points + border->num_points;
446 FT_Byte* tag = border->tags + border->num_points;
447
448
449 vec[0] = *to;
450 tag[0] = FT_STROKE_TAG_ON;
451
452 border->num_points += 1;
453 }
454 }
455 border->movable = movable;
456 return error;
2285 return FT_Err_Ok;
2286
2287 Exit:
2288 return error;
2289
2290 Invalid_Outline:
2291 return FT_THROW( Invalid_Outline );
2292 }
2293
2294
2295 /* documentation is in ftstroke.h */
2296
2297 FT_EXPORT_DEF( FT_Error )
2298 FT_Glyph_Stroke( FT_Glyph *pglyph,
2299 FT_Stroker stroker,
2300 FT_Bool destroy )
2301 {
2302 FT_Error error = FT_ERR( Invalid_Argument );
2303 FT_Glyph glyph = NULL;
2304
2305
2306 if ( !pglyph )
2307 goto Exit;
2308
2309 glyph = *pglyph;
2310 if ( !glyph || glyph->clazz != &ft_outline_glyph_class )
2311 goto Exit;
2312
2313 {
2314 FT_Glyph copy;
2315
2316
2317 error = FT_Glyph_Copy( glyph, © );
2318 if ( error )
2319 goto Exit;
2320
2321 glyph = copy;
2322 }
2323
2324 {
2325 FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
2326 FT_Outline* outline = &oglyph->outline;
2327 FT_UInt num_points, num_contours;
2328
2329
2330 error = FT_Stroker_ParseOutline( stroker, outline, FALSE );
2360
2361 if ( !destroy )
2362 *pglyph = NULL;
2363
2364 Exit:
2365 return error;
2366 }
2367
2368
2369 /* documentation is in ftstroke.h */
2370
2371 FT_EXPORT_DEF( FT_Error )
2372 FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
2373 FT_Stroker stroker,
2374 FT_Bool inside,
2375 FT_Bool destroy )
2376 {
2377 FT_Error error = FT_ERR( Invalid_Argument );
2378 FT_Glyph glyph = NULL;
2379
2380
2381 if ( !pglyph )
2382 goto Exit;
2383
2384 glyph = *pglyph;
2385 if ( !glyph || glyph->clazz != &ft_outline_glyph_class )
2386 goto Exit;
2387
2388 {
2389 FT_Glyph copy;
2390
2391
2392 error = FT_Glyph_Copy( glyph, © );
2393 if ( error )
2394 goto Exit;
2395
2396 glyph = copy;
2397 }
2398
2399 {
2400 FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
2401 FT_StrokerBorder border;
2402 FT_Outline* outline = &oglyph->outline;
2403 FT_UInt num_points, num_contours;
2404
2405
|