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