1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/ 2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* pshalgo.c */ 4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* PostScript hinting algorithm (body). */ 6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 7ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki/* Copyright 2001-2015 by */ 8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* This file is part of the FreeType project, and may only be used */ 11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* modified and distributed under the terms of the FreeType project */ 12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* this file you indicate that you have read the license and */ 14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* understand and accept it fully. */ 15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/ 17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h> 20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H 21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H 22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_CALC_H 23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "pshalgo.h" 24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "pshnterr.h" 26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef FT_COMPONENT 29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT trace_pshalgo2 30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 33ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki PSH_Hint_Table ps_debug_hint_table = NULL; 34ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki PSH_HintFunc ps_debug_hint_func = NULL; 35ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki PSH_Glyph ps_debug_glyph = NULL; 36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define COMPUTE_INFLEXS /* compute inflection points to optimize `S' */ 40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* and similar glyphs */ 41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** BASIC HINTS RECORDINGS *****/ 47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* return true if two stem hints overlap */ 52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Int 53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_overlap( PSH_Hint hint1, 54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint2 ) 55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return hint1->org_pos + hint1->org_len >= hint2->org_pos && 57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint2->org_pos + hint2->org_len >= hint1->org_pos; 58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* destroy hints table */ 62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_done( PSH_Hint_Table table, 64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory ) 65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( table->zones ); 67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->num_zones = 0; 68ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki table->zone = NULL; 69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( table->sort ); 71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( table->hints ); 72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->num_hints = 0; 73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->max_hints = 0; 74ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki table->sort_global = NULL; 75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* deactivate all hints in a table */ 79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_deactivate( PSH_Hint_Table table ) 81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = table->max_hints; 83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = table->hints; 84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, hint++ ) 87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_deactivate( hint ); 89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->order = -1; 90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* internal function to record a new hint */ 95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_record( PSH_Hint_Table table, 97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt idx ) 98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = table->hints + idx; 100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( idx >= table->max_hints ) 103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 104295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_TRACE0(( "psh_hint_table_record: invalid hint index %d\n", idx )); 105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* ignore active hints */ 109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_hint_is_active( hint ) ) 110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_activate( hint ); 113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now scan the current active hint set to check */ 115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* whether `hint' overlaps with another hint */ 116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint* sorted = table->sort_global; 118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = table->num_hints; 119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint2; 120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 122ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki hint->parent = NULL; 123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, sorted++ ) 124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint2 = sorted[0]; 126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_hint_overlap( hint, hint2 ) ) 128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->parent = hint2; 130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( table->num_hints < table->max_hints ) 136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->sort_global[table->num_hints++] = hint; 137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 138295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_TRACE0(( "psh_hint_table_record: too many sorted hints! BUG!\n" )); 139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_record_mask( PSH_Hint_Table table, 144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Mask hint_mask ) 145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int mask = 0, val = 0; 147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* cursor = hint_mask->bytes; 148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt idx, limit; 149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project limit = hint_mask->num_bits; 152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( idx = 0; idx < limit; idx++ ) 154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mask == 0 ) 156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project val = *cursor++; 158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project mask = 0x80; 159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( val & mask ) 162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_record( table, idx ); 163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project mask >>= 1; 165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* create hints table */ 170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_init( PSH_Hint_Table table, 172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Hint_Table hints, 173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Mask_Table hint_masks, 174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Mask_Table counter_masks, 175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory ) 176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count; 178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( counter_masks ); 181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project count = hints->num_hints; 184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* allocate our tables */ 186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_NEW_ARRAY( table->sort, 2 * count ) || 187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_NEW_ARRAY( table->hints, count ) || 188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_NEW_ARRAY( table->zones, 2 * count + 1 ) ) 189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->max_hints = count; 192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->sort_global = table->sort + count; 193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->num_hints = 0; 194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->num_zones = 0; 195ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki table->zone = NULL; 196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* initialize the `table->hints' array */ 198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint write = table->hints; 200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Hint read = hints->hints; 201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, write++, read++ ) 204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project write->org_pos = read->pos; 206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project write->org_len = read->len; 207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project write->flags = read->flags; 208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* we now need to determine the initial `parent' stems; first */ 212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* activate the hints that are given by the initial hint masks */ 213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( hint_masks ) 214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Mask mask = hint_masks->masks; 216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project count = hint_masks->num_masks; 219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->hint_masks = hint_masks; 220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, mask++ ) 222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_record_mask( table, mask ); 223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* finally, do a linear parse in case some hints were left alone */ 226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( table->num_hints != table->max_hints ) 227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt idx; 229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 231295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_TRACE0(( "psh_hint_table_init: missing/incorrect hint masks\n" )); 232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project count = table->max_hints; 234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( idx = 0; idx < count; idx++ ) 235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_record( table, idx ); 236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_activate_mask( PSH_Hint_Table table, 245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Mask hint_mask ) 246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int mask = 0, val = 0; 248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Byte* cursor = hint_mask->bytes; 249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt idx, limit, count; 250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project limit = hint_mask->num_bits; 253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project count = 0; 254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_deactivate( table ); 256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( idx = 0; idx < limit; idx++ ) 258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mask == 0 ) 260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project val = *cursor++; 262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project mask = 0x80; 263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( val & mask ) 266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = &table->hints[idx]; 268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_hint_is_active( hint ) ) 271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count2; 273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0 275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint* sort = table->sort; 276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint2; 277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( count2 = count; count2 > 0; count2--, sort++ ) 280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint2 = sort[0]; 282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_hint_overlap( hint, hint2 ) ) 283295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_TRACE0(( "psh_hint_table_activate_mask:" 284295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner " found overlapping hints\n" )) 285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else 287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project count2 = 0; 288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( count2 == 0 ) 291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_activate( hint ); 293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( count < table->max_hints ) 294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->sort[count++] = hint; 295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 296295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_TRACE0(( "psh_hint_tableactivate_mask:" 297295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner " too many active hints\n" )); 298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project mask >>= 1; 303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table->num_hints = count; 305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now, sort the hints; they are guaranteed to not overlap */ 307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* so we can compare their "org_pos" field directly */ 308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int i1, i2; 310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint1, hint2; 311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint* sort = table->sort; 312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* a simple bubble sort will do, since in 99% of cases, the hints */ 315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* will be already sorted -- and the sort will be linear */ 316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( i1 = 1; i1 < (FT_Int)count; i1++ ) 317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint1 = sort[i1]; 319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( i2 = i1 - 1; i2 >= 0; i2-- ) 320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint2 = sort[i2]; 322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( hint2->org_pos < hint1->org_pos ) 324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project sort[i2 + 1] = hint2; 327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project sort[i2] = hint1; 328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** HINTS GRID-FITTING AND OPTIMIZATION *****/ 338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1 343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_dimension_quantize_len( PSH_Dimension dim, 345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos len, 346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool do_snapping ) 347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len <= 64 ) 349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = 64; 350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta = len - dim->stdw.widths[0].cur; 353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta < 0 ) 356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = -delta; 357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta < 40 ) 359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = dim->stdw.widths[0].cur; 361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len < 48 ) 362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = 48; 363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len < 3 * 64 ) 366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = ( len & 63 ); 368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len &= -64; 369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta < 10 ) 371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len += delta; 372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 32 ) 374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len += 10; 375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 54 ) 377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len += 54; 378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len += delta; 381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = FT_PIX_ROUND( len ); 384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( do_snapping ) 387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = FT_PIX_ROUND( len ); 388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return len; 390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 0 */ 392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_simple_scale( PSH_Hint_Table table, 398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale, 399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta, 400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension ) 401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 402727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease FT_UInt count; 403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( count = 0; count < table->max_hints; count++ ) 406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 407727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease PSH_Hint hint = table->hints + count; 408727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta; 411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = FT_MulFix( hint->org_len, scale ); 412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ps_debug_hint_func ) 414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_debug_hint_func( hint, dimension ); 415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_HINTER */ 419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Fixed 422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_snap_stem_side_delta( FT_Fixed pos, 423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed len ) 424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta1 = FT_PIX_ROUND( pos ) - pos; 426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta2 = FT_PIX_ROUND( pos + len ) - pos - len; 427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( delta1 ) <= FT_ABS( delta2 ) ) 430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return delta1; 431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return delta2; 433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_align( PSH_Hint hint, 438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Globals globals, 439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension, 440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Glyph glyph ) 441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim = &globals->dimension[dimension]; 443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale = dim->scale_mult; 444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta = dim->scale_delta; 445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_hint_is_fitted( hint ) ) 448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; 450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos len = FT_MulFix( hint->org_len, scale ); 451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int do_snapping; 453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos fit_len; 454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_AlignmentRec align; 455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* ignore stem alignments when requested through the hint flags */ 458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( dimension == 0 && !glyph->do_horz_hints ) || 459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dimension == 1 && !glyph->do_vert_hints ) ) 460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = pos; 462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = len; 463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_set_fitted( hint ); 465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* perform stem snapping when requested - this is necessary 469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * for monochrome and LCD hinting modes only 470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) || 472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dimension == 1 && glyph->do_vert_snapping ); 473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = fit_len = len; 475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check blue zones for horizontal stems */ 477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project align.align = PSH_BLUE_ALIGN_NONE; 478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project align.align_bot = align.align_top = 0; 479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dimension == 1 ) 481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_blues_snap_stem( &globals->blues, 482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->org_pos + hint->org_len, 483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->org_pos, 484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &align ); 485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project switch ( align.align ) 487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_TOP: 489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the top of the stem is aligned against a blue zone */ 490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = align.align_top - fit_len; 491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_BOT: 494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the bottom of the stem is aligned against a blue zone */ 495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = align.align_bot; 496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: 499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* both edges of the stem are aligned against blue zones */ 500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = align.align_bot; 501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = align.align_top - align.align_bot; 502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project default: 505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint parent = hint->parent; 507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( parent ) 510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos par_org_center, par_cur_center; 512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos cur_org_center, cur_delta; 513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* ensure that parent is already fitted */ 516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_hint_is_fitted( parent ) ) 517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_align( parent, globals, dimension, glyph ); 518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* keep original relation between hints, this is, use the */ 520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* scaled distance between the centers of the hints to */ 521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute the new position */ 522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project par_org_center = parent->org_pos + ( parent->org_len >> 1 ); 523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 ); 524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_org_center = hint->org_pos + ( hint->org_len >> 1 ); 525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); 527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = par_cur_center + cur_delta - ( len >> 1 ); 528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = pos; 531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = fit_len; 532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Stem adjustment tries to snap stem widths to standard 534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * ones. This is important to prevent unpleasant rounding 535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * artefacts. 536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( glyph->do_stem_adjust ) 538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len <= 64 ) 540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the stem is less than one pixel; we will center it 542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * around the nearest pixel center 543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len >= 32 ) 545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* This is a special case where we also widen the stem 547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * and align it to the pixel grid. 548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * stem_center = pos + (len/2) 550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * nearest_pixel_center = FT_ROUND(stem_center-32)+32 551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * new_pos = nearest_pixel_center-32 552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * = FT_ROUND(stem_center-32) 553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * = FT_FLOOR(stem_center-32+32) 554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * = FT_FLOOR(stem_center) 555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * new_len = 64 556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ); 558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = 64; 559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( len > 0 ) 561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* This is a very small stem; we simply align it to the 563727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease * pixel grid, trying to find the minimum displacement. 564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * left = pos 566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * right = pos + len 567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * left_nearest_edge = ROUND(pos) 568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * right_nearest_edge = ROUND(right) 569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * if ( ABS(left_nearest_edge - left) <= 571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * ABS(right_nearest_edge - right) ) 572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * new_pos = left 573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * else 574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * new_pos = right 575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos left_nearest = FT_PIX_ROUND( pos ); 577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos right_nearest = FT_PIX_ROUND( pos + len ); 578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos left_disp = left_nearest - pos; 579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos right_disp = right_nearest - ( pos + len ); 580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left_disp < 0 ) 583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left_disp = -left_disp; 584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( right_disp < 0 ) 585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right_disp = -right_disp; 586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left_disp <= right_disp ) 587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = left_nearest; 588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = right_nearest; 590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* this is a ghost stem; we simply round it */ 594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = FT_PIX_ROUND( pos ); 595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = psh_dimension_quantize_len( dim, len, 0 ); 600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now that we have a good hinted stem width, try to position */ 604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the stem along a pixel grid integer coordinate */ 605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len ); 606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = len; 607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( do_snapping ) 611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = hint->cur_pos; 613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = hint->cur_len; 614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len < 64 ) 616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = 64; 617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = FT_PIX_ROUND( len ); 619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project switch ( align.align ) 621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_TOP: 623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = align.align_top - len; 624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = len; 625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_BOT: 628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = len; 629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP: 632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* don't touch */ 633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project default: 637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = len; 638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len & 64 ) 639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32; 640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = FT_PIX_ROUND( pos + ( len >> 1 ) ); 642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = pos - ( len >> 1 ); 644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = len; 645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_set_fitted( hint ); 649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ps_debug_hint_func ) 652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_debug_hint_func( hint, dimension ); 653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0 /* not used for now, experimental */ 659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT) 662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * of stems 663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_align_light( PSH_Hint hint, 666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Globals globals, 667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension, 668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Glyph glyph ) 669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim = &globals->dimension[dimension]; 671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale = dim->scale_mult; 672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta = dim->scale_delta; 673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_hint_is_fitted( hint ) ) 676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos pos = FT_MulFix( hint->org_pos, scale ) + delta; 678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos len = FT_MulFix( hint->org_len, scale ); 679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos fit_len; 681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_AlignmentRec align; 683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* ignore stem alignments when requested through the hint flags */ 686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( dimension == 0 && !glyph->do_horz_hints ) || 687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dimension == 1 && !glyph->do_vert_hints ) ) 688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = pos; 690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = len; 691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_set_fitted( hint ); 693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project fit_len = len; 697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = fit_len; 699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check blue zones for horizontal stems */ 701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project align.align = PSH_BLUE_ALIGN_NONE; 702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project align.align_bot = align.align_top = 0; 703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dimension == 1 ) 705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_blues_snap_stem( &globals->blues, 706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->org_pos + hint->org_len, 707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->org_pos, 708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &align ); 709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project switch ( align.align ) 711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_TOP: 713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the top of the stem is aligned against a blue zone */ 714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = align.align_top - fit_len; 715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_BOT: 718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the bottom of the stem is aligned against a blue zone */ 719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = align.align_bot; 720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT: 723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* both edges of the stem are aligned against blue zones */ 724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = align.align_bot; 725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_len = align.align_top - align.align_bot; 726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project default: 729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint parent = hint->parent; 731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( parent ) 734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos par_org_center, par_cur_center; 736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos cur_org_center, cur_delta; 737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* ensure that parent is already fitted */ 740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_hint_is_fitted( parent ) ) 741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_align_light( parent, globals, dimension, glyph ); 742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project par_org_center = parent->org_pos + ( parent->org_len / 2 ); 744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project par_cur_center = parent->cur_pos + ( parent->cur_len / 2 ); 745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_org_center = hint->org_pos + ( hint->org_len / 2 ); 746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); 748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos = par_cur_center + cur_delta - ( len >> 1 ); 749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Stems less than one pixel wide are easy -- we want to 752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * make them as dark as possible, so they must fall within 753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * one pixel. If the stem is split between two pixels 754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * then snap the edge that is nearer to the pixel boundary 755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * to the pixel boundary. 756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len <= 64 ) 758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( pos + len + 63 ) / 64 != pos / 64 + 1 ) 760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos += psh_hint_snap_stem_side_delta ( pos, len ); 761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Position stems other to minimize the amount of mid-grays. 764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * There are, in general, two positions that do this, 765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * illustrated as A) and B) below. 766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * + + + + 768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * A) |--------------------------------| 770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * B) |--------------------------------| 771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * C) |--------------------------------| 772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * Position A) (split the excess stem equally) should be better 774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * for stems of width N + f where f < 0.5. 775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * Position B) (split the deficiency equally) should be better 777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * for stems of width N + f where f > 0.5. 778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * It turns out though that minimizing the total number of lit 780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * pixels is also important, so position C), with one edge 781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * aligned with a pixel boundary is actually preferable 782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * to A). There are also more possibile positions for C) than 783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * for A) or B), so it involves less distortion of the overall 784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * character shape. 785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else /* len > 64 */ 787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed frac_len = len & 63; 789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed center = pos + ( len >> 1 ); 790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta_a, delta_b; 791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( len / 64 ) & 1 ) 794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta_a = FT_PIX_FLOOR( center ) + 32 - center; 796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta_b = FT_PIX_ROUND( center ) - center; 797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta_a = FT_PIX_ROUND( center ) - center; 801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta_b = FT_PIX_FLOOR( center ) + 32 - center; 802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* We choose between B) and C) above based on the amount 805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * of fractinal stem width; for small amounts, choose 806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * C) always, for large amounts, B) always, and inbetween, 807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * pick whichever one involves less stem movement. 808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( frac_len < 32 ) 810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos += psh_hint_snap_stem_side_delta ( pos, len ); 812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( frac_len < 48 ) 814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed side_delta = psh_hint_snap_stem_side_delta ( pos, 816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len ); 817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) ) 819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos += side_delta; 820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos += delta_b; 822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pos += delta_b; 826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->cur_pos = pos; 830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } /* switch */ 832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_set_fitted( hint ); 834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ps_debug_hint_func ) 837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_debug_hint_func( hint, dimension ); 838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 0 */ 843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_align_hints( PSH_Hint_Table table, 847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Globals globals, 848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension, 849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Glyph glyph ) 850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint; 852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count; 853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim = &globals->dimension[dimension]; 857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale = dim->scale_mult; 858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta = dim->scale_delta; 859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ps_debug_no_vert_hints && dimension == 0 ) 862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_simple_scale( table, scale, delta, dimension ); 864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ps_debug_no_horz_hints && dimension == 1 ) 868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_simple_scale( table, scale, delta, dimension ); 870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_HINTER*/ 874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint = table->hints; 876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project count = table->max_hints; 877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, hint++ ) 879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_align( hint, globals, dimension, glyph ); 880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** POINTS INTERPOLATION ROUTINES *****/ 887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define xxDEBUG_ZONES 892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_ZONES 895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 8960a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include FT_CONFIG_STANDARD_LIBRARY_H 897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_print_zone( PSH_Zone zone ) 900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n", 902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project zone->scale / 65536.0, 903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project zone->delta / 64.0, 904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project zone->min, 905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project zone->max ); 906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_ZONES */ 909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** HINTER GLYPH MANAGEMENT *****/ 915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1 920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define psh_corner_is_flat ft_corner_is_flat 922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define psh_corner_orientation ft_corner_orientation 923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else 925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( FT_Int ) 927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_corner_is_flat( FT_Pos x_in, 928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos y_in, 929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos x_out, 930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos y_out ) 931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos ax = x_in; 933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos ay = y_in; 934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos d_in, d_out, d_corner; 936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ax < 0 ) 939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ax = -ax; 940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ay < 0 ) 941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ay = -ay; 942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_in = ax + ay; 943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ax = x_out; 945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ax < 0 ) 946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ax = -ax; 947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ay = y_out; 948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ay < 0 ) 949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ay = -ay; 950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_out = ax + ay; 951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ax = x_out + x_in; 953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ax < 0 ) 954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ax = -ax; 955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ay = y_out + y_in; 956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ay < 0 ) 957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ay = -ay; 958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_corner = ax + ay; 959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return ( d_in + d_out - d_corner ) < ( d_corner >> 4 ); 961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Int 964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_corner_orientation( FT_Pos in_x, 965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos in_y, 966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos out_x, 967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos out_y ) 968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int result; 970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* deal with the trivial cases quickly */ 973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( in_y == 0 ) 974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( in_x >= 0 ) 976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = out_y; 977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = -out_y; 979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( in_x == 0 ) 981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( in_y >= 0 ) 983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = -out_x; 984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = out_x; 986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( out_y == 0 ) 988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( out_x >= 0 ) 990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = in_y; 991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = -in_y; 993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( out_x == 0 ) 995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( out_y >= 0 ) 997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = -in_x; 998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = in_x; 1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else /* general case */ 1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project long long delta = (long long)in_x * out_y - (long long)in_y * out_x; 1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta == 0 ) 1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = 0; 1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = 1 - 2 * ( delta < 0 ); 1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return result; 1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* !1 */ 1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef COMPUTE_INFLEXS 1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute all inflex points in a given glyph */ 1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_compute_inflections( PSH_Glyph glyph ) 1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt n; 1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < glyph->num_contours; n++ ) 1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point first, start, end, before, after; 1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos in_x, in_y, out_x, out_y; 1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int orient_prev, orient_cur; 1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int finished = 0; 1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* we need at least 4 points to create an inflection point */ 1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( glyph->contours[n].count < 4 ) 1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute first segment in contour */ 1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = glyph->contours[n].start; 1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project start = end = first; 1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end = end->next; 1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( end == first ) 1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Skip; 1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_x = end->org_u - start->org_u; 1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_y = end->org_v - start->org_v; 1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( in_x == 0 && in_y == 0 ); 1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* extend the segment start whenever possible */ 1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = start; 1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project start = before; 1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = before->prev; 1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before == first ) 1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Skip; 1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project out_x = start->org_u - before->org_u; 1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project out_y = start->org_v - before->org_v; 1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( out_x == 0 && out_y == 0 ); 1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project orient_prev = psh_corner_orientation( in_x, in_y, out_x, out_y ); 1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( orient_prev == 0 ); 1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = start; 1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_x = out_x; 1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_y = out_y; 1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now, process all segments in the contour */ 1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* first, extend current segment's end whenever possible */ 1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = end; 1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end = after; 1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = after->next; 1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( after == first ) 1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project finished = 1; 1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project out_x = after->org_u - end->org_u; 1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project out_y = after->org_v - end->org_v; 1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( out_x == 0 && out_y == 0 ); 1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y ); 1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( orient_cur == 0 ); 1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( orient_cur ^ orient_prev ) < 0 ) 1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_inflex( start ); 1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project start = start->next; 1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( start != end ); 1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_inflex( start ); 1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project start = end; 1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project end = after; 1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project orient_prev = orient_cur; 1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_x = out_x; 1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project in_y = out_y; 1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( !finished ); 1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Skip: 1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ; 1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* COMPUTE_INFLEXS */ 1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_done( PSH_Glyph glyph ) 1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory = glyph->memory; 1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_done( &glyph->hint_tables[1], memory ); 1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_done( &glyph->hint_tables[0], memory ); 1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( glyph->points ); 1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( glyph->contours ); 1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->num_points = 0; 1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->num_contours = 0; 1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1143ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki glyph->memory = NULL; 1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static int 1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_compute_dir( FT_Pos dx, 1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dy ) 1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos ax, ay; 1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project int result = PSH_DIR_NONE; 1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1155727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease ax = FT_ABS( dx ); 1156727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease ay = FT_ABS( dy ); 1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ay * 12 < ax ) 1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* |dy| <<< |dx| means a near-horizontal segment */ 1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT; 1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( ax * 12 < ay ) 1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* |dx| <<< |dy| means a near-vertical segment */ 1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN; 1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return result; 1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* load outline point coordinates into hinter glyph */ 1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_load_points( PSH_Glyph glyph, 1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension ) 1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec = glyph->outline->points; 1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = glyph->points; 1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = glyph->num_points; 1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, point++, vec++ ) 1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags2 = 0; 1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->hint = NULL; 1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dimension == 0 ) 1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->org_u = vec->x; 1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->org_v = vec->y; 1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->org_u = vec->y; 1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->org_v = vec->x; 1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->org_x = vec->x; 1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->org_y = vec->y; 1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* save hinted point coordinates back to outline */ 1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_save_points( PSH_Glyph glyph, 1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension ) 1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt n; 1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = glyph->points; 1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec = glyph->outline->points; 1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project char* tags = glyph->outline->tags; 1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < glyph->num_points; n++ ) 1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dimension == 0 ) 1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[n].x = point->cur_u; 1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project vec[n].y = point->cur_u; 1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_strong( point ) ) 1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 ); 1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dimension == 0 ) 1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_x = point->cur_u; 1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags_x = point->flags2 | point->flags; 1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_y = point->cur_u; 1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags_y = point->flags2 | point->flags; 1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point++; 1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_init( PSH_Glyph glyph, 1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline, 1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Hints ps_hints, 1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Globals globals ) 1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory; 1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* clear all fields */ 1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_MEM_ZERO( glyph, sizeof ( *glyph ) ); 1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project memory = glyph->memory = globals->memory; 1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* allocate and setup points + contours arrays */ 1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) || 1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_NEW_ARRAY( glyph->contours, outline->n_contours ) ) 1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1268ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki glyph->num_points = (FT_UInt)outline->n_points; 1269ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki glyph->num_contours = (FT_UInt)outline->n_contours; 1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt first = 0, next, n; 1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point points = glyph->points; 1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Contour contour = glyph->contours; 1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < glyph->num_contours; n++ ) 1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1279ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki FT_UInt count; 1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point; 1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1283ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki next = (FT_UInt)outline->contours[n] + 1; 1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project count = next - first; 1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project contour->start = points + first; 1287ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki contour->count = count; 1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( count > 0 ) 1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = points + first; 1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->prev = points + next - 1; 1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->contour = contour; 1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 1; count-- ) 1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point[0].next = point + 1; 1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point[1].prev = point; 1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point++; 1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->contour = contour; 1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->next = points + first; 1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project contour++; 1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = next; 1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point points = glyph->points; 1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = points; 1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Vector* vec = outline->points; 1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt n; 1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < glyph->num_points; n++, point++ ) 1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int n_prev = (FT_Int)( point->prev - points ); 1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int n_next = (FT_Int)( point->next - points ); 1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dxi, dyi, dxo, dyo; 1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) ) 1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags = PSH_POINT_OFF; 1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dxi = vec[n].x - vec[n_prev].x; 1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dyi = vec[n].y - vec[n_prev].y; 1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi ); 1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dxo = vec[n_next].x - vec[n].x; 1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dyo = vec[n_next].y - vec[n].y; 1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo ); 1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* detect smooth points */ 1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point->flags & PSH_POINT_OFF ) 1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= PSH_POINT_SMOOTH; 1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( point->dir_in == point->dir_out ) 1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point->dir_out != PSH_DIR_NONE || 1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_corner_is_flat( dxi, dyi, dxo, dyo ) ) 1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= PSH_POINT_SMOOTH; 1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->outline = outline; 1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->globals = globals; 1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef COMPUTE_INFLEXS 1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_load_points( glyph, 0 ); 1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_compute_inflections( glyph ); 1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* COMPUTE_INFLEXS */ 1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now deal with hints tables */ 1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = psh_hint_table_init( &glyph->hint_tables [0], 1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &ps_hints->dimension[0].hints, 1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &ps_hints->dimension[0].masks, 1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &ps_hints->dimension[0].counters, 1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project memory ); 1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = psh_hint_table_init( &glyph->hint_tables [1], 1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &ps_hints->dimension[1].hints, 1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &ps_hints->dimension[1].masks, 1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project &ps_hints->dimension[1].counters, 1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project memory ); 1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute all extrema in a glyph for a given dimension */ 1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_compute_extrema( PSH_Glyph glyph ) 1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt n; 1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* first of all, compute all local extrema */ 1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < glyph->num_contours; n++ ) 1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point first = glyph->contours[n].start; 1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point, before, after; 1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( glyph->contours[n].count == 0 ) 1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = first; 1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = point; 1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = before->prev; 1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before == first ) 1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Skip; 1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( before->org_u == point->org_u ); 1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = point = before->next; 1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for (;;) 1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = point; 1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = after->next; 1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( after == first ) 1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Next; 1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( after->org_u == point->org_u ); 1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before->org_u < point->org_u ) 1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( after->org_u < point->org_u ) 1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* local maximum */ 1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Extremum; 1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else /* before->org_u > point->org_u */ 1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( after->org_u > point->org_u ) 1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* local minimum */ 1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Extremum: 1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_extremum( point ); 1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = point->next; 1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( point != after ); 1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = after->prev; 1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = after; 1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } /* for */ 1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Next: 1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ; 1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* for each extremum, determine its direction along the */ 1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* orthogonal axis */ 1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < glyph->num_points; n++ ) 1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point, before, after; 1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = &glyph->points[n]; 1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = point; 1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = point; 1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_extremum( point ) ) 1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = before->prev; 1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before == point ) 1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Skip; 1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( before->org_v == point->org_v ); 1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = after->next; 1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( after == point ) 1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Skip; 1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( after->org_v == point->org_v ); 1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before->org_v < point->org_v && 1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after->org_v > point->org_v ) 1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_positive( point ); 1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( before->org_v > point->org_v && 1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after->org_v < point->org_v ) 1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_negative( point ); 1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Skip: 1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ; 1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* major_dir is the direction for points on the bottom/left of the stem; */ 1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Points on the top/right of the stem will have a direction of */ 1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* -major_dir. */ 1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_find_strong_points( PSH_Hint_Table table, 1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point, 1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count, 1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int threshold, 1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int major_dir ) 1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint* sort = table->sort; 1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_hints = table->num_hints; 1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, point++ ) 1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int point_dir = 0; 1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos org_u = point->org_u; 1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_strong( point ) ) 1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) ) 1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point_dir = point->dir_in; 1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) ) 1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point_dir = point->dir_out; 1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point_dir ) 1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point_dir == major_dir ) 1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt nn; 1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( nn = 0; nn < num_hints; nn++ ) 1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = sort[nn]; 1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos d = org_u - hint->org_pos; 1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d < threshold && -d < threshold ) 1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_strong( point ); 1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags2 |= PSH_POINT_EDGE_MIN; 1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->hint = hint; 1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( point_dir == -major_dir ) 1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt nn; 1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( nn = 0; nn < num_hints; nn++ ) 1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = sort[nn]; 1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos d = org_u - hint->org_pos - hint->org_len; 1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d < threshold && -d < threshold ) 1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_strong( point ); 1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags2 |= PSH_POINT_EDGE_MAX; 1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->hint = hint; 1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1 1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( psh_point_is_extremum( point ) ) 1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* treat extrema as special cases for stem edge alignment */ 1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt nn, min_flag, max_flag; 1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( major_dir == PSH_DIR_HORIZONTAL ) 1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project min_flag = PSH_POINT_POSITIVE; 1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project max_flag = PSH_POINT_NEGATIVE; 1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project min_flag = PSH_POINT_NEGATIVE; 1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project max_flag = PSH_POINT_POSITIVE; 1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point->flags2 & min_flag ) 1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( nn = 0; nn < num_hints; nn++ ) 1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = sort[nn]; 1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos d = org_u - hint->org_pos; 1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d < threshold && -d < threshold ) 1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags2 |= PSH_POINT_EDGE_MIN; 1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->hint = hint; 1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_strong( point ); 1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( point->flags2 & max_flag ) 1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( nn = 0; nn < num_hints; nn++ ) 1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = sort[nn]; 1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos d = org_u - hint->org_pos - hint->org_len; 1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d < threshold && -d < threshold ) 1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags2 |= PSH_POINT_EDGE_MAX; 1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->hint = hint; 1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_strong( point ); 1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point->hint == NULL ) 1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( nn = 0; nn < num_hints; nn++ ) 1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = sort[nn]; 1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( org_u >= hint->org_pos && 1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_u <= hint->org_pos + hint->org_len ) 1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->hint = hint; 1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 1 */ 1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the accepted shift for strong points in fractional pixels */ 1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PSH_STRONG_THRESHOLD 32 1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the maximum shift value in font units */ 1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PSH_STRONG_THRESHOLD_MAXIMUM 30 1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* find strong points in a glyph */ 1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_find_strong_points( PSH_Glyph glyph, 1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension ) 1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* a point is `strong' if it is located on a stem edge and */ 1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* has an `in' or `out' tangent parallel to the hint's direction */ 1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint_Table table = &glyph->hint_tables[dimension]; 1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PS_Mask mask = table->hint_masks->masks; 1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_masks = table->hint_masks->num_masks; 1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt first = 0; 1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int major_dir = dimension == 0 ? PSH_DIR_VERTICAL 1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project : PSH_DIR_HORIZONTAL; 1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim = &glyph->globals->dimension[dimension]; 1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale = dim->scale_mult; 1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int threshold; 1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale ); 1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM ) 1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = PSH_STRONG_THRESHOLD_MAXIMUM; 1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process secondary hints to `selected' points */ 1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( num_masks > 1 && glyph->num_points > 0 ) 1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1683aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich /* the `endchar' op can reduce the number of points */ 1684aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich first = mask->end_point > glyph->num_points 1685aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich ? glyph->num_points 1686aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich : mask->end_point; 1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project mask++; 1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; num_masks > 1; num_masks--, mask++ ) 1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1690ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki FT_UInt next = FT_MIN( mask->end_point, glyph->num_points ); 1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1693ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki if ( next > first ) 1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1695ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki FT_UInt count = next - first; 1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = glyph->points + first; 1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_activate_mask( table, mask ); 1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_find_strong_points( table, point, count, 1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold, major_dir ); 1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = next; 1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* process primary hints for all points */ 1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( num_masks == 1 ) 1710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = glyph->num_points; 1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = glyph->points; 1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_activate_mask( table, table->hint_masks->masks ); 1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_find_strong_points( table, point, count, 1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold, major_dir ); 1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now, certain points may have been attached to a hint and */ 1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* not marked as strong; update their flags then */ 1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = glyph->num_points; 1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = glyph->points; 1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, point++ ) 1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point->hint && !psh_point_is_strong( point ) ) 1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_strong( point ); 1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* find points in a glyph which are in a blue zone and have `in' or */ 1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* `out' tangents parallel to the horizontal axis */ 1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_find_blue_points( PSH_Blues blues, 1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Glyph glyph ) 1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Blue_Table table; 1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Blue_Zone zone; 1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt glyph_count = glyph->num_points; 1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt blue_count; 1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = glyph->points; 1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; glyph_count > 0; glyph_count--, point++ ) 1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos y; 1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check tangents */ 1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !PSH_DIR_COMPARE( point->dir_in, PSH_DIR_HORIZONTAL ) && 1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) ) 1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* skip strong points */ 1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_strong( point ) ) 1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project y = point->org_u; 1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* look up top zones */ 1765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table = &blues->normal_top; 1766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project blue_count = table->count; 1767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project zone = table->zones; 1768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; blue_count > 0; blue_count--, zone++ ) 1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta = y - zone->org_bottom; 1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta < -blues->blue_fuzz ) 1775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( y <= zone->org_top + blues->blue_fuzz ) 1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( blues->no_overshoots || delta <= blues->blue_threshold ) 1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = zone->cur_bottom; 1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_strong( point ); 1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_fitted( point ); 1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* look up bottom zones */ 1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project table = &blues->normal_bottom; 1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project blue_count = table->count; 1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project zone = table->zones + blue_count - 1; 1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; blue_count > 0; blue_count--, zone-- ) 1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta = zone->org_top - y; 1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta < -blues->blue_fuzz ) 1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( y >= zone->org_bottom - blues->blue_fuzz ) 1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( blues->no_overshoots || delta < blues->blue_threshold ) 1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = zone->cur_top; 1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_strong( point ); 1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_fitted( point ); 1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* interpolate strong points with the help of hinted coordinates */ 1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_interpolate_strong_points( PSH_Glyph glyph, 1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension ) 1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim = &glyph->globals->dimension[dimension]; 1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale = dim->scale_mult; 1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt count = glyph->num_points; 1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point = glyph->points; 1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; count > 0; count--, point++ ) 1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Hint hint = point->hint; 1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( hint ) 1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta; 1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_edge_min( point ) ) 1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = hint->cur_pos; 1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( psh_point_is_edge_max( point ) ) 1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = hint->cur_pos + hint->cur_len; 1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = point->org_u - hint->org_pos; 1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta <= 0 ) 1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = hint->cur_pos + FT_MulFix( delta, scale ); 1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta >= hint->org_len ) 1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = hint->cur_pos + hint->cur_len + 1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_MulFix( delta - hint->org_len, scale ); 1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 18507f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner else /* hint->org_len > 0 */ 1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = hint->cur_pos + 1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_MulDiv( delta, hint->cur_len, 1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint->org_len ); 1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_fitted( point ); 1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PSH_MAX_STRONG_INTERNAL 16 1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_interpolate_normal_points( PSH_Glyph glyph, 1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension ) 1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1 1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* first technique: a point is strong if it is a local extremum */ 1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim = &glyph->globals->dimension[dimension]; 1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale = dim->scale_mult; 1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory = glyph->memory; 1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point* strongs = NULL; 1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point strongs_0[PSH_MAX_STRONG_INTERNAL]; 1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_strongs = 0; 1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point points = glyph->points; 1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point points_end = points + glyph->num_points; 1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point point; 1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* first count the number of strong points */ 1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( point = points; point < points_end; point++ ) 1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_strong( point ) ) 1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_strongs++; 1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( num_strongs == 0 ) /* nothing to do here */ 1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* allocate an array to store a list of points, */ 1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* stored in increasing org_u order */ 1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( num_strongs <= PSH_MAX_STRONG_INTERNAL ) 1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project strongs = strongs_0; 1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_NEW_ARRAY( strongs, num_strongs ) ) 1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_strongs = 0; 1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( point = points; point < points_end; point++ ) 1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point* insert; 1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_point_is_strong( point ) ) 1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( insert = strongs + num_strongs; insert > strongs; insert-- ) 1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( insert[-1]->org_u <= point->org_u ) 1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project insert[0] = insert[-1]; 1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project insert[0] = point; 1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project num_strongs++; 1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now try to interpolate all normal points */ 1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( point = points; point < points_end; point++ ) 1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_strong( point ) ) 1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* sometimes, some local extrema are smooth points */ 1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_smooth( point ) ) 1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point->dir_in == PSH_DIR_NONE || 1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->dir_in != point->dir_out ) 1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_point_is_extremum( point ) && 1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project !psh_point_is_inflex( point ) ) 1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags &= ~PSH_POINT_SMOOTH; 1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* find best enclosing point coordinates then interpolate */ 1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point before, after; 1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt nn; 1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( nn = 0; nn < num_strongs; nn++ ) 1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( strongs[nn]->org_u > point->org_u ) 1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( nn == 0 ) /* point before the first strong point */ 1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = strongs[0]; 1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = after->cur_u + 1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_MulFix( point->org_u - after->org_u, 1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale ); 1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = strongs[nn - 1]; 1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( nn = num_strongs; nn > 0; nn-- ) 1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( strongs[nn - 1]->org_u < point->org_u ) 1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( nn == num_strongs ) /* point is after last strong point */ 1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = strongs[nn - 1]; 1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = before->cur_u + 1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_MulFix( point->org_u - before->org_u, 1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale ); 1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos u; 1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after = strongs[nn]; 1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now interpolate point between before and after */ 1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u = point->org_u; 1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( u == before->org_u ) 1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = before->cur_u; 1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( u == after->org_u ) 1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = after->cur_u; 1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = before->cur_u + 1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_MulDiv( u - before->org_u, 2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after->cur_u - before->cur_u, 2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project after->org_u - before->org_u ); 2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_point_set_fitted( point ); 2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( strongs != strongs_0 ) 2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( strongs ); 2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 1 */ 2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* interpolate other points */ 2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_interpolate_other_points( PSH_Glyph glyph, 2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension ) 2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim = &glyph->globals->dimension[dimension]; 2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale = dim->scale_mult; 2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed delta = dim->scale_delta; 2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Contour contour = glyph->contours; 2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt num_contours = glyph->num_contours; 2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; num_contours > 0; num_contours--, contour++ ) 2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point start = contour->start; 2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Point first, next, point; 2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt fit_count; 2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* count the number of strong points in this contour */ 2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project next = start + contour->count; 2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project fit_count = 0; 2038ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki first = NULL; 2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( point = start; point < next; point++ ) 2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_fitted( point ) ) 2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !first ) 2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = point; 2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project fit_count++; 2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* if there are less than 2 fitted points in the contour, we */ 2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* simply scale and eventually translate the contour points */ 2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( fit_count < 2 ) 2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( fit_count == 1 ) 2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = first->cur_u - FT_MulFix( first->org_u, scale ); 2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( point = start; point < next; point++ ) 2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point != first ) 2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = FT_MulFix( point->org_u, scale ) + delta; 2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Next_Contour; 2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* there are more than 2 strong points in this contour; we */ 2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* need to interpolate weak points between them */ 2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project start = first; 2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* skip consecutive fitted points */ 2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for (;;) 2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project next = first->next; 2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( next == start ) 2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Next_Contour; 2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !psh_point_is_fitted( next ) ) 2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = next; 2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* find next fitted point after unfitted one */ 2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for (;;) 2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project next = next->next; 2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( psh_point_is_fitted( next ) ) 2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now interpolate between them */ 2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos org_a, org_ab, cur_a, cur_ab; 2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos org_c, org_ac, cur_c; 2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale_ab; 2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( first->org_u <= next->org_u ) 2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_a = first->org_u; 2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_a = first->cur_u; 2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_ab = next->org_u - org_a; 2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_ab = next->cur_u - cur_a; 2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_a = next->org_u; 2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_a = next->cur_u; 2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_ab = first->org_u - org_a; 2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_ab = first->cur_u - cur_a; 2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale_ab = 0x10000L; 2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( org_ab > 0 ) 2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale_ab = FT_DivFix( cur_ab, org_ab ); 2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = first->next; 2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_c = point->org_u; 2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_ac = org_c - org_a; 2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( org_ac <= 0 ) 2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* on the left of the interpolation zone */ 2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_c = cur_a + FT_MulFix( org_ac, scale ); 2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( org_ac >= org_ab ) 2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* on the right on the interpolation zone */ 2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale ); 2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* within the interpolation zone */ 2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_c = cur_a + FT_MulFix( org_ac, scale_ab ); 2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->cur_u = cur_c; 2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = point->next; 2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( point != next ); 2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* keep going until all points in the contours have been processed */ 2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project first = next; 2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( first != start ); 2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Next_Contour: 2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ; 2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** HIGH-LEVEL INTERFACE *****/ 2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error 2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_hints_apply( PS_Hints ps_hints, 2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Outline* outline, 2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Globals globals, 2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Render_Mode hint_mode ) 2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_GlyphRec glyphrec; 2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Glyph glyph = &glyphrec; 2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory; 2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int dimension; 2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* something to do? */ 2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( outline->n_points == 0 || outline->n_contours == 0 ) 2180727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return FT_Err_Ok; 2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef DEBUG_HINTER 2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project memory = globals->memory; 2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ps_debug_glyph ) 2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_done( ps_debug_glyph ); 2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_FREE( ps_debug_glyph ); 2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_NEW( glyph ) ) 2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ps_debug_glyph = glyph; 2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* DEBUG_HINTER */ 2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = psh_glyph_init( glyph, outline, ps_hints, globals ); 2200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* try to optimize the y_scale so that the top of non-capital letters 2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * is aligned on a pixel boundary whenever possible 2205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim_x = &glyph->globals->dimension[0]; 2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project PSH_Dimension dim_y = &glyph->globals->dimension[1]; 2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed x_scale = dim_x->scale_mult; 2211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed y_scale = dim_y->scale_mult; 2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed old_x_scale = x_scale; 2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed old_y_scale = y_scale; 2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scaled; 2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed fitted; 2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool rescale = FALSE; 2220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); 2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project fitted = FT_PIX_ROUND( scaled ); 2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( fitted != 0 && scaled != fitted ) 2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project rescale = TRUE; 2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project y_scale = FT_MulDiv( y_scale, fitted, scaled ); 2230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( fitted < scaled ) 2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project x_scale -= x_scale / 50; 2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 ); 2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->do_horz_hints = 1; 2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->do_vert_hints = 1; 2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || 2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint_mode == FT_RENDER_MODE_LCD ); 2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || 2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hint_mode == FT_RENDER_MODE_LCD_V ); 2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); 2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( dimension = 0; dimension < 2; dimension++ ) 2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* load outline coordinates into glyph */ 2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_load_points( glyph, dimension ); 2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute local extrema */ 2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_compute_extrema( glyph ); 2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute aligned stem/hints positions */ 2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_hint_table_align_hints( &glyph->hint_tables[dimension], 2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph->globals, 2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dimension, 2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project glyph ); 2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* find strong points, align them, then interpolate others */ 2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_find_strong_points( glyph, dimension ); 2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dimension == 1 ) 2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_find_blue_points( &globals->blues, glyph ); 2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_interpolate_strong_points( glyph, dimension ); 2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_interpolate_normal_points( glyph, dimension ); 2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_interpolate_other_points( glyph, dimension ); 2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* save hinted coordinates back to outline */ 2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_save_points( glyph, dimension ); 2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( rescale ) 2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_globals_set_scale( glyph->globals, 2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project old_x_scale, old_y_scale, 0, 0 ); 2276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef DEBUG_HINTER 2282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project psh_glyph_done( glyph ); 2283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 2284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */ 2290