1f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/***************************************************************************/ 2f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* */ 3f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* afhints.c */ 4f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* */ 5f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* Auto-fitter hinting routines (body). */ 6f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* */ 70a0c22569deab933df21127e75db5c81f724f292Werner Lemberg/* Copyright 2003-2018 by */ 8f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* */ 10f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* This file is part of the FreeType project, and may only be used, */ 11f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* modified, and distributed under the terms of the FreeType project */ 12f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* this file you indicate that you have read the license and */ 14f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* understand and accept it fully. */ 15f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/* */ 16f13516c8321b386227414be01e707563e852fc0dWerner Lemberg/***************************************************************************/ 17f13516c8321b386227414be01e707563e852fc0dWerner Lemberg 18f13516c8321b386227414be01e707563e852fc0dWerner Lemberg 198bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg#include "afhints.h" 20a37745bad4e46c5ad0e690150b0ec8081ff81c90Werner Lemberg#include "aferrors.h" 21effd15de89b8c11f933609888c8370dc1d6fe948David Turner#include FT_INTERNAL_CALC_H 22b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg#include FT_INTERNAL_DEBUG_H 23b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg 24b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg 25b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg /*************************************************************************/ 26b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg /* */ 27b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 28b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 29b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg /* messages during execution. */ 30b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg /* */ 31b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg#undef FT_COMPONENT 32b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg#define FT_COMPONENT trace_afhints 33b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 34111b5aefcaf1156fe4f25b3f0f166f3cbc644ac3Werner Lemberg 35c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Get new segment for given axis. */ 36c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 37b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_LOCAL_DEF( FT_Error ) 38b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner af_axis_hints_new_segment( AF_AxisHints axis, 39b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_Memory memory, 40b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner AF_Segment *asegment ) 41b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner { 42e3c9301581a450fae5db73a3b94b10ed6a0aeb5eWerner Lemberg FT_Error error = FT_Err_Ok; 43b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner AF_Segment segment = NULL; 44b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 45b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 4656ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( axis->num_segments < AF_SEGMENTS_EMBEDDED ) 4756ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 484441f7b24675fbd7d91f794f5d54e6c1ff168439Werner Lemberg if ( !axis->segments ) 4956ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 5056ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod axis->segments = axis->embedded.segments; 5156ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod axis->max_segments = AF_SEGMENTS_EMBEDDED; 5256ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 5356ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 5456ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod else if ( axis->num_segments >= axis->max_segments ) 55b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner { 56b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_Int old_max = axis->max_segments; 57b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_Int new_max = old_max; 5887054758fb1a416a045690d38dcd3d2b05ab1ac1Suzuki, Toshiya (鈴木俊哉) FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) ); 59b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 60b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 61b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner if ( old_max >= big_max ) 62b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner { 63059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg error = FT_THROW( Out_Of_Memory ); 64b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner goto Exit; 65b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner } 66b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 670529ba8d2579dcff1c287c40ea491ebc39fa24f5David Turner new_max += ( new_max >> 2 ) + 4; 68b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner if ( new_max < old_max || new_max > big_max ) 69b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner new_max = big_max; 70b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 7156ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( axis->segments == axis->embedded.segments ) 7256ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 7356ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( FT_NEW_ARRAY( axis->segments, new_max ) ) 7456ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod goto Exit; 7556ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod ft_memcpy( axis->segments, axis->embedded.segments, 7656ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod sizeof ( axis->embedded.segments ) ); 7756ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 7856ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod else 7956ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 8056ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) ) 8156ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod goto Exit; 8256ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 83b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 84b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner axis->max_segments = new_max; 85b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner } 86b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 87b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner segment = axis->segments + axis->num_segments++; 88b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 89b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner Exit: 90b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner *asegment = segment; 91b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner return error; 92b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner } 93b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 94b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 95387a9fe73dabcac45a11a55bb27fa0e8e7d81437Werner Lemberg /* Get new edge for given axis, direction, and position, */ 96387a9fe73dabcac45a11a55bb27fa0e8e7d81437Werner Lemberg /* without initializing the edge itself. */ 97c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 98f13516c8321b386227414be01e707563e852fc0dWerner Lemberg FT_LOCAL( FT_Error ) 99b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner af_axis_hints_new_edge( AF_AxisHints axis, 100b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_Int fpos, 101b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Direction dir, 1022e09812c5121413fa29692a46b310983cb3de3e8Werner Lemberg FT_Bool top_to_bottom_hinting, 103b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_Memory memory, 104b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg AF_Edge *anedge ) 105b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner { 106e3c9301581a450fae5db73a3b94b10ed6a0aeb5eWerner Lemberg FT_Error error = FT_Err_Ok; 107b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg AF_Edge edge = NULL; 108b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg AF_Edge edges; 109b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 110b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 11156ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( axis->num_edges < AF_EDGES_EMBEDDED ) 11256ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 1134441f7b24675fbd7d91f794f5d54e6c1ff168439Werner Lemberg if ( !axis->edges ) 11456ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 11556ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod axis->edges = axis->embedded.edges; 11656ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod axis->max_edges = AF_EDGES_EMBEDDED; 11756ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 11856ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 11956ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod else if ( axis->num_edges >= axis->max_edges ) 120b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner { 121b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_Int old_max = axis->max_edges; 122b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner FT_Int new_max = old_max; 12387054758fb1a416a045690d38dcd3d2b05ab1ac1Suzuki, Toshiya (鈴木俊哉) FT_Int big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) ); 124b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 125b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 126b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner if ( old_max >= big_max ) 127b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner { 128059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg error = FT_THROW( Out_Of_Memory ); 129b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner goto Exit; 130b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner } 131b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 1320529ba8d2579dcff1c287c40ea491ebc39fa24f5David Turner new_max += ( new_max >> 2 ) + 4; 133b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner if ( new_max < old_max || new_max > big_max ) 134b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner new_max = big_max; 135b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 13656ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( axis->edges == axis->embedded.edges ) 13756ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 13856ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( FT_NEW_ARRAY( axis->edges, new_max ) ) 13956ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod goto Exit; 14056ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod ft_memcpy( axis->edges, axis->embedded.edges, 14156ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod sizeof ( axis->embedded.edges ) ); 14256ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 14356ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod else 14456ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod { 14556ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) ) 14656ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod goto Exit; 14756ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod } 148b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 149b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner axis->max_edges = new_max; 150b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner } 151b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 152b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner edges = axis->edges; 153b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner edge = edges + axis->num_edges; 154b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 155b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner while ( edge > edges ) 156b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner { 1572e09812c5121413fa29692a46b310983cb3de3e8Werner Lemberg if ( top_to_bottom_hinting ? ( edge[-1].fpos > fpos ) 1582e09812c5121413fa29692a46b310983cb3de3e8Werner Lemberg : ( edge[-1].fpos < fpos ) ) 159b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner break; 160b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 16149e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg /* we want the edge with same position and minor direction */ 16249e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg /* to appear before those in the major one in the list */ 16349e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg if ( edge[-1].fpos == fpos && dir == axis->major_dir ) 164b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner break; 165b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 166b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner edge[0] = edge[-1]; 167b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner edge--; 168b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner } 169b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 170b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner axis->num_edges++; 171b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 172b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner Exit: 173b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg *anedge = edge; 174b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner return error; 175b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner } 176b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 177b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 178d503b1bce25d61a7ed6c262e013b6ceb3b627045Werner Lemberg#ifdef FT_DEBUG_AUTOFIT 1798bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 18024d72a1b0b3d7227000a8b9a54f3513f99c7fe4eWerner Lemberg#include FT_CONFIG_STANDARD_LIBRARY_H 1818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 18252166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg /* The dump functions are used in the `ftgrid' demo program, too. */ 18352166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg#define AF_DUMP( varformat ) \ 18452166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg do \ 18552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg { \ 18652166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg if ( to_stdout ) \ 18752166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg printf varformat; \ 18852166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg else \ 18952166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg FT_TRACE7( varformat ); \ 19052166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg } while ( 0 ) 19152166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg 19252166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg 193b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg static const char* 194b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg af_dir_str( AF_Direction dir ) 1958bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1968bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg const char* result; 1978bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 198b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 199b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg switch ( dir ) 2008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 201b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg case AF_DIR_UP: 202b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg result = "up"; 203b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg break; 204b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg case AF_DIR_DOWN: 205b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg result = "down"; 206b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg break; 207b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg case AF_DIR_LEFT: 208b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg result = "left"; 209b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg break; 210b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg case AF_DIR_RIGHT: 211b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg result = "right"; 212b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg break; 213b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg default: 214b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg result = "none"; 2158bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 216b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 2178bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg return result; 2188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 2198bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 220b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 221a632b5f4064873ab7f21b749f93332387bc47f76Werner Lemberg#define AF_INDEX_NUM( ptr, base ) (int)( (ptr) ? ( (ptr) - (base) ) : -1 ) 222b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 2238bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 2247f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg static char* 2257f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( char* p, 2267f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int idx ) 2277f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 2287f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg if ( idx == -1 ) 2297f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 2307f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg p[0] = '-'; 2317f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg p[1] = '-'; 2327f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg p[2] = '\0'; 2337f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 2347f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg else 2357f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg ft_sprintf( p, "%d", idx ); 2367f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2377f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg return p; 2387f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 2397f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2407f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2417f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg static int 2427f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_get_segment_index( AF_GlyphHints hints, 2437f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int point_idx, 2447f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int dimension ) 2457f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 2467f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_AxisHints axis = &hints->axis[dimension]; 2477f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_Point point = hints->points + point_idx; 2487f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_Segment segments = axis->segments; 2497f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_Segment limit = segments + axis->num_segments; 2507f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_Segment segment; 2517f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2527f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2537f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg for ( segment = segments; segment < limit; segment++ ) 2547f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 2557f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg if ( segment->first <= segment->last ) 2567f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 2577f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg if ( point >= segment->first && point <= segment->last ) 2587f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg break; 2597f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 2607f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg else 2617f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 26268fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg AF_Point p = segment->first; 26368fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg 26468fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg 26568fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg for (;;) 26668fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg { 26768fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg if ( point == p ) 26868fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg goto Exit; 26968fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg 27068fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg if ( p == segment->last ) 27168fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg break; 27268fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg 27368fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg p = p->next; 27468fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg } 2757f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 2767f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 2777f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 27868fb4789a582561606fafbe51e7a217598bb35ecWerner Lemberg Exit: 2797f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg if ( segment == limit ) 2807f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg return -1; 2817f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2827f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg return (int)( segment - segments ); 2837f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 2847f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2857f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2867f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg static int 2877f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_get_edge_index( AF_GlyphHints hints, 2887f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int segment_idx, 2897f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int dimension ) 2907f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 2917f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_AxisHints axis = &hints->axis[dimension]; 2927f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_Edge edges = axis->edges; 2937f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg AF_Segment segment = axis->segments + segment_idx; 2947f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2957f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2967f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg return segment_idx == -1 ? -1 : AF_INDEX_NUM( segment->edge, edges ); 2977f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 2987f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 2997f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 3008bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#ifdef __cplusplus 3018bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg extern "C" { 3028bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#endif 3038bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg void 30452166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg af_glyph_hints_dump_points( AF_GlyphHints hints, 30552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg FT_Bool to_stdout ) 3068bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 307baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg AF_Point points = hints->points; 308baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg AF_Point limit = points + hints->num_points; 309baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg AF_Point* contour = hints->contours; 310baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg AF_Point* climit = contour + hints->num_contours; 311baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg AF_Point point; 3128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 313b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 314a2fa657a03f17ef9cd79b4ad529f08cfe676aa1cWerner Lemberg AF_DUMP(( "Table of points:\n" )); 315a2fa657a03f17ef9cd79b4ad529f08cfe676aa1cWerner Lemberg 316a2fa657a03f17ef9cd79b4ad529f08cfe676aa1cWerner Lemberg if ( hints->num_points ) 3178768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg { 318709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg AF_DUMP(( " index hedge hseg vedge vseg flags " 3198768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg /* " XXXXX XXXXX XXXXX XXXXX XXXXX XXXXXX" */ 320baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg " xorg yorg xscale yscale xfit yfit" )); 3218768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg /* " XXXXX XXXXX XXXX.XX XXXX.XX XXXX.XX XXXX.XX" */ 3228768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg } 323a2fa657a03f17ef9cd79b4ad529f08cfe676aa1cWerner Lemberg else 324a2fa657a03f17ef9cd79b4ad529f08cfe676aa1cWerner Lemberg AF_DUMP(( " (none)\n" )); 325b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 3268bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( point = points; point < limit; point++ ) 3277f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg { 3287f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int point_idx = AF_INDEX_NUM( point, points ); 3297f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int segment_idx_0 = af_get_segment_index( hints, point_idx, 0 ); 3307f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg int segment_idx_1 = af_get_segment_index( hints, point_idx, 1 ); 3317f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 3327f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg char buf1[16], buf2[16], buf3[16], buf4[16]; 3337f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 3347f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 335baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg /* insert extra newline at the beginning of a contour */ 336baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg if ( contour < climit && *contour == point ) 337baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg { 338baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg AF_DUMP(( "\n" )); 339baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg contour++; 340baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg } 341baa41ff204e581fee745d0a2badbe62b35509e58Werner Lemberg 342709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg AF_DUMP(( " %5d %5s %5s %5s %5s %s" 3437f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg " %5d %5d %7.2f %7.2f %7.2f %7.2f\n", 3447f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg point_idx, 3457f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf1, 3467f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_get_edge_index( hints, segment_idx_1, 1 ) ), 3477f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf2, segment_idx_1 ), 3487f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf3, 3497f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_get_edge_index( hints, segment_idx_0, 0 ) ), 3507f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf4, segment_idx_0 ), 351709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg ( point->flags & AF_FLAG_NEAR ) 352709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg ? " near " 353709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg : ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) 354709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg ? " weak " 355709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg : "strong", 3567f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 35752166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg point->fx, 35852166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg point->fy, 35952166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg point->ox / 64.0, 36052166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg point->oy / 64.0, 36152166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg point->x / 64.0, 3627f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg point->y / 64.0 )); 3637f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg } 36452166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_DUMP(( "\n" )); 3658bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 3668bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#ifdef __cplusplus 3678bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg } 3688bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#endif 3698bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 3708bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 371b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner static const char* 37281e5ff53a89b454a3984a7181516dfb4cb22187aWerner Lemberg af_edge_flags_to_string( FT_UInt flags ) 373b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 37449e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg static char temp[32]; 37549e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg int pos = 0; 37649e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg 377b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 378b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( flags & AF_EDGE_ROUND ) 379b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 380e85baf4f8e9ba09fd16d31808b6a5d31735b13bfWerner Lemberg ft_memcpy( temp + pos, "round", 5 ); 381b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner pos += 5; 382b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 383b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( flags & AF_EDGE_SERIF ) 384b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 38549e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg if ( pos > 0 ) 386b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner temp[pos++] = ' '; 387e85baf4f8e9ba09fd16d31808b6a5d31735b13bfWerner Lemberg ft_memcpy( temp + pos, "serif", 5 ); 388b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner pos += 5; 389b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 39049e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg if ( pos == 0 ) 391b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner return "normal"; 392b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 393b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg temp[pos] = '\0'; 39449e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg 395b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner return temp; 396b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 397b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 39849e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg 399c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Dump the array of linked segments. */ 400c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 4018bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#ifdef __cplusplus 4028bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg extern "C" { 4038bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#endif 4048bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg void 40552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg af_glyph_hints_dump_segments( AF_GlyphHints hints, 40652166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg FT_Bool to_stdout ) 4078bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 40823df31adcc598c4da75ea6ed3cf11bd95a6e3ba9Werner Lemberg FT_Int dimension; 409b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 4108bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 4118bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( dimension = 1; dimension >= 0; dimension-- ) 4128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 413b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg AF_AxisHints axis = &hints->axis[dimension]; 414fd5ae9599ad674db14a3730f2a07e11e0407b182Werner Lemberg AF_Point points = hints->points; 415fd5ae9599ad674db14a3730f2a07e11e0407b182Werner Lemberg AF_Edge edges = axis->edges; 4168bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Segment segments = axis->segments; 4178bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Segment limit = segments + axis->num_segments; 4188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Segment seg; 4198bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 4207f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg char buf1[16], buf2[16], buf3[16]; 4217f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 4228bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 42352166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_DUMP(( "Table of %s segments:\n", 42452166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg dimension == AF_DIMENSION_HORZ ? "vertical" 42552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg : "horizontal" )); 426eed830614f280406f4c4784d4b22429b8c199cb8Werner Lemberg if ( axis->num_segments ) 4278768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg { 4281831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg AF_DUMP(( " index pos delta dir from to " 4298768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg /* " XXXXX XXXXX XXXXX XXXXX XXXX XXXX" */ 4301831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg " link serif edge" 4318768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg /* " XXXX XXXXX XXXX" */ 4327f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg " height extra flags\n" )); 4338768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg /* " XXXXXX XXXXX XXXXXXXXXXX" */ 4348768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg } 435fd5ae9599ad674db14a3730f2a07e11e0407b182Werner Lemberg else 43652166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_DUMP(( " (none)\n" )); 4378bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 4388bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( seg = segments; seg < limit; seg++ ) 4391831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg AF_DUMP(( " %5d %5d %5d %5s %4d %4d" 4407f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg " %4s %5s %4s" 4417f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg " %6d %5d %11s\n", 442a632b5f4064873ab7f21b749f93332387bc47f76Werner Lemberg AF_INDEX_NUM( seg, segments ), 4431831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg seg->pos, 4441831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg seg->delta, 44552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg af_dir_str( (AF_Direction)seg->dir ), 44652166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_INDEX_NUM( seg->first, points ), 44752166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_INDEX_NUM( seg->last, points ), 4487f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 4497f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf1, AF_INDEX_NUM( seg->link, segments ) ), 4507f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf2, AF_INDEX_NUM( seg->serif, segments ) ), 4517f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf3, AF_INDEX_NUM( seg->edge, edges ) ), 4527f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 45352166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg seg->height, 45452166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg seg->height - ( seg->max_coord - seg->min_coord ), 45581e5ff53a89b454a3984a7181516dfb4cb22187aWerner Lemberg af_edge_flags_to_string( seg->flags ) )); 45652166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_DUMP(( "\n" )); 4578bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 4588bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 4598bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#ifdef __cplusplus 4608bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg } 4618bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#endif 4628bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 4638bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 4643a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg /* Fetch number of segments. */ 4653a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 4663a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#ifdef __cplusplus 4673a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg extern "C" { 4683a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#endif 4693a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg FT_Error 4703a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg af_glyph_hints_get_num_segments( AF_GlyphHints hints, 4713a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg FT_Int dimension, 4723a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg FT_Int* num_segments ) 4733a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg { 4743a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg AF_Dimension dim; 4753a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg AF_AxisHints axis; 4763a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 4773a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 4783a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT; 4793a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 4803a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg axis = &hints->axis[dim]; 4813a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg *num_segments = axis->num_segments; 4823a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 483e3c9301581a450fae5db73a3b94b10ed6a0aeb5eWerner Lemberg return FT_Err_Ok; 4843a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg } 4853a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#ifdef __cplusplus 4863a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg } 4873a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#endif 4883a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 4893a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 4903a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg /* Fetch offset of segments into user supplied offset array. */ 4913a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 4923a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#ifdef __cplusplus 4933a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg extern "C" { 4943a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#endif 4953a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg FT_Error 4963a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg af_glyph_hints_get_segment_offset( AF_GlyphHints hints, 4973a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg FT_Int dimension, 4983a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg FT_Int idx, 4995c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg FT_Pos *offset, 5005c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg FT_Bool *is_blue, 5015c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg FT_Pos *blue_offset ) 5023a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg { 5033a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg AF_Dimension dim; 5043a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg AF_AxisHints axis; 5053a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg AF_Segment seg; 5063a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 5073a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 5083a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg if ( !offset ) 509059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg return FT_THROW( Invalid_Argument ); 5103a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 5113a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT; 5123a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 5133a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg axis = &hints->axis[dim]; 5143a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 5153a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg if ( idx < 0 || idx >= axis->num_segments ) 516059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg return FT_THROW( Invalid_Argument ); 5173a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 5185c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg seg = &axis->segments[idx]; 5190ab2b62d3fa6b3c5a50ece8b322bf21cc0e38d52Werner Lemberg *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->fx 5200ab2b62d3fa6b3c5a50ece8b322bf21cc0e38d52Werner Lemberg : seg->first->fy; 5215c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg if ( seg->edge ) 5225c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg *is_blue = (FT_Bool)( seg->edge->blue_edge != 0 ); 5235c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg else 5245c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg *is_blue = FALSE; 5255c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg 5265c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg if ( *is_blue ) 5270ab2b62d3fa6b3c5a50ece8b322bf21cc0e38d52Werner Lemberg *blue_offset = seg->edge->blue_edge->org; 5285c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg else 5295c7f5500e89824dad3888a02cd9770e58c44230eWerner Lemberg *blue_offset = 0; 5303a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 531e3c9301581a450fae5db73a3b94b10ed6a0aeb5eWerner Lemberg return FT_Err_Ok; 5323a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg } 5333a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#ifdef __cplusplus 5343a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg } 5353a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg#endif 5363a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 5373a0844c8ef274a1dff8594164579a093435fb286Werner Lemberg 538c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Dump the array of linked edges. */ 539c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 5408bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#ifdef __cplusplus 5418bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg extern "C" { 5428bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#endif 5438bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg void 54452166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg af_glyph_hints_dump_edges( AF_GlyphHints hints, 54552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg FT_Bool to_stdout ) 5468bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 547b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_Int dimension; 548b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 5498bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 5508bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( dimension = 1; dimension >= 0; dimension-- ) 5518bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 552b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg AF_AxisHints axis = &hints->axis[dimension]; 5538bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge edges = axis->edges; 5548bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge limit = edges + axis->num_edges; 5558bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge edge; 5568bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 5577f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg char buf1[16], buf2[16]; 5587f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 559b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 560b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /* 561b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * note: AF_DIMENSION_HORZ corresponds to _vertical_ edges 562c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg * since they have a constant X coordinate. 563b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg */ 5641831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg if ( dimension == AF_DIMENSION_HORZ ) 5651831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n", 5661831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg "vertical", 5671831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg 65536.0 * 64.0 / hints->x_scale, 5681831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg 10.0 * hints->x_scale / 65536.0 / 64.0 )); 5691831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg else 5701831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg AF_DUMP(( "Table of %s edges (1px=%.2fu, 10u=%.2fpx):\n", 5711831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg "horizontal", 5721831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg 65536.0 * 64.0 / hints->y_scale, 5731831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg 10.0 * hints->y_scale / 65536.0 / 64.0 )); 5741831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg 575fd5ae9599ad674db14a3730f2a07e11e0407b182Werner Lemberg if ( axis->num_edges ) 5768768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg { 5771831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg AF_DUMP(( " index pos dir link serif" 5788768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg /* " XXXXX XXXX.XX XXXXX XXXX XXXXX" */ 5791831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg " blue opos pos flags\n" )); 5808768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg /* " X XXXX.XX XXXX.XX XXXXXXXXXXX" */ 5818768536c89d6bb3e747bc69a7c2c1e58d2ed4aa9Werner Lemberg } 582fd5ae9599ad674db14a3730f2a07e11e0407b182Werner Lemberg else 58352166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_DUMP(( " (none)\n" )); 5848bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 5858bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( edge = edges; edge < limit; edge++ ) 5861831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg AF_DUMP(( " %5d %7.2f %5s %4s %5s" 5871831e6f0689c8de6340774de1ad00fd3bb6ff924Werner Lemberg " %c %7.2f %7.2f %11s\n", 588a632b5f4064873ab7f21b749f93332387bc47f76Werner Lemberg AF_INDEX_NUM( edge, edges ), 58952166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg (int)edge->opos / 64.0, 59052166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg af_dir_str( (AF_Direction)edge->dir ), 5917f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf1, AF_INDEX_NUM( edge->link, edges ) ), 5927f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg af_print_idx( buf2, AF_INDEX_NUM( edge->serif, edges ) ), 5937f00fa64627bb57042ec62aa2ec938f679e097c1Werner Lemberg 59452166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg edge->blue_edge ? 'y' : 'n', 59552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg edge->opos / 64.0, 59652166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg edge->pos / 64.0, 59781e5ff53a89b454a3984a7181516dfb4cb22187aWerner Lemberg af_edge_flags_to_string( edge->flags ) )); 59852166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg AF_DUMP(( "\n" )); 5998bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 6008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 6018bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#ifdef __cplusplus 6028bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg } 6038bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg#endif 6048bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 60552166ab0a7e51ebedd144e8cac546a3f732c77b1Werner Lemberg#undef AF_DUMP 6068bd77f9030a718daf6526ce631e9e79fd62a95bdWerner Lemberg 607d503b1bce25d61a7ed6c262e013b6ceb3b627045Werner Lemberg#endif /* !FT_DEBUG_AUTOFIT */ 6088bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 6098bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 610c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Compute the direction value of a given vector. */ 611c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 6128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( AF_Direction ) 6138bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_direction_compute( FT_Pos dx, 6148bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_Pos dy ) 6158bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 616281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner FT_Pos ll, ss; /* long and short arm lengths */ 617281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner AF_Direction dir; /* candidate direction */ 6189fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner 619545c4e566e9785ba3c84062e211d21aeb5be989aWerner Lemberg 620281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner if ( dy >= dx ) 6219fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner { 622281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner if ( dy >= -dx ) 6239fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner { 624281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner dir = AF_DIR_UP; 625281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner ll = dy; 626281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner ss = dx; 6279fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner } 628281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner else 6299fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner { 630281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner dir = AF_DIR_LEFT; 631281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner ll = -dx; 632281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner ss = dy; 6339fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner } 6349fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner } 635281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner else /* dy < dx */ 6369fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner { 637281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner if ( dy >= -dx ) 6389fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner { 639281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner dir = AF_DIR_RIGHT; 640281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner ll = dx; 641281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner ss = dy; 6429fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner } 643281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner else 6449fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner { 645281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner dir = AF_DIR_DOWN; 646886f4d049391993197b409a9038138a8208dd5feAlexei Podtelezhnikov (Алексей Подтележников) ll = -dy; 647281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner ss = dx; 6489fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner } 6499fbd2ab8849d2517f2e7f4ce1af3c5a77893cbe5David Turner } 650cee37a3b0a34c88caa981f9ef8cd3080d1fe0defWerner Lemberg 651886f4d049391993197b409a9038138a8208dd5feAlexei Podtelezhnikov (Алексей Подтележников) /* return no direction if arm lengths do not differ enough */ 652e8da532d2a87a2210dc8ddc07966dcf01dd07bd7Werner Lemberg /* (value 14 is heuristic, corresponding to approx. 4.1 degrees) */ 653886f4d049391993197b409a9038138a8208dd5feAlexei Podtelezhnikov (Алексей Подтележников) /* the long arm is never negative */ 654886f4d049391993197b409a9038138a8208dd5feAlexei Podtelezhnikov (Алексей Подтележников) if ( ll <= 14 * FT_ABS( ss ) ) 655281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner dir = AF_DIR_NONE; 656cee37a3b0a34c88caa981f9ef8cd3080d1fe0defWerner Lemberg 657281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner return dir; 6588bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 6598bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 6608bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 6618bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( void ) 6628bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_glyph_hints_init( AF_GlyphHints hints, 6638bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_Memory memory ) 6648bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 6656f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod /* no need to initialize the embedded items */ 6666f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod FT_MEM_ZERO( hints, sizeof ( *hints ) - sizeof ( hints->embedded ) ); 6678bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->memory = memory; 6688bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 6698bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 6708bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 6718bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( void ) 6728bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_glyph_hints_done( AF_GlyphHints hints ) 6738bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 67416217e5f22127cbe3aed6375b446629228098b90Werner Lemberg FT_Memory memory; 675b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg int dim; 6768bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 677b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 678b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg if ( !( hints && hints->memory ) ) 679b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg return; 680b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg 68116217e5f22127cbe3aed6375b446629228098b90Werner Lemberg memory = hints->memory; 68216217e5f22127cbe3aed6375b446629228098b90Werner Lemberg 683b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg /* 684b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg * note that we don't need to free the segment and edge 685b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg * buffers since they are really within the hints->points array 686b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg */ 687b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) 688b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg { 689b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg AF_AxisHints axis = &hints->axis[dim]; 690b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 6918bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 692b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg axis->num_segments = 0; 693b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg axis->max_segments = 0; 69456ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( axis->segments != axis->embedded.segments ) 69556ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod FT_FREE( axis->segments ); 696b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner 697b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg axis->num_edges = 0; 698b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg axis->max_edges = 0; 69956ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod if ( axis->edges != axis->embedded.edges ) 70056ddafa01ce251d2f1f3adde3b0f72dd8ff7a405Behdad Esfahbod FT_FREE( axis->edges ); 701b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg } 7028bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 7036f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod if ( hints->contours != hints->embedded.contours ) 7046f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod FT_FREE( hints->contours ); 705b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg hints->max_contours = 0; 706b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg hints->num_contours = 0; 7078bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 7086f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod if ( hints->points != hints->embedded.points ) 7096f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod FT_FREE( hints->points ); 710b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg hints->max_points = 0; 7116f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod hints->num_points = 0; 7128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 713b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg hints->memory = NULL; 7148bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 7158bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 7168bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 717c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Reset metrics. */ 718c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 719e664efadddc49bee32b337571e329f150006a84bDavid Turner FT_LOCAL_DEF( void ) 7203f91cb338b860307b4db874e703bbdf96a8750c6Werner Lemberg af_glyph_hints_rescale( AF_GlyphHints hints, 7213f91cb338b860307b4db874e703bbdf96a8750c6Werner Lemberg AF_StyleMetrics metrics ) 722e664efadddc49bee32b337571e329f150006a84bDavid Turner { 7235b5f382b7d093e085d41be95cd73075acb5cd1a2David Turner hints->metrics = metrics; 7245b5f382b7d093e085d41be95cd73075acb5cd1a2David Turner hints->scaler_flags = metrics->scaler.flags; 725e664efadddc49bee32b337571e329f150006a84bDavid Turner } 726e664efadddc49bee32b337571e329f150006a84bDavid Turner 727e664efadddc49bee32b337571e329f150006a84bDavid Turner 728c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Recompute all AF_Point in AF_GlyphHints from the definitions */ 729c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* in a source outline. */ 730c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 7318bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( FT_Error ) 732b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg af_glyph_hints_reload( AF_GlyphHints hints, 73309344385ee652cb8df33d35f07627c93e827f10dWerner Lemberg FT_Outline* outline ) 7348bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 735e3c9301581a450fae5db73a3b94b10ed6a0aeb5eWerner Lemberg FT_Error error = FT_Err_Ok; 736b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg AF_Point points; 737b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_UInt old_max, new_max; 738b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_Fixed x_scale = hints->x_scale; 739b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_Fixed y_scale = hints->y_scale; 740b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_Pos x_delta = hints->x_delta; 741b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_Pos y_delta = hints->y_delta; 742b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_Memory memory = hints->memory; 743b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 7448bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 745f13516c8321b386227414be01e707563e852fc0dWerner Lemberg hints->num_points = 0; 746f13516c8321b386227414be01e707563e852fc0dWerner Lemberg hints->num_contours = 0; 7478bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 7488bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->axis[0].num_segments = 0; 7498bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->axis[0].num_edges = 0; 7508bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->axis[1].num_segments = 0; 7518bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->axis[1].num_edges = 0; 7528bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 753c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* first of all, reallocate the contours array if necessary */ 754b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg new_max = (FT_UInt)outline->n_contours; 755b57bb11ad015e2d41426d435d6e5ba692afba207Werner Lemberg old_max = (FT_UInt)hints->max_contours; 7566f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod 7576f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod if ( new_max <= AF_CONTOURS_EMBEDDED ) 758b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg { 7594441f7b24675fbd7d91f794f5d54e6c1ff168439Werner Lemberg if ( !hints->contours ) 760b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg { 761b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg hints->contours = hints->embedded.contours; 762b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg hints->max_contours = AF_CONTOURS_EMBEDDED; 763b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg } 764b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg } 7656f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod else if ( new_max > old_max ) 7668bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 7676f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod if ( hints->contours == hints->embedded.contours ) 7686f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod hints->contours = NULL; 7696f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod 770b57bb11ad015e2d41426d435d6e5ba692afba207Werner Lemberg new_max = ( new_max + 3 ) & ~3U; /* round up to a multiple of 4 */ 7718bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 7728bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) ) 7738bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg goto Exit; 7748bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 775b57bb11ad015e2d41426d435d6e5ba692afba207Werner Lemberg hints->max_contours = (FT_Int)new_max; 7768bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 7778bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 778b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /* 779f13516c8321b386227414be01e707563e852fc0dWerner Lemberg * then reallocate the points arrays if necessary -- 780b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * note that we reserve two additional point positions, used to 781b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * hint metrics appropriately 782b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg */ 7838bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg new_max = (FT_UInt)( outline->n_points + 2 ); 784b57bb11ad015e2d41426d435d6e5ba692afba207Werner Lemberg old_max = (FT_UInt)hints->max_points; 7856f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod 7866f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod if ( new_max <= AF_POINTS_EMBEDDED ) 787b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg { 7884441f7b24675fbd7d91f794f5d54e6c1ff168439Werner Lemberg if ( !hints->points ) 789b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg { 790b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg hints->points = hints->embedded.points; 791b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg hints->max_points = AF_POINTS_EMBEDDED; 792b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg } 793b6cb4997e8f0accd98b9589f29e4654e8002501fWerner Lemberg } 7946f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod else if ( new_max > old_max ) 7958bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 7966f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod if ( hints->points == hints->embedded.points ) 7976f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod hints->points = NULL; 7986f16b10019d7699aff4d5bbc64999a5fd1ce7457Behdad Esfahbod 799b57bb11ad015e2d41426d435d6e5ba692afba207Werner Lemberg new_max = ( new_max + 2 + 7 ) & ~7U; /* round up to a multiple of 8 */ 8008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 801b9c22aff61a90a17d8ace2dfda5094df31ac860cDavid Turner if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) ) 8028bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg goto Exit; 8038bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 804b57bb11ad015e2d41426d435d6e5ba692afba207Werner Lemberg hints->max_points = (FT_Int)new_max; 8058bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 8068bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 8078bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->num_points = outline->n_points; 8088bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->num_contours = outline->n_contours; 8098bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 810b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /* We can't rely on the value of `FT_Outline.flags' to know the fill */ 811b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /* direction used for a glyph, given that some fonts are broken (e.g., */ 812b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /* the Arphic ones). We thus recompute it each time we need to. */ 813b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /* */ 814b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP; 815b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT; 8168bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 8178bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT ) 8188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 819b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN; 820b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT; 8218bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 8228bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 8238bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->x_scale = x_scale; 8248bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->y_scale = y_scale; 8258bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->x_delta = x_delta; 8268bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg hints->y_delta = y_delta; 8278bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 828d91eebda1c2eb722eeb63fce27fbbf243a701cf0David Turner hints->xmin_delta = 0; 829d91eebda1c2eb722eeb63fce27fbbf243a701cf0David Turner hints->xmax_delta = 0; 830d91eebda1c2eb722eeb63fce27fbbf243a701cf0David Turner 8318bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg points = hints->points; 8328bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( hints->num_points == 0 ) 8338bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg goto Exit; 8348bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 8358bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 8368bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point point; 8378bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point point_limit = points + hints->num_points; 8388bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 839709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg /* value 20 in `near_limit' is heuristic */ 840709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg FT_UInt units_per_em = hints->metrics->scaler.face->units_per_EM; 841709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg FT_Int near_limit = 20 * units_per_em / 2048; 842709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg 8438bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 844b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner /* compute coordinates & Bezier flags, next and prev */ 8458bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 84649e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg FT_Vector* vec = outline->points; 84749e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg char* tag = outline->tags; 848709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg FT_Short endpoint = outline->contours[0]; 849709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg AF_Point end = points + endpoint; 85049e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg AF_Point prev = end; 851b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner FT_Int contour_index = 0; 8528bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 85349e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg 8548bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( point = points; point < point_limit; point++, vec++, tag++ ) 8558bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 856709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg FT_Pos out_x, out_y; 857709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg 858709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg 859faa21472b795eff3a5254b17ca10d0333d7d03feWerner Lemberg point->in_dir = (FT_Char)AF_DIR_NONE; 860faa21472b795eff3a5254b17ca10d0333d7d03feWerner Lemberg point->out_dir = (FT_Char)AF_DIR_NONE; 861faa21472b795eff3a5254b17ca10d0333d7d03feWerner Lemberg 862750fa961c63e35913583c0d78e9bfa5bb3dfda59David Turner point->fx = (FT_Short)vec->x; 863750fa961c63e35913583c0d78e9bfa5bb3dfda59David Turner point->fy = (FT_Short)vec->y; 8648bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta; 8658bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta; 8668bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 867614a8f17c7bd931e99ebbf70308fe75ee27eb8e7Werner Lemberg end->fx = (FT_Short)outline->points[endpoint].x; 868614a8f17c7bd931e99ebbf70308fe75ee27eb8e7Werner Lemberg end->fy = (FT_Short)outline->points[endpoint].y; 869614a8f17c7bd931e99ebbf70308fe75ee27eb8e7Werner Lemberg 8708bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg switch ( FT_CURVE_TAG( *tag ) ) 8718bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 8728bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg case FT_CURVE_TAG_CONIC: 8738bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->flags = AF_FLAG_CONIC; 8748bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg break; 8758bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg case FT_CURVE_TAG_CUBIC: 8768bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->flags = AF_FLAG_CUBIC; 8778bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg break; 8788bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg default: 879c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg point->flags = AF_FLAG_NONE; 8808bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 8818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 882709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg out_x = point->fx - prev->fx; 883709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg out_y = point->fy - prev->fy; 884709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg 885709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit ) 886709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg prev->flags |= AF_FLAG_NEAR; 887709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg 8888bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->prev = prev; 889b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner prev->next = point; 890b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner prev = point; 891b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 89249e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg if ( point == end ) 8938bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 894b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( ++contour_index < outline->n_contours ) 8958bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 896709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg endpoint = outline->contours[contour_index]; 897614a8f17c7bd931e99ebbf70308fe75ee27eb8e7Werner Lemberg end = points + endpoint; 898614a8f17c7bd931e99ebbf70308fe75ee27eb8e7Werner Lemberg prev = end; 8998bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 9008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 9018bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 9028bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 9038bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 904c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* set up the contours array */ 9058bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 9068bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point* contour = hints->contours; 9078bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point* contour_limit = contour + hints->num_contours; 9088bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg short* end = outline->contours; 9098bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg short idx = 0; 9108bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 9118bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 9128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( ; contour < contour_limit; contour++, end++ ) 9138bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 9148bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg contour[0] = points + idx; 9158bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg idx = (short)( end[0] + 1 ); 9168bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 9178bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 9188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 9198bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 9208a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* 9218a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * Compute directions of `in' and `out' vectors. 9228a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * 9238a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * Note that distances between points that are very near to each 924709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg * other are accumulated. In other words, the auto-hinter either 9258a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * prepends the small vectors between near points to the first 926709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg * non-near vector, or the sum of small vector lengths exceeds a 927709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg * threshold, thus `grouping' the small vectors. All intermediate 928709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg * points are tagged as weak; the directions are adjusted also to 929709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg * be equal to the accumulated one. 9308a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg */ 9318a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 932709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg FT_Int near_limit2 = 2 * near_limit - 1; 933cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 9348a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point* contour; 9358a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point* contour_limit = hints->contours + hints->num_contours; 93649e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg 9378a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 9388a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg for ( contour = hints->contours; contour < contour_limit; contour++ ) 9398bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 9408a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point first = *contour; 9418a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point next, prev, curr; 9428a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 9438a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg FT_Pos out_x, out_y; 9448a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 94549e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg 9468a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* since the first point of a contour could be part of a */ 9478a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* series of near points, go backwards to find the first */ 9488a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* non-near point and adjust `first' */ 9498a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 9508a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg point = first; 9518a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg prev = first->prev; 9528a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 9538a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg while ( prev != first ) 954b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 9558a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_x = point->fx - prev->fx; 9568a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_y = point->fy - prev->fy; 957cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 95807e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg /* 95907e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * We use Taxicab metrics to measure the vector length. 96007e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * 96107e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * Note that the accumulated distances so far could have the 96207e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * opposite direction of the distance measured here. For this 96307e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * reason we use `near_limit2' for the comparison to get a 96407e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * non-near point even in the worst case. 96507e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg */ 96607e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg if ( FT_ABS( out_x ) + FT_ABS( out_y ) >= near_limit2 ) 9678a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg break; 968cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 9698a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg point = prev; 9708a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg prev = prev->prev; 9718a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg } 972cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 9738a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* adjust first point */ 9748a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg first = point; 975cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 9768a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* now loop over all points of the contour to get */ 9778a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* `in' and `out' vector directions */ 978cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 979709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg curr = first; 98007e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg 98107e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg /* 98207e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * We abuse the `u' and `v' fields to store index deltas to the 98307e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * next and previous non-near point, respectively. 98407e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * 98507e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * To avoid problems with not having non-near points, we point to 98607e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * `first' by default as the next non-near point. 98707e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg * 98807e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg */ 98907e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg curr->u = (FT_Pos)( first - curr ); 99007e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg first->v = -curr->u; 99107e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg 9928a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_x = 0; 9938a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_y = 0; 994cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 99567b912d2fa17caa921f513cae180c7aae28b1bc6Alexei Podtelezhnikov (Алексей Подтележников) next = first; 99667b912d2fa17caa921f513cae180c7aae28b1bc6Alexei Podtelezhnikov (Алексей Подтележников) do 9978a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg { 9988a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Direction out_dir; 999cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 1000cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 100167b912d2fa17caa921f513cae180c7aae28b1bc6Alexei Podtelezhnikov (Алексей Подтележников) point = next; 1002709486db7f5684329bdf39156fadf6bdff6d8fddWerner Lemberg next = point->next; 1003cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 10048a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_x += next->fx - point->fx; 10058a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_y += next->fy - point->fy; 10068a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10078a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg if ( FT_ABS( out_x ) + FT_ABS( out_y ) < near_limit ) 10088a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg { 10098a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg next->flags |= AF_FLAG_WEAK_INTERPOLATION; 10108a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg continue; 1011cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg } 1012cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 10138a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg curr->u = (FT_Pos)( next - curr ); 10148a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg next->v = -curr->u; 10158a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10168a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_dir = af_direction_compute( out_x, out_y ); 10178a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10188a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* adjust directions for all points inbetween; */ 10198a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* the loop also updates position of `curr' */ 10208a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg curr->out_dir = (FT_Char)out_dir; 10218a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg for ( curr = curr->next; curr != next; curr = curr->next ) 10228a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg { 10238a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg curr->in_dir = (FT_Char)out_dir; 10248a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg curr->out_dir = (FT_Char)out_dir; 10258a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg } 10268a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg next->in_dir = (FT_Char)out_dir; 10278a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 102807e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg curr->u = (FT_Pos)( first - curr ); 102907e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg first->v = -curr->u; 103007e7b8affeef35383fdef09ebe817b568f71249aWerner Lemberg 10318a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_x = 0; 10328a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_y = 0; 103367b912d2fa17caa921f513cae180c7aae28b1bc6Alexei Podtelezhnikov (Алексей Подтележников) 103467b912d2fa17caa921f513cae180c7aae28b1bc6Alexei Podtelezhnikov (Алексей Подтележников) } while ( next != first ); 10358a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg } 10368bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 10378a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* 10388a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * The next step is to `simplify' an outline's topology so that we 10398a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * can identify local extrema more reliably: A series of 10408a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * non-horizontal or non-vertical vectors pointing into the same 10418a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * quadrant are handled as a single, long vector. From a 10428a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * topological point of the view, the intermediate points are of no 10438a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * interest and thus tagged as weak. 10448a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg */ 10458bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 10468a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg for ( point = points; point < point_limit; point++ ) 10478a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg { 10488a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg if ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) 10498a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg continue; 1050cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 10518a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg if ( point->in_dir == AF_DIR_NONE && 10528a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg point->out_dir == AF_DIR_NONE ) 1053cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg { 10548a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* check whether both vectors point into the same quadrant */ 10558a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10568a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg FT_Pos in_x, in_y; 10578a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg FT_Pos out_x, out_y; 10588a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10598a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point next_u = point + point->u; 10608a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point prev_v = point + point->v; 10618a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10628a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10638a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg in_x = point->fx - prev_v->fx; 10648a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg in_y = point->fy - prev_v->fy; 10658a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10668a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_x = next_u->fx - point->fx; 10678a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg out_y = next_u->fy - point->fy; 1068cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg 10698a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg if ( ( in_x ^ out_x ) >= 0 && ( in_y ^ out_y ) >= 0 ) 10708a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg { 10718a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* yes, so tag current point as weak */ 10728a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* and update index deltas */ 10738a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10748a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg point->flags |= AF_FLAG_WEAK_INTERPOLATION; 10758a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 10768a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg prev_v->u = (FT_Pos)( next_u - prev_v ); 10778a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg next_u->v = -prev_v->u; 10788a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg } 10798a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg } 10808a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg } 10818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 10828a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* 10838a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * Finally, check for remaining weak points. Everything else not 10848a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * collected in edges so far is then implicitly classified as strong 10858a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg * points. 10868a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg */ 10878bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 10888a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg for ( point = points; point < point_limit; point++ ) 10898a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg { 10908a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg if ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) 10918a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg continue; 1092c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 1093b6978dd0c949aedbaa1773724e19fec47a34a29cWerner Lemberg if ( point->flags & AF_FLAG_CONTROL ) 10948bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1095cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg /* control points are always weak */ 10968bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg Is_Weak_Point: 10978bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->flags |= AF_FLAG_WEAK_INTERPOLATION; 10988bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 10998bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else if ( point->out_dir == point->in_dir ) 11008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1101281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner if ( point->out_dir != AF_DIR_NONE ) 1102cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg { 1103df41fe57917df4ac239fdbc0877c24049aaf8c90Werner Lemberg /* current point lies on a horizontal or */ 1104df41fe57917df4ac239fdbc0877c24049aaf8c90Werner Lemberg /* vertical segment (but doesn't start or end it) */ 1105281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner goto Is_Weak_Point; 1106cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg } 1107281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner 1108cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg { 11098a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point next_u = point + point->u; 11108a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg AF_Point prev_v = point + point->v; 11118a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 11128a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 11138a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg if ( ft_corner_is_flat( point->fx - prev_v->fx, 11148a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg point->fy - prev_v->fy, 11158a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg next_u->fx - point->fx, 11168a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg next_u->fy - point->fy ) ) 11178a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg { 11188a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* either the `in' or the `out' vector is much more */ 11198a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* dominant than the other one, so tag current point */ 11208a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg /* as weak and update index deltas */ 11218a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 11228a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg prev_v->u = (FT_Pos)( next_u - prev_v ); 11238a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg next_u->v = -prev_v->u; 11248a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg 11258a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg goto Is_Weak_Point; 11268a94b1efd6cfe76ffbd66e9315542c9438a34722Werner Lemberg } 1127cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg } 11288bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 11298bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else if ( point->in_dir == -point->out_dir ) 1130cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg { 1131cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg /* current point forms a spike */ 11328bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg goto Is_Weak_Point; 1133cc25e3ae12216380179506b9d5d9c25293966708Werner Lemberg } 11348bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 11358bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 11368bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 11378bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 11388bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg Exit: 11398bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg return error; 11408bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 11418bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 11428bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1143c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Store the hinted outline in an FT_Outline structure. */ 1144c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 11458bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( void ) 1146b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg af_glyph_hints_save( AF_GlyphHints hints, 1147b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg FT_Outline* outline ) 11488bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 11498bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point point = hints->points; 11508bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point limit = point + hints->num_points; 11518bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_Vector* vec = outline->points; 11528bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg char* tag = outline->tags; 11538bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1154b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 11558bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( ; point < limit; point++, vec++, tag++ ) 11568bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1157750fa961c63e35913583c0d78e9bfa5bb3dfda59David Turner vec->x = point->x; 1158750fa961c63e35913583c0d78e9bfa5bb3dfda59David Turner vec->y = point->y; 11598bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 11608bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( point->flags & AF_FLAG_CONIC ) 11618bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg tag[0] = FT_CURVE_TAG_CONIC; 11628bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else if ( point->flags & AF_FLAG_CUBIC ) 11638bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg tag[0] = FT_CURVE_TAG_CUBIC; 11648bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 11658bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg tag[0] = FT_CURVE_TAG_ON; 11668bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 11678bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 11688bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 11698bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1170b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /**************************************************************** 1171b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * 1172b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * EDGE POINT GRID-FITTING 1173b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * 1174b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg ****************************************************************/ 11758bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 11768bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1177c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Align all points of an edge to the same coordinate value, */ 1178c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* either horizontally or vertically. */ 1179c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 11808bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( void ) 11818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_glyph_hints_align_edge_points( AF_GlyphHints hints, 11828bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Dimension dim ) 11838bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1184b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_AxisHints axis = & hints->axis[dim]; 1185b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Segment segments = axis->segments; 1186b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Segment segment_limit = segments + axis->num_segments; 1187b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Segment seg; 11888bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1189b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 1190b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( dim == AF_DIMENSION_HORZ ) 11918bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1192b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner for ( seg = segments; seg < segment_limit; seg++ ) 11938bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1194b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Edge edge = seg->edge; 1195b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Point point, first, last; 1196b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 11978bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 11984441f7b24675fbd7d91f794f5d54e6c1ff168439Werner Lemberg if ( !edge ) 1199b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner continue; 12008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1201b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner first = seg->first; 1202b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner last = seg->last; 1203b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point = first; 12048bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for (;;) 12058bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1206b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point->x = edge->pos; 1207b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point->flags |= AF_FLAG_TOUCH_X; 12088bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1209b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( point == last ) 12108bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg break; 12118bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point = point->next; 12138bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 1214b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 1215b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 1216b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner else 1217b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 1218b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner for ( seg = segments; seg < segment_limit; seg++ ) 1219b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 1220b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Edge edge = seg->edge; 1221b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner AF_Point point, first, last; 1222b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1223b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 12244441f7b24675fbd7d91f794f5d54e6c1ff168439Werner Lemberg if ( !edge ) 1225b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner continue; 12268bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1227b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner first = seg->first; 1228b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner last = seg->last; 1229b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point = first; 1230b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner for (;;) 1231b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 1232b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point->y = edge->pos; 1233b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point->flags |= AF_FLAG_TOUCH_Y; 12348bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1235b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( point == last ) 1236b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner break; 1237b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1238b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point = point->next; 1239b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 1240b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 12418bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 12428bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 12438bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12448bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1245b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /**************************************************************** 1246b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * 1247b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * STRONG POINT INTERPOLATION 1248b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * 1249b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg ****************************************************************/ 12508bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12518bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1252c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Hint the strong points -- this is equivalent to the TrueType `IP' */ 1253c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* hinting instruction. */ 1254b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 12558bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( void ) 12568bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_glyph_hints_align_strong_points( AF_GlyphHints hints, 12578bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Dimension dim ) 12588bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 12598bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point points = hints->points; 12608bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point point_limit = points + hints->num_points; 12618bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_AxisHints axis = &hints->axis[dim]; 12628bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge edges = axis->edges; 12638bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge edge_limit = edges + axis->num_edges; 126481e5ff53a89b454a3984a7181516dfb4cb22187aWerner Lemberg FT_UInt touch_flag; 12658bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12668bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12678bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( dim == AF_DIMENSION_HORZ ) 12688bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg touch_flag = AF_FLAG_TOUCH_X; 12698bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 12708bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg touch_flag = AF_FLAG_TOUCH_Y; 12718bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12728bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( edges < edge_limit ) 12738bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 12748bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point point; 12758bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge edge; 12768bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1277b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 12788bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( point = points; point < point_limit; point++ ) 12798bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 12808bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_Pos u, ou, fu; /* point position */ 12818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_Pos delta; 12828bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12838bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12848bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( point->flags & touch_flag ) 12858bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg continue; 12868bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1287b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /* if this point is candidate to weak interpolation, we */ 12888bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* interpolate it after all strong points have been processed */ 1289b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 12905b68e4fb60421038b58cceb8ef86e27ebf8625d7Werner Lemberg if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ) 12918bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg continue; 12928bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 12938bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( dim == AF_DIMENSION_VERT ) 12948bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 12958bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = point->fy; 12968bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg ou = point->oy; 12978bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 12988bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 12998bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 13008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = point->fx; 13018bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg ou = point->ox; 13028bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13038bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13048bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg fu = u; 13058bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13068bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* is the point before the first edge? */ 13078bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg edge = edges; 13088bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg delta = edge->fpos - u; 13098bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( delta >= 0 ) 13108bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 13118bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = edge->pos - ( edge->opos - ou ); 13128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg goto Store_Point; 13138bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13148bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13158bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* is the point after the last edge? */ 13168bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg edge = edge_limit - 1; 13178bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg delta = u - edge->fpos; 13188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( delta >= 0 ) 13198bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 13208bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = edge->pos + ( ou - edge->opos ); 13218bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg goto Store_Point; 13228bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13238bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13248bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1325b56680240a10db7e13cf5925a61946626d269c84Suzuki, Toshiya (鈴木俊哉) FT_PtrDist min, max, mid; 1326b56680240a10db7e13cf5925a61946626d269c84Suzuki, Toshiya (鈴木俊哉) FT_Pos fpos; 13278bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13288bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13298bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* find enclosing edges */ 13308bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg min = 0; 13318bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg max = edge_limit - edges; 13328bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1333b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner#if 1 1334c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* for a small number of edges, a linear search is better */ 1335b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( max <= 8 ) 1336b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 1337b56680240a10db7e13cf5925a61946626d269c84Suzuki, Toshiya (鈴木俊哉) FT_PtrDist nn; 1338b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1339c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 1340b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner for ( nn = 0; nn < max; nn++ ) 1341b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( edges[nn].fpos >= u ) 1342b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner break; 1343b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1344b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( edges[nn].fpos == u ) 1345b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 1346b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner u = edges[nn].pos; 1347b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner goto Store_Point; 1348b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 1349b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner min = nn; 1350b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 1351b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner else 1352b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner#endif 13538bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg while ( min < max ) 13548bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 13558bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg mid = ( max + min ) >> 1; 13568bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg edge = edges + mid; 13578bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg fpos = edge->fpos; 13588bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13598bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( u < fpos ) 13608bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg max = mid; 13618bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else if ( u > fpos ) 13628bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg min = mid + 1; 13638bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 13648bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 13658bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* we are on the edge */ 13668bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = edge->pos; 13678bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg goto Store_Point; 13688bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13698bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13708bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1371c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* point is not on an edge */ 13728bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 13738bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge before = edges + min - 1; 13748bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Edge after = edges + min + 0; 13758bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13768bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13778bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* assert( before && after && before != after ) */ 13788bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( before->scale == 0 ) 13798bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg before->scale = FT_DivFix( after->pos - before->pos, 13808bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg after->fpos - before->fpos ); 13818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13828bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = before->pos + FT_MulFix( fu - before->fpos, 13838bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg before->scale ); 13848bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13858bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13868bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13878bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg Store_Point: 13888bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* save the point position */ 13898bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( dim == AF_DIMENSION_HORZ ) 13908bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->x = u; 13918bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 13928bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->y = u; 13938bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13948bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->flags |= touch_flag; 13958bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13968bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13978bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 13988bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 13998bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1400b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg /**************************************************************** 1401b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * 1402b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * WEAK POINT INTERPOLATION 1403b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg * 1404b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg ****************************************************************/ 1405b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 14068bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1407c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Shift the original coordinates of all points between `p1' and */ 1408c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* `p2' to get hinted coordinates, using the same difference as */ 1409c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* given by `ref'. */ 1410c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 14118bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg static void 14128bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_iup_shift( AF_Point p1, 14138bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point p2, 14148bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point ref ) 14158bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 14168bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point p; 14178bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_Pos delta = ref->u - ref->v; 14188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1419c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 142049e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg if ( delta == 0 ) 1421b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner return; 14228bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14238bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( p = p1; p < ref; p++ ) 14248bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg p->u = p->v + delta; 14258bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14268bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( p = ref + 1; p <= p2; p++ ) 14278bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg p->u = p->v + delta; 14288bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 14298bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14308bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1431c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Interpolate the original coordinates of all points between `p1' and */ 1432c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the */ 1433c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* reference points. The `u' and `v' members are the current and */ 1434c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* original coordinate values, respectively. */ 1435c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* */ 1436c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Details can be found in the TrueType bytecode specification. */ 1437c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 14388bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg static void 14398bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_iup_interp( AF_Point p1, 14408bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point p2, 14418bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point ref1, 14428bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point ref2 ) 14438bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 14448bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Point p; 1445409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) FT_Pos u, v1, v2, u1, u2, d1, d2; 14468bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14478bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14488bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( p1 > p2 ) 14498bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg return; 14508bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1451409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) if ( ref1->v > ref2->v ) 14528bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1453409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) p = ref1; 1454409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) ref1 = ref2; 1455409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) ref2 = p; 14568bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 14578bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1458409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) v1 = ref1->v; 1459409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) v2 = ref2->v; 1460409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) u1 = ref1->u; 1461409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) u2 = ref2->u; 1462409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) d1 = u1 - v1; 1463409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) d2 = u2 - v2; 1464409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) 1465409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) if ( u1 == u2 || v1 == v2 ) 14668bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 14678bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( p = p1; p <= p2; p++ ) 14688bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 14698bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = p->v; 14708bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14718bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( u <= v1 ) 14728bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u += d1; 14738bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else if ( u >= v2 ) 14748bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u += d2; 14758bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 1476409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) u = u1; 14778bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14788bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg p->u = u; 14798bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 14808bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 14818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 14828bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1483409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) FT_Fixed scale = FT_DivFix( u2 - u1, v2 - v1 ); 1484409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) 1485a678560dc23f7dfa6d6cda8d0d35be37c04713e2Werner Lemberg 14868bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( p = p1; p <= p2; p++ ) 14878bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 14888bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u = p->v; 14898bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1490409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) if ( u <= v1 ) 14918bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg u += d1; 1492409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) else if ( u >= v2 ) 1493409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) u += d2; 14948bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 1495409149527173a089278fd6d1b84a2a8dc911c9a6Alexei Podtelezhnikov (Алексей Подтележников) u = u1 + FT_MulFix( u - v1, scale ); 14968bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 14978bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg p->u = u; 14988bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 14998bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 15008bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 15018bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 15028bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1503c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* Hint the weak points -- this is equivalent to the TrueType `IUP' */ 1504c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* hinting instruction. */ 1505c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 15068bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg FT_LOCAL_DEF( void ) 15078bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg af_glyph_hints_align_weak_points( AF_GlyphHints hints, 15088bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg AF_Dimension dim ) 15098bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1510f13516c8321b386227414be01e707563e852fc0dWerner Lemberg AF_Point points = hints->points; 1511f13516c8321b386227414be01e707563e852fc0dWerner Lemberg AF_Point point_limit = points + hints->num_points; 1512f13516c8321b386227414be01e707563e852fc0dWerner Lemberg AF_Point* contour = hints->contours; 1513f13516c8321b386227414be01e707563e852fc0dWerner Lemberg AF_Point* contour_limit = contour + hints->num_contours; 151481e5ff53a89b454a3984a7181516dfb4cb22187aWerner Lemberg FT_UInt touch_flag; 1515f13516c8321b386227414be01e707563e852fc0dWerner Lemberg AF_Point point; 1516f13516c8321b386227414be01e707563e852fc0dWerner Lemberg AF_Point end_point; 1517f13516c8321b386227414be01e707563e852fc0dWerner Lemberg AF_Point first_point; 15188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 15198bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 15208bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* PASS 1: Move segment points to edge positions */ 15218bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 15228bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( dim == AF_DIMENSION_HORZ ) 15238bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 15248bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg touch_flag = AF_FLAG_TOUCH_X; 15258bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 15268bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( point = points; point < point_limit; point++ ) 15278bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 15288bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->u = point->x; 15298bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->v = point->ox; 15308bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 15318bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 15328bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 15338bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 15348bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg touch_flag = AF_FLAG_TOUCH_Y; 15358bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 15368bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( point = points; point < point_limit; point++ ) 15378bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 15388bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->u = point->y; 15398bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->v = point->oy; 15408bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 15418bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 15428bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 15438bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( ; contour < contour_limit; contour++ ) 15448bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 154549e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg AF_Point first_touched, last_touched; 154649e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg 1547b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 15488bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point = *contour; 15498bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg end_point = point->prev; 15508bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg first_point = point; 15518bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1552b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner /* find first touched point */ 1553b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner for (;;) 1554b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 1555b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( point > end_point ) /* no touched point in contour */ 1556b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner goto NextContour; 1557b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1558b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( point->flags & touch_flag ) 1559b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner break; 1560b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 15618bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point++; 1562b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 15638bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1564b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner first_touched = point; 1565b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1566b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner for (;;) 15678bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1568c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg FT_ASSERT( point <= end_point && 156949e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg ( point->flags & touch_flag ) != 0 ); 15708bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1571c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg /* skip any touched neighbours */ 1572c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg while ( point < end_point && 1573c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg ( point[1].flags & touch_flag ) != 0 ) 1574b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner point++; 15758bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1576b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner last_touched = point; 1577b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1578b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner /* find the next touched point, if any */ 1579c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg point++; 1580b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner for (;;) 15818bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 1582b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( point > end_point ) 1583b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner goto EndContour; 1584b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 158549e18b8d5f7df1c931e07f94615b375a0399162aWerner Lemberg if ( ( point->flags & touch_flag ) != 0 ) 1586b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner break; 1587b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 15888bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point++; 15898bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 15908bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 1591b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner /* interpolate between last_touched and point */ 1592b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner af_iup_interp( last_touched + 1, point - 1, 1593b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner last_touched, point ); 15948bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 1595b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1596b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner EndContour: 1597b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner /* special case: only one point was touched */ 1598b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( last_touched == first_touched ) 1599b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner af_iup_shift( first_point, end_point, first_touched ); 1600c5bda503b9b15bdd042e2c9696f2b1975f49d98cWerner Lemberg 1601b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner else /* interpolate the last part */ 1602b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner { 1603b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( last_touched < end_point ) 1604b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner af_iup_interp( last_touched + 1, end_point, 1605b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner last_touched, first_touched ); 1606b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1607b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner if ( first_touched > points ) 1608b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner af_iup_interp( first_point, first_touched - 1, 1609b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner last_touched, first_touched ); 1610b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner } 1611b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner 1612b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner NextContour: 1613b792017fafd1e99e8ca81811a58b09dc562b48c9David Turner ; 16148bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 16158bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg 16168bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg /* now save the interpolated values back to x/y */ 16178bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg if ( dim == AF_DIMENSION_HORZ ) 16188bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 16198bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( point = points; point < point_limit; point++ ) 16208bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->x = point->u; 16218bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 16228bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg else 16238bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg { 16248bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg for ( point = points; point < point_limit; point++ ) 16258bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg point->y = point->u; 16268bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 16278bb07e6386ef47f9f9d2bd28a36dda8784530727Werner Lemberg } 1628b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 16291be9ebf5f909d7fc026eb185a8b5eeb6a372afe6Werner Lemberg 1630576fc2c06e9b34db235b18cc8ae20c3ce789fb65Werner Lemberg#ifdef AF_CONFIG_OPTION_USE_WARPER 16311be9ebf5f909d7fc026eb185a8b5eeb6a372afe6Werner Lemberg 16327ad15d59265410139078d835181565b771e34c05Werner Lemberg /* Apply (small) warp scale and warp delta for given dimension. */ 16337ad15d59265410139078d835181565b771e34c05Werner Lemberg 1634bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner FT_LOCAL_DEF( void ) 1635bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner af_glyph_hints_scale_dim( AF_GlyphHints hints, 1636bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner AF_Dimension dim, 1637bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner FT_Fixed scale, 1638bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner FT_Pos delta ) 1639bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner { 1640bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner AF_Point points = hints->points; 1641bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner AF_Point points_limit = points + hints->num_points; 1642bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner AF_Point point; 1643281679de8591f6884ea904c9c812e520ba3cc5dcDavid Turner 16441be9ebf5f909d7fc026eb185a8b5eeb6a372afe6Werner Lemberg 1645bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner if ( dim == AF_DIMENSION_HORZ ) 1646bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner { 1647bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner for ( point = points; point < points_limit; point++ ) 1648bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner point->x = FT_MulFix( point->fx, scale ) + delta; 1649bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner } 1650bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner else 1651bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner { 1652bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner for ( point = points; point < points_limit; point++ ) 1653bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner point->y = FT_MulFix( point->fy, scale ) + delta; 1654bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner } 1655bb4edc923597aa48da0d0ac217e7a80d41e77f0dDavid Turner } 16561be9ebf5f909d7fc026eb185a8b5eeb6a372afe6Werner Lemberg 1657576fc2c06e9b34db235b18cc8ae20c3ce789fb65Werner Lemberg#endif /* AF_CONFIG_OPTION_USE_WARPER */ 1658b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg 1659b19b0810cd887a4c1036121b0d3e9bb93278a0a9Werner Lemberg/* END */ 1660