Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenftoutln.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ftoutln.c */ 00004 /* */ 00005 /* FreeType outline management (body). */ 00006 /* */ 00007 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 /*************************************************************************/ 00020 /* */ 00021 /* All functions are declared in freetype.h. */ 00022 /* */ 00023 /*************************************************************************/ 00024 00025 00026 #include <ft2build.h> 00027 #include FT_OUTLINE_H 00028 #include FT_INTERNAL_OBJECTS_H 00029 #include FT_INTERNAL_DEBUG_H 00030 #include FT_TRIGONOMETRY_H 00031 00032 00033 /*************************************************************************/ 00034 /* */ 00035 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00036 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00037 /* messages during execution. */ 00038 /* */ 00039 #undef FT_COMPONENT 00040 #define FT_COMPONENT trace_outline 00041 00042 00043 static 00044 const FT_Outline null_outline = { 0, 0, 0, 0, 0, 0 }; 00045 00046 00047 /* documentation is in ftoutln.h */ 00048 00049 FT_EXPORT_DEF( FT_Error ) 00050 FT_Outline_Decompose( FT_Outline* outline, 00051 const FT_Outline_Funcs* func_interface, 00052 void* user ) 00053 { 00054 #undef SCALED 00055 #define SCALED( x ) ( ( (x) << shift ) - delta ) 00056 00057 FT_Vector v_last; 00058 FT_Vector v_control; 00059 FT_Vector v_start; 00060 00061 FT_Vector* point; 00062 FT_Vector* limit; 00063 char* tags; 00064 00065 FT_Error error; 00066 00067 FT_Int n; /* index of contour in outline */ 00068 FT_UInt first; /* index of first point in contour */ 00069 FT_Int tag; /* current point's state */ 00070 00071 FT_Int shift; 00072 FT_Pos delta; 00073 00074 00075 if ( !outline || !func_interface ) 00076 return FT_Err_Invalid_Argument; 00077 00078 shift = func_interface->shift; 00079 delta = func_interface->delta; 00080 first = 0; 00081 00082 for ( n = 0; n < outline->n_contours; n++ ) 00083 { 00084 FT_Int last; /* index of last point in contour */ 00085 00086 00087 FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); 00088 00089 last = outline->contours[n]; 00090 if ( last < 0 ) 00091 goto Invalid_Outline; 00092 limit = outline->points + last; 00093 00094 v_start = outline->points[first]; 00095 v_start.x = SCALED( v_start.x ); 00096 v_start.y = SCALED( v_start.y ); 00097 00098 v_last = outline->points[last]; 00099 v_last.x = SCALED( v_last.x ); 00100 v_last.y = SCALED( v_last.y ); 00101 00102 v_control = v_start; 00103 00104 point = outline->points + first; 00105 tags = outline->tags + first; 00106 tag = FT_CURVE_TAG( tags[0] ); 00107 00108 /* A contour cannot start with a cubic control point! */ 00109 if ( tag == FT_CURVE_TAG_CUBIC ) 00110 goto Invalid_Outline; 00111 00112 /* check first point to determine origin */ 00113 if ( tag == FT_CURVE_TAG_CONIC ) 00114 { 00115 /* first point is conic control. Yes, this happens. */ 00116 if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) 00117 { 00118 /* start at last point if it is on the curve */ 00119 v_start = v_last; 00120 limit--; 00121 } 00122 else 00123 { 00124 /* if both first and last points are conic, */ 00125 /* start at their middle and record its position */ 00126 /* for closure */ 00127 v_start.x = ( v_start.x + v_last.x ) / 2; 00128 v_start.y = ( v_start.y + v_last.y ) / 2; 00129 00130 v_last = v_start; 00131 } 00132 point--; 00133 tags--; 00134 } 00135 00136 FT_TRACE5(( " move to (%.2f, %.2f)\n", 00137 v_start.x / 64.0, v_start.y / 64.0 )); 00138 error = func_interface->move_to( &v_start, user ); 00139 if ( error ) 00140 goto Exit; 00141 00142 while ( point < limit ) 00143 { 00144 point++; 00145 tags++; 00146 00147 tag = FT_CURVE_TAG( tags[0] ); 00148 switch ( tag ) 00149 { 00150 case FT_CURVE_TAG_ON: /* emit a single line_to */ 00151 { 00152 FT_Vector vec; 00153 00154 00155 vec.x = SCALED( point->x ); 00156 vec.y = SCALED( point->y ); 00157 00158 FT_TRACE5(( " line to (%.2f, %.2f)\n", 00159 vec.x / 64.0, vec.y / 64.0 )); 00160 error = func_interface->line_to( &vec, user ); 00161 if ( error ) 00162 goto Exit; 00163 continue; 00164 } 00165 00166 case FT_CURVE_TAG_CONIC: /* consume conic arcs */ 00167 v_control.x = SCALED( point->x ); 00168 v_control.y = SCALED( point->y ); 00169 00170 Do_Conic: 00171 if ( point < limit ) 00172 { 00173 FT_Vector vec; 00174 FT_Vector v_middle; 00175 00176 00177 point++; 00178 tags++; 00179 tag = FT_CURVE_TAG( tags[0] ); 00180 00181 vec.x = SCALED( point->x ); 00182 vec.y = SCALED( point->y ); 00183 00184 if ( tag == FT_CURVE_TAG_ON ) 00185 { 00186 FT_TRACE5(( " conic to (%.2f, %.2f)" 00187 " with control (%.2f, %.2f)\n", 00188 vec.x / 64.0, vec.y / 64.0, 00189 v_control.x / 64.0, v_control.y / 64.0 )); 00190 error = func_interface->conic_to( &v_control, &vec, user ); 00191 if ( error ) 00192 goto Exit; 00193 continue; 00194 } 00195 00196 if ( tag != FT_CURVE_TAG_CONIC ) 00197 goto Invalid_Outline; 00198 00199 v_middle.x = ( v_control.x + vec.x ) / 2; 00200 v_middle.y = ( v_control.y + vec.y ) / 2; 00201 00202 FT_TRACE5(( " conic to (%.2f, %.2f)" 00203 " with control (%.2f, %.2f)\n", 00204 v_middle.x / 64.0, v_middle.y / 64.0, 00205 v_control.x / 64.0, v_control.y / 64.0 )); 00206 error = func_interface->conic_to( &v_control, &v_middle, user ); 00207 if ( error ) 00208 goto Exit; 00209 00210 v_control = vec; 00211 goto Do_Conic; 00212 } 00213 00214 FT_TRACE5(( " conic to (%.2f, %.2f)" 00215 " with control (%.2f, %.2f)\n", 00216 v_start.x / 64.0, v_start.y / 64.0, 00217 v_control.x / 64.0, v_control.y / 64.0 )); 00218 error = func_interface->conic_to( &v_control, &v_start, user ); 00219 goto Close; 00220 00221 default: /* FT_CURVE_TAG_CUBIC */ 00222 { 00223 FT_Vector vec1, vec2; 00224 00225 00226 if ( point + 1 > limit || 00227 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) 00228 goto Invalid_Outline; 00229 00230 point += 2; 00231 tags += 2; 00232 00233 vec1.x = SCALED( point[-2].x ); 00234 vec1.y = SCALED( point[-2].y ); 00235 00236 vec2.x = SCALED( point[-1].x ); 00237 vec2.y = SCALED( point[-1].y ); 00238 00239 if ( point <= limit ) 00240 { 00241 FT_Vector vec; 00242 00243 00244 vec.x = SCALED( point->x ); 00245 vec.y = SCALED( point->y ); 00246 00247 FT_TRACE5(( " cubic to (%.2f, %.2f)" 00248 " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", 00249 vec.x / 64.0, vec.y / 64.0, 00250 vec1.x / 64.0, vec1.y / 64.0, 00251 vec2.x / 64.0, vec2.y / 64.0 )); 00252 error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); 00253 if ( error ) 00254 goto Exit; 00255 continue; 00256 } 00257 00258 FT_TRACE5(( " cubic to (%.2f, %.2f)" 00259 " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", 00260 v_start.x / 64.0, v_start.y / 64.0, 00261 vec1.x / 64.0, vec1.y / 64.0, 00262 vec2.x / 64.0, vec2.y / 64.0 )); 00263 error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); 00264 goto Close; 00265 } 00266 } 00267 } 00268 00269 /* close the contour with a line segment */ 00270 FT_TRACE5(( " line to (%.2f, %.2f)\n", 00271 v_start.x / 64.0, v_start.y / 64.0 )); 00272 error = func_interface->line_to( &v_start, user ); 00273 00274 Close: 00275 if ( error ) 00276 goto Exit; 00277 00278 first = last + 1; 00279 } 00280 00281 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); 00282 return FT_Err_Ok; 00283 00284 Exit: 00285 FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); 00286 return error; 00287 00288 Invalid_Outline: 00289 return FT_Err_Invalid_Outline; 00290 } 00291 00292 00293 FT_EXPORT_DEF( FT_Error ) 00294 FT_Outline_New_Internal( FT_Memory memory, 00295 FT_UInt numPoints, 00296 FT_Int numContours, 00297 FT_Outline *anoutline ) 00298 { 00299 FT_Error error; 00300 00301 00302 if ( !anoutline || !memory ) 00303 return FT_Err_Invalid_Argument; 00304 00305 *anoutline = null_outline; 00306 00307 if ( FT_NEW_ARRAY( anoutline->points, numPoints ) || 00308 FT_NEW_ARRAY( anoutline->tags, numPoints ) || 00309 FT_NEW_ARRAY( anoutline->contours, numContours ) ) 00310 goto Fail; 00311 00312 anoutline->n_points = (FT_UShort)numPoints; 00313 anoutline->n_contours = (FT_Short)numContours; 00314 anoutline->flags |= FT_OUTLINE_OWNER; 00315 00316 return FT_Err_Ok; 00317 00318 Fail: 00319 anoutline->flags |= FT_OUTLINE_OWNER; 00320 FT_Outline_Done_Internal( memory, anoutline ); 00321 00322 return error; 00323 } 00324 00325 00326 /* documentation is in ftoutln.h */ 00327 00328 FT_EXPORT_DEF( FT_Error ) 00329 FT_Outline_New( FT_Library library, 00330 FT_UInt numPoints, 00331 FT_Int numContours, 00332 FT_Outline *anoutline ) 00333 { 00334 if ( !library ) 00335 return FT_Err_Invalid_Library_Handle; 00336 00337 return FT_Outline_New_Internal( library->memory, numPoints, 00338 numContours, anoutline ); 00339 } 00340 00341 00342 /* documentation is in ftoutln.h */ 00343 00344 FT_EXPORT_DEF( FT_Error ) 00345 FT_Outline_Check( FT_Outline* outline ) 00346 { 00347 if ( outline ) 00348 { 00349 FT_Int n_points = outline->n_points; 00350 FT_Int n_contours = outline->n_contours; 00351 FT_Int end0, end; 00352 FT_Int n; 00353 00354 00355 /* empty glyph? */ 00356 if ( n_points == 0 && n_contours == 0 ) 00357 return 0; 00358 00359 /* check point and contour counts */ 00360 if ( n_points <= 0 || n_contours <= 0 ) 00361 goto Bad; 00362 00363 end0 = end = -1; 00364 for ( n = 0; n < n_contours; n++ ) 00365 { 00366 end = outline->contours[n]; 00367 00368 /* note that we don't accept empty contours */ 00369 if ( end <= end0 || end >= n_points ) 00370 goto Bad; 00371 00372 end0 = end; 00373 } 00374 00375 if ( end != n_points - 1 ) 00376 goto Bad; 00377 00378 /* XXX: check the tags array */ 00379 return 0; 00380 } 00381 00382 Bad: 00383 return FT_Err_Invalid_Argument; 00384 } 00385 00386 00387 /* documentation is in ftoutln.h */ 00388 00389 FT_EXPORT_DEF( FT_Error ) 00390 FT_Outline_Copy( const FT_Outline* source, 00391 FT_Outline *target ) 00392 { 00393 FT_Int is_owner; 00394 00395 00396 if ( !source || !target || 00397 source->n_points != target->n_points || 00398 source->n_contours != target->n_contours ) 00399 return FT_Err_Invalid_Argument; 00400 00401 if ( source == target ) 00402 return FT_Err_Ok; 00403 00404 FT_ARRAY_COPY( target->points, source->points, source->n_points ); 00405 00406 FT_ARRAY_COPY( target->tags, source->tags, source->n_points ); 00407 00408 FT_ARRAY_COPY( target->contours, source->contours, source->n_contours ); 00409 00410 /* copy all flags, except the `FT_OUTLINE_OWNER' one */ 00411 is_owner = target->flags & FT_OUTLINE_OWNER; 00412 target->flags = source->flags; 00413 00414 target->flags &= ~FT_OUTLINE_OWNER; 00415 target->flags |= is_owner; 00416 00417 return FT_Err_Ok; 00418 } 00419 00420 00421 FT_EXPORT_DEF( FT_Error ) 00422 FT_Outline_Done_Internal( FT_Memory memory, 00423 FT_Outline* outline ) 00424 { 00425 if ( memory && outline ) 00426 { 00427 if ( outline->flags & FT_OUTLINE_OWNER ) 00428 { 00429 FT_FREE( outline->points ); 00430 FT_FREE( outline->tags ); 00431 FT_FREE( outline->contours ); 00432 } 00433 *outline = null_outline; 00434 00435 return FT_Err_Ok; 00436 } 00437 else 00438 return FT_Err_Invalid_Argument; 00439 } 00440 00441 00442 /* documentation is in ftoutln.h */ 00443 00444 FT_EXPORT_DEF( FT_Error ) 00445 FT_Outline_Done( FT_Library library, 00446 FT_Outline* outline ) 00447 { 00448 /* check for valid `outline' in FT_Outline_Done_Internal() */ 00449 00450 if ( !library ) 00451 return FT_Err_Invalid_Library_Handle; 00452 00453 return FT_Outline_Done_Internal( library->memory, outline ); 00454 } 00455 00456 00457 /* documentation is in ftoutln.h */ 00458 00459 FT_EXPORT_DEF( void ) 00460 FT_Outline_Get_CBox( const FT_Outline* outline, 00461 FT_BBox *acbox ) 00462 { 00463 FT_Pos xMin, yMin, xMax, yMax; 00464 00465 00466 if ( outline && acbox ) 00467 { 00468 if ( outline->n_points == 0 ) 00469 { 00470 xMin = 0; 00471 yMin = 0; 00472 xMax = 0; 00473 yMax = 0; 00474 } 00475 else 00476 { 00477 FT_Vector* vec = outline->points; 00478 FT_Vector* limit = vec + outline->n_points; 00479 00480 00481 xMin = xMax = vec->x; 00482 yMin = yMax = vec->y; 00483 vec++; 00484 00485 for ( ; vec < limit; vec++ ) 00486 { 00487 FT_Pos x, y; 00488 00489 00490 x = vec->x; 00491 if ( x < xMin ) xMin = x; 00492 if ( x > xMax ) xMax = x; 00493 00494 y = vec->y; 00495 if ( y < yMin ) yMin = y; 00496 if ( y > yMax ) yMax = y; 00497 } 00498 } 00499 acbox->xMin = xMin; 00500 acbox->xMax = xMax; 00501 acbox->yMin = yMin; 00502 acbox->yMax = yMax; 00503 } 00504 } 00505 00506 00507 /* documentation is in ftoutln.h */ 00508 00509 FT_EXPORT_DEF( void ) 00510 FT_Outline_Translate( const FT_Outline* outline, 00511 FT_Pos xOffset, 00512 FT_Pos yOffset ) 00513 { 00514 FT_UShort n; 00515 FT_Vector* vec; 00516 00517 00518 if ( !outline ) 00519 return; 00520 00521 vec = outline->points; 00522 00523 for ( n = 0; n < outline->n_points; n++ ) 00524 { 00525 vec->x += xOffset; 00526 vec->y += yOffset; 00527 vec++; 00528 } 00529 } 00530 00531 00532 /* documentation is in ftoutln.h */ 00533 00534 FT_EXPORT_DEF( void ) 00535 FT_Outline_Reverse( FT_Outline* outline ) 00536 { 00537 FT_UShort n; 00538 FT_Int first, last; 00539 00540 00541 if ( !outline ) 00542 return; 00543 00544 first = 0; 00545 00546 for ( n = 0; n < outline->n_contours; n++ ) 00547 { 00548 last = outline->contours[n]; 00549 00550 /* reverse point table */ 00551 { 00552 FT_Vector* p = outline->points + first; 00553 FT_Vector* q = outline->points + last; 00554 FT_Vector swap; 00555 00556 00557 while ( p < q ) 00558 { 00559 swap = *p; 00560 *p = *q; 00561 *q = swap; 00562 p++; 00563 q--; 00564 } 00565 } 00566 00567 /* reverse tags table */ 00568 { 00569 char* p = outline->tags + first; 00570 char* q = outline->tags + last; 00571 char swap; 00572 00573 00574 while ( p < q ) 00575 { 00576 swap = *p; 00577 *p = *q; 00578 *q = swap; 00579 p++; 00580 q--; 00581 } 00582 } 00583 00584 first = last + 1; 00585 } 00586 00587 outline->flags ^= FT_OUTLINE_REVERSE_FILL; 00588 } 00589 00590 00591 /* documentation is in ftoutln.h */ 00592 00593 FT_EXPORT_DEF( FT_Error ) 00594 FT_Outline_Render( FT_Library library, 00595 FT_Outline* outline, 00596 FT_Raster_Params* params ) 00597 { 00598 FT_Error error; 00599 FT_Bool update = FALSE; 00600 FT_Renderer renderer; 00601 FT_ListNode node; 00602 00603 00604 if ( !library ) 00605 return FT_Err_Invalid_Library_Handle; 00606 00607 if ( !outline || !params ) 00608 return FT_Err_Invalid_Argument; 00609 00610 renderer = library->cur_renderer; 00611 node = library->renderers.head; 00612 00613 params->source = (void*)outline; 00614 00615 error = FT_Err_Cannot_Render_Glyph; 00616 while ( renderer ) 00617 { 00618 error = renderer->raster_render( renderer->raster, params ); 00619 if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph ) 00620 break; 00621 00622 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */ 00623 /* is unsupported by the current renderer for this glyph image */ 00624 /* format */ 00625 00626 /* now, look for another renderer that supports the same */ 00627 /* format */ 00628 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 00629 &node ); 00630 update = TRUE; 00631 } 00632 00633 /* if we changed the current renderer for the glyph image format */ 00634 /* we need to select it as the next current one */ 00635 if ( !error && update && renderer ) 00636 FT_Set_Renderer( library, renderer, 0, 0 ); 00637 00638 return error; 00639 } 00640 00641 00642 /* documentation is in ftoutln.h */ 00643 00644 FT_EXPORT_DEF( FT_Error ) 00645 FT_Outline_Get_Bitmap( FT_Library library, 00646 FT_Outline* outline, 00647 const FT_Bitmap *abitmap ) 00648 { 00649 FT_Raster_Params params; 00650 00651 00652 if ( !abitmap ) 00653 return FT_Err_Invalid_Argument; 00654 00655 /* other checks are delayed to FT_Outline_Render() */ 00656 00657 params.target = abitmap; 00658 params.flags = 0; 00659 00660 if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY || 00661 abitmap->pixel_mode == FT_PIXEL_MODE_LCD || 00662 abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V ) 00663 params.flags |= FT_RASTER_FLAG_AA; 00664 00665 return FT_Outline_Render( library, outline, ¶ms ); 00666 } 00667 00668 00669 /* documentation is in freetype.h */ 00670 00671 FT_EXPORT_DEF( void ) 00672 FT_Vector_Transform( FT_Vector* vector, 00673 const FT_Matrix* matrix ) 00674 { 00675 FT_Pos xz, yz; 00676 00677 00678 if ( !vector || !matrix ) 00679 return; 00680 00681 xz = FT_MulFix( vector->x, matrix->xx ) + 00682 FT_MulFix( vector->y, matrix->xy ); 00683 00684 yz = FT_MulFix( vector->x, matrix->yx ) + 00685 FT_MulFix( vector->y, matrix->yy ); 00686 00687 vector->x = xz; 00688 vector->y = yz; 00689 } 00690 00691 00692 /* documentation is in ftoutln.h */ 00693 00694 FT_EXPORT_DEF( void ) 00695 FT_Outline_Transform( const FT_Outline* outline, 00696 const FT_Matrix* matrix ) 00697 { 00698 FT_Vector* vec; 00699 FT_Vector* limit; 00700 00701 00702 if ( !outline || !matrix ) 00703 return; 00704 00705 vec = outline->points; 00706 limit = vec + outline->n_points; 00707 00708 for ( ; vec < limit; vec++ ) 00709 FT_Vector_Transform( vec, matrix ); 00710 } 00711 00712 00713 #if 0 00714 00715 #define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \ 00716 do { \ 00717 (first) = ( c > 0 ) ? (outline)->points + \ 00718 (outline)->contours[c - 1] + 1 \ 00719 : (outline)->points; \ 00720 (last) = (outline)->points + (outline)->contours[c]; \ 00721 } while ( 0 ) 00722 00723 00724 /* Is a point in some contour? */ 00725 /* */ 00726 /* We treat every point of the contour as if it */ 00727 /* it were ON. That is, we allow false positives, */ 00728 /* but disallow false negatives. (XXX really?) */ 00729 static FT_Bool 00730 ft_contour_has( FT_Outline* outline, 00731 FT_Short c, 00732 FT_Vector* point ) 00733 { 00734 FT_Vector* first; 00735 FT_Vector* last; 00736 FT_Vector* a; 00737 FT_Vector* b; 00738 FT_UInt n = 0; 00739 00740 00741 FT_OUTLINE_GET_CONTOUR( outline, c, first, last ); 00742 00743 for ( a = first; a <= last; a++ ) 00744 { 00745 FT_Pos x; 00746 FT_Int intersect; 00747 00748 00749 b = ( a == last ) ? first : a + 1; 00750 00751 intersect = ( a->y - point->y ) ^ ( b->y - point->y ); 00752 00753 /* a and b are on the same side */ 00754 if ( intersect >= 0 ) 00755 { 00756 if ( intersect == 0 && a->y == point->y ) 00757 { 00758 if ( ( a->x <= point->x && b->x >= point->x ) || 00759 ( a->x >= point->x && b->x <= point->x ) ) 00760 return 1; 00761 } 00762 00763 continue; 00764 } 00765 00766 x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y ); 00767 00768 if ( x < point->x ) 00769 n++; 00770 else if ( x == point->x ) 00771 return 1; 00772 } 00773 00774 return ( n % 2 ); 00775 } 00776 00777 00778 static FT_Bool 00779 ft_contour_enclosed( FT_Outline* outline, 00780 FT_UShort c ) 00781 { 00782 FT_Vector* first; 00783 FT_Vector* last; 00784 FT_Short i; 00785 00786 00787 FT_OUTLINE_GET_CONTOUR( outline, c, first, last ); 00788 00789 for ( i = 0; i < outline->n_contours; i++ ) 00790 { 00791 if ( i != c && ft_contour_has( outline, i, first ) ) 00792 { 00793 FT_Vector* pt; 00794 00795 00796 for ( pt = first + 1; pt <= last; pt++ ) 00797 if ( !ft_contour_has( outline, i, pt ) ) 00798 return 0; 00799 00800 return 1; 00801 } 00802 } 00803 00804 return 0; 00805 } 00806 00807 00808 /* This version differs from the public one in that each */ 00809 /* part (contour not enclosed in another contour) of the */ 00810 /* outline is checked for orientation. This is */ 00811 /* necessary for some buggy CJK fonts. */ 00812 static FT_Orientation 00813 ft_outline_get_orientation( FT_Outline* outline ) 00814 { 00815 FT_Short i; 00816 FT_Vector* first; 00817 FT_Vector* last; 00818 FT_Orientation orient = FT_ORIENTATION_NONE; 00819 00820 00821 first = outline->points; 00822 for ( i = 0; i < outline->n_contours; i++, first = last + 1 ) 00823 { 00824 FT_Vector* point; 00825 FT_Vector* xmin_point; 00826 FT_Pos xmin; 00827 00828 00829 last = outline->points + outline->contours[i]; 00830 00831 /* skip degenerate contours */ 00832 if ( last < first + 2 ) 00833 continue; 00834 00835 if ( ft_contour_enclosed( outline, i ) ) 00836 continue; 00837 00838 xmin = first->x; 00839 xmin_point = first; 00840 00841 for ( point = first + 1; point <= last; point++ ) 00842 { 00843 if ( point->x < xmin ) 00844 { 00845 xmin = point->x; 00846 xmin_point = point; 00847 } 00848 } 00849 00850 /* check the orientation of the contour */ 00851 { 00852 FT_Vector* prev; 00853 FT_Vector* next; 00854 FT_Orientation o; 00855 00856 00857 prev = ( xmin_point == first ) ? last : xmin_point - 1; 00858 next = ( xmin_point == last ) ? first : xmin_point + 1; 00859 00860 if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) > 00861 FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) ) 00862 o = FT_ORIENTATION_POSTSCRIPT; 00863 else 00864 o = FT_ORIENTATION_TRUETYPE; 00865 00866 if ( orient == FT_ORIENTATION_NONE ) 00867 orient = o; 00868 else if ( orient != o ) 00869 return FT_ORIENTATION_NONE; 00870 } 00871 } 00872 00873 return orient; 00874 } 00875 00876 #endif /* 0 */ 00877 00878 00879 /* documentation is in ftoutln.h */ 00880 00881 FT_EXPORT_DEF( FT_Error ) 00882 FT_Outline_Embolden( FT_Outline* outline, 00883 FT_Pos strength ) 00884 { 00885 FT_Vector* points; 00886 FT_Vector v_prev, v_first, v_next, v_cur; 00887 FT_Angle rotate, angle_in, angle_out; 00888 FT_Int c, n, first; 00889 FT_Int orientation; 00890 00891 00892 if ( !outline ) 00893 return FT_Err_Invalid_Argument; 00894 00895 strength /= 2; 00896 if ( strength == 0 ) 00897 return FT_Err_Ok; 00898 00899 orientation = FT_Outline_Get_Orientation( outline ); 00900 if ( orientation == FT_ORIENTATION_NONE ) 00901 { 00902 if ( outline->n_contours ) 00903 return FT_Err_Invalid_Argument; 00904 else 00905 return FT_Err_Ok; 00906 } 00907 00908 if ( orientation == FT_ORIENTATION_TRUETYPE ) 00909 rotate = -FT_ANGLE_PI2; 00910 else 00911 rotate = FT_ANGLE_PI2; 00912 00913 points = outline->points; 00914 00915 first = 0; 00916 for ( c = 0; c < outline->n_contours; c++ ) 00917 { 00918 int last = outline->contours[c]; 00919 00920 00921 v_first = points[first]; 00922 v_prev = points[last]; 00923 v_cur = v_first; 00924 00925 for ( n = first; n <= last; n++ ) 00926 { 00927 FT_Vector in, out; 00928 FT_Angle angle_diff; 00929 FT_Pos d; 00930 FT_Fixed scale; 00931 00932 00933 if ( n < last ) 00934 v_next = points[n + 1]; 00935 else 00936 v_next = v_first; 00937 00938 /* compute the in and out vectors */ 00939 in.x = v_cur.x - v_prev.x; 00940 in.y = v_cur.y - v_prev.y; 00941 00942 out.x = v_next.x - v_cur.x; 00943 out.y = v_next.y - v_cur.y; 00944 00945 angle_in = FT_Atan2( in.x, in.y ); 00946 angle_out = FT_Atan2( out.x, out.y ); 00947 angle_diff = FT_Angle_Diff( angle_in, angle_out ); 00948 scale = FT_Cos( angle_diff / 2 ); 00949 00950 if ( scale < 0x4000L && scale > -0x4000L ) 00951 in.x = in.y = 0; 00952 else 00953 { 00954 d = FT_DivFix( strength, scale ); 00955 00956 FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate ); 00957 } 00958 00959 outline->points[n].x = v_cur.x + strength + in.x; 00960 outline->points[n].y = v_cur.y + strength + in.y; 00961 00962 v_prev = v_cur; 00963 v_cur = v_next; 00964 } 00965 00966 first = last + 1; 00967 } 00968 00969 return FT_Err_Ok; 00970 } 00971 00972 00973 /* documentation is in ftoutln.h */ 00974 00975 FT_EXPORT_DEF( FT_Orientation ) 00976 FT_Outline_Get_Orientation( FT_Outline* outline ) 00977 { 00978 FT_Pos xmin = 32768L; 00979 FT_Pos xmin_ymin = 32768L; 00980 FT_Pos xmin_ymax = -32768L; 00981 FT_Vector* xmin_first = NULL; 00982 FT_Vector* xmin_last = NULL; 00983 00984 short* contour; 00985 00986 FT_Vector* first; 00987 FT_Vector* last; 00988 FT_Vector* prev; 00989 FT_Vector* point; 00990 00991 int i; 00992 FT_Pos ray_y[3]; 00993 FT_Orientation result[3] = 00994 { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE }; 00995 00996 00997 if ( !outline || outline->n_points <= 0 ) 00998 return FT_ORIENTATION_TRUETYPE; 00999 01000 /* We use the nonzero winding rule to find the orientation. */ 01001 /* Since glyph outlines behave much more `regular' than arbitrary */ 01002 /* cubic or quadratic curves, this test deals with the polygon */ 01003 /* only which is spanned up by the control points. */ 01004 01005 first = outline->points; 01006 for ( contour = outline->contours; 01007 contour < outline->contours + outline->n_contours; 01008 contour++, first = last + 1 ) 01009 { 01010 FT_Pos contour_xmin = 32768L; 01011 FT_Pos contour_xmax = -32768L; 01012 FT_Pos contour_ymin = 32768L; 01013 FT_Pos contour_ymax = -32768L; 01014 01015 01016 last = outline->points + *contour; 01017 01018 /* skip degenerate contours */ 01019 if ( last < first + 2 ) 01020 continue; 01021 01022 for ( point = first; point <= last; ++point ) 01023 { 01024 if ( point->x < contour_xmin ) 01025 contour_xmin = point->x; 01026 01027 if ( point->x > contour_xmax ) 01028 contour_xmax = point->x; 01029 01030 if ( point->y < contour_ymin ) 01031 contour_ymin = point->y; 01032 01033 if ( point->y > contour_ymax ) 01034 contour_ymax = point->y; 01035 } 01036 01037 if ( contour_xmin < xmin && 01038 contour_xmin != contour_xmax && 01039 contour_ymin != contour_ymax ) 01040 { 01041 xmin = contour_xmin; 01042 xmin_ymin = contour_ymin; 01043 xmin_ymax = contour_ymax; 01044 xmin_first = first; 01045 xmin_last = last; 01046 } 01047 } 01048 01049 if ( xmin == 32768L ) 01050 return FT_ORIENTATION_TRUETYPE; 01051 01052 ray_y[0] = ( xmin_ymin * 3 + xmin_ymax ) >> 2; 01053 ray_y[1] = ( xmin_ymin + xmin_ymax ) >> 1; 01054 ray_y[2] = ( xmin_ymin + xmin_ymax * 3 ) >> 2; 01055 01056 for ( i = 0; i < 3; i++ ) 01057 { 01058 FT_Pos left_x; 01059 FT_Pos right_x; 01060 FT_Vector* left1; 01061 FT_Vector* left2; 01062 FT_Vector* right1; 01063 FT_Vector* right2; 01064 01065 01066 RedoRay: 01067 left_x = 32768L; 01068 right_x = -32768L; 01069 01070 left1 = left2 = right1 = right2 = NULL; 01071 01072 prev = xmin_last; 01073 for ( point = xmin_first; point <= xmin_last; prev = point, ++point ) 01074 { 01075 FT_Pos tmp_x; 01076 01077 01078 if ( point->y == ray_y[i] || prev->y == ray_y[i] ) 01079 { 01080 ray_y[i]++; 01081 goto RedoRay; 01082 } 01083 01084 if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) || 01085 ( point->y > ray_y[i] && prev->y > ray_y[i] ) ) 01086 continue; 01087 01088 tmp_x = FT_MulDiv( point->x - prev->x, 01089 ray_y[i] - prev->y, 01090 point->y - prev->y ) + prev->x; 01091 01092 if ( tmp_x < left_x ) 01093 { 01094 left_x = tmp_x; 01095 left1 = prev; 01096 left2 = point; 01097 } 01098 01099 if ( tmp_x > right_x ) 01100 { 01101 right_x = tmp_x; 01102 right1 = prev; 01103 right2 = point; 01104 } 01105 } 01106 01107 if ( left1 && right1 ) 01108 { 01109 if ( left1->y < left2->y && right1->y > right2->y ) 01110 result[i] = FT_ORIENTATION_TRUETYPE; 01111 else if ( left1->y > left2->y && right1->y < right2->y ) 01112 result[i] = FT_ORIENTATION_POSTSCRIPT; 01113 else 01114 result[i] = FT_ORIENTATION_NONE; 01115 } 01116 } 01117 01118 if ( result[0] != FT_ORIENTATION_NONE && 01119 ( result[0] == result[1] || result[0] == result[2] ) ) 01120 return result[0]; 01121 01122 if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] ) 01123 return result[1]; 01124 01125 return FT_ORIENTATION_TRUETYPE; 01126 } 01127 01128 01129 /* END */ Generated on Sun May 27 2012 04:33:35 for ReactOS by
1.7.6.1
|