1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/ 2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* afcjk.c */ 4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 59c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod/* Auto-fitter hinting routines for CJK writing system (body). */ 6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 7fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki/* Copyright 2006-2015 by */ 8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* This file is part of the FreeType project, and may only be used, */ 11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* modified, and distributed under the terms of the FreeType project */ 12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* this file you indicate that you have read the license and */ 14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* understand and accept it fully. */ 15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/ 17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * The algorithm is based on akito's autohint patch, available here: 20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * http://www.kde.gr.jp/~akito/patch/freetype2/ 22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 25aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#include <ft2build.h> 26aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#include FT_ADVANCES_H 27aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#include FT_INTERNAL_DEBUG_H 28aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 29ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#include "afglobal.h" 309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#include "afpic.h" 31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin.h" 32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_CONFIG_OPTION_CJK 35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 36aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#undef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT 37aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afcjk.h" 39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aferrors.h" 40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 42aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER 43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afwarp.h" 44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 48aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* */ 49aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 50aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 51aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* messages during execution. */ 52aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* */ 53aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#undef FT_COMPONENT 54aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#define FT_COMPONENT trace_afcjk 55aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 56aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 57aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /*************************************************************************/ 58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K G L O B A L M E T R I C S *****/ 61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 65aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 66aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* Basically the Latin version with AF_CJKMetrics */ 67aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* to replace AF_LatinMetrics. */ 68aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 69aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_LOCAL_DEF( void ) 70aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_metrics_init_widths( AF_CJKMetrics metrics, 71727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease FT_Face face ) 72aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 73aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* scan the array of segments in each direction */ 74aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_GlyphHintsRec hints[1]; 75aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 76aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 77ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "\n" 789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod "cjk standard widths computation (style `%s')\n" 799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod "===================================================\n" 80ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease "\n", 819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_style_names[metrics->root.style_class->style] )); 82ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 83aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_glyph_hints_init( hints, face->memory ); 84aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 85aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner metrics->axis[AF_DIMENSION_HORZ].width_count = 0; 86aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner metrics->axis[AF_DIMENSION_VERT].width_count = 0; 87aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 88aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 89aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Error error; 909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_ULong glyph_index; 919c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_Long y_offset; 92aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner int dim; 93aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKMetricsRec dummy[1]; 94aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Scaler scaler = &dummy->root.scaler; 95aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 969c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_CONFIG_OPTION_PIC 979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod AF_FaceGlobals globals = metrics->root.globals; 989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif 99aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod AF_StyleClass style_class = metrics->root.style_class; 1019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET 1029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod [style_class->script]; 1039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 1049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_UInt32 standard_char; 1059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 1069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 1079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod standard_char = script_class->standard_char1; 1089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_get_char_index( &metrics->root, 1099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod standard_char, 1109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod &glyph_index, 1119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod &y_offset ); 1129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod if ( !glyph_index ) 1139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod { 1149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod if ( script_class->standard_char2 ) 1159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod { 1169c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod standard_char = script_class->standard_char2; 1179c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_get_char_index( &metrics->root, 1189c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod standard_char, 1199c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod &glyph_index, 1209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod &y_offset ); 1219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod if ( !glyph_index ) 1229c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod { 1239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod if ( script_class->standard_char3 ) 1249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod { 1259c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod standard_char = script_class->standard_char3; 1269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_get_char_index( &metrics->root, 1279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod standard_char, 1289c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod &glyph_index, 1299c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod &y_offset ); 1309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod if ( !glyph_index ) 1319c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod goto Exit; 1329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod } 1339c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod else 1349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod goto Exit; 1359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod } 1369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod } 1379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod else 1389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod goto Exit; 1399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod } 140aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 141ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "standard character: U+%04lX (glyph index %d)\n", 1429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod standard_char, glyph_index )); 143ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 144aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); 145aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( error || face->glyph->outline.n_points <= 0 ) 146aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner goto Exit; 147aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 148aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_ZERO( dummy ); 149aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 150aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner dummy->units_per_em = metrics->units_per_em; 151aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 152aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scaler->x_scale = 0x10000L; 153aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scaler->y_scale = 0x10000L; 154aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scaler->x_delta = 0; 155aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scaler->y_delta = 0; 156aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 157aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scaler->face = face; 158aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scaler->render_mode = FT_RENDER_MODE_NORMAL; 159aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scaler->flags = 0; 160aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1619c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy ); 162aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 163aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner error = af_glyph_hints_reload( hints, &face->glyph->outline ); 164aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( error ) 165aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner goto Exit; 166aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 167aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) 168aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 169aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKAxis axis = &metrics->axis[dim]; 170aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_AxisHints axhints = &hints->axis[dim]; 171aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Segment seg, limit, link; 172aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_UInt num_widths = 0; 173aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 174aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 175ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease error = af_latin_hints_compute_segments( hints, 176ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease (AF_Dimension)dim ); 177aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( error ) 178aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner goto Exit; 179aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 180ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease af_latin_hints_link_segments( hints, 1819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 0, 1829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod NULL, 183ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease (AF_Dimension)dim ); 184aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 185aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner seg = axhints->segments; 186aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner limit = seg + axhints->num_segments; 187aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 188aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( ; seg < limit; seg++ ) 189aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 190aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner link = seg->link; 191aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 192aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* we only consider stem segments there! */ 193aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( link && link->link == seg && link > seg ) 194aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 195aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos dist; 196aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 197aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 198aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner dist = seg->pos - link->pos; 199aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( dist < 0 ) 200aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner dist = -dist; 201aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 202aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( num_widths < AF_CJK_MAX_WIDTHS ) 203aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->widths[num_widths++].org = dist; 204aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 205aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 206aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 207727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease /* this also replaces multiple almost identical stem widths */ 208ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* with a single one (the value 100 is heuristic) */ 209727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease af_sort_and_quantize_widths( &num_widths, axis->widths, 210727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease dummy->units_per_em / 100 ); 211aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->width_count = num_widths; 212aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 213aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 214aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner Exit: 215aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) 216aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 217aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKAxis axis = &metrics->axis[dim]; 218aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos stdw; 219aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 220aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 221aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner stdw = ( axis->width_count > 0 ) ? axis->widths[0].org 222aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner : AF_LATIN_CONSTANT( metrics, 50 ); 223aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 224aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* let's try 20% of the smallest width */ 225aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->edge_distance_threshold = stdw / 5; 226aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->standard_width = stdw; 227aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->extra_light = 0; 228aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 229ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE 230ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 231ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_UInt i; 232aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 233aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 234ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "%s widths:\n", 235ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease dim == AF_DIMENSION_VERT ? "horizontal" 236ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease : "vertical" )); 237aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 238ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " %d (standard)", axis->standard_width )); 239ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease for ( i = 1; i < axis->width_count; i++ ) 240ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " %d", axis->widths[i].org )); 241aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 242ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "\n" )); 243ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 244ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif 245aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 246aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 247aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 248ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "\n" )); 249ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 250ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease af_glyph_hints_done( hints ); 251ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 252aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 253ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 254ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Find all blue zones. */ 255aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 256aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner static void 257ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease af_cjk_metrics_init_blues( AF_CJKMetrics metrics, 258ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Face face ) 259aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 260ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Pos fills[AF_BLUE_STRING_MAX_LEN]; 261ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Pos flats[AF_BLUE_STRING_MAX_LEN]; 262aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 263fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt num_fills; 264fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt num_flats; 265aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 2669c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_Bool fill; 2679c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 268ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_CJKBlue blue; 269ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Error error; 270ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_CJKAxis axis; 271ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Outline outline; 272ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2739c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod AF_StyleClass sc = metrics->root.style_class; 274aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 2759c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod AF_Blue_Stringset bss = sc->blue_stringset; 2769c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod const AF_Blue_StringRec* bs = &af_blue_stringsets[bss]; 277aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 278aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 2799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod /* we walk over the blue character strings as specified in the */ 2809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod /* style's entry in the `af_blue_stringset' array, computing its */ 2819c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod /* extremum points (depending on the string properties) */ 282aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 283ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "cjk blue zones computation\n" 284ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease "==========================\n" 285ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease "\n" )); 286aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 287ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ ) 288aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 289ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease const char* p = &af_blue_strings[bs->string]; 290ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Pos* blue_ref; 291ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Pos* blue_shoot; 292ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 293ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 294ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( AF_CJK_IS_HORIZ_BLUE( bs ) ) 295ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease axis = &metrics->axis[AF_DIMENSION_HORZ]; 296ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease else 297ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease axis = &metrics->axis[AF_DIMENSION_VERT]; 298aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 2999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#ifdef FT_DEBUG_LEVEL_TRACE 3009c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod { 3019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_String* cjk_blue_name[4] = 3029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod { 3039c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (FT_String*)"bottom", /* -- , -- */ 3049c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (FT_String*)"top", /* -- , TOP */ 3059c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (FT_String*)"left", /* HORIZ, -- */ 3069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (FT_String*)"right" /* HORIZ, TOP */ 3079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod }; 3089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 3099c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 3109c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_TRACE5(( "blue zone %d (%s):\n", 3119c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod axis->blue_count, 3129c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod cjk_blue_name[AF_CJK_IS_HORIZ_BLUE( bs ) | 3139c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod AF_CJK_IS_TOP_BLUE( bs ) ] )); 3149c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod } 3159c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#endif /* FT_DEBUG_LEVEL_TRACE */ 316aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 317aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner num_fills = 0; 318aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner num_flats = 0; 319aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 3209c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod fill = 1; /* start with characters that define fill values */ 3219c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_TRACE5(( " [overshoot values]\n" )); 322ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 323ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease while ( *p ) 324aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 325ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_ULong ch; 3269c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_ULong glyph_index; 3279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_Long y_offset; 328ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Pos best_pos; /* same as points.y or points.x, resp. */ 329ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Int best_point; 330ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Vector* points; 331aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 332aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 333ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease GET_UTF8_CHAR( ch, p ); 334aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 3359c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod /* switch to characters that define flat values */ 3369c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod if ( ch == '|' ) 3379c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod { 3389c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod fill = 0; 3399c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_TRACE5(( " [reference values]\n" )); 3409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod continue; 3419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod } 3429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 343ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* load the character in the face -- skip unknown or empty ones */ 3449c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset ); 345ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( glyph_index == 0 ) 346ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 347ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " U+%04lX unavailable\n", ch )); 348ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease continue; 349ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 350aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 351ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); 352ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease outline = face->glyph->outline; 353ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( error || outline.n_points <= 0 ) 354aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 355ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " U+%04lX contains no outlines\n", ch )); 356ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease continue; 357ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 358aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 359ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* now compute min or max point indices and coordinates */ 360ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease points = outline.points; 361ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease best_point = -1; 362ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease best_pos = 0; /* make compiler happy */ 363aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 364ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 365ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Int nn; 366ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Int first = 0; 367ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Int last = -1; 368aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 369aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 370ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ ) 371aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 372ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_Int pp; 373aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 374aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 375ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease last = outline.contours[nn]; 376aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 377ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Avoid single-point contours since they are never rasterized. */ 378ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* In some fonts, they correspond to mark attachment points */ 379ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* which are way outside of the glyph's real outline. */ 380ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( last <= first ) 381ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease continue; 382aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 383ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( AF_CJK_IS_HORIZ_BLUE( bs ) ) 384aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 385ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( AF_CJK_IS_RIGHT_BLUE( bs ) ) 386aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 387aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 388ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( best_point < 0 || points[pp].x > best_pos ) 389aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 390aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_point = pp; 391ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease best_pos = points[pp].x; 392aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 393ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 394ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease else 395ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 396aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 397ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( best_point < 0 || points[pp].x < best_pos ) 398aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 399aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_point = pp; 400ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease best_pos = points[pp].x; 401aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 402ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 403ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 404ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease else 405ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 406ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( AF_CJK_IS_TOP_BLUE( bs ) ) 407ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 408aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 409ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( best_point < 0 || points[pp].y > best_pos ) 410aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 411aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_point = pp; 412ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease best_pos = points[pp].y; 413aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 414ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 415ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease else 416ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 417aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 418ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( best_point < 0 || points[pp].y < best_pos ) 419aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 420aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_point = pp; 421ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease best_pos = points[pp].y; 422aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 423aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 424aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 425aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 426aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 427ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " U+%04lX: best_pos = %5ld\n", ch, best_pos )); 428aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 429ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 4309c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod if ( fill ) 431ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease fills[num_fills++] = best_pos; 432ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease else 433ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease flats[num_flats++] = best_pos; 434aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 435aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 436aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( num_flats == 0 && num_fills == 0 ) 437aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 438aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* 439aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * we couldn't find a single glyph to compute this blue zone, 440aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * we will simply ignore it then 441aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner */ 4429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_TRACE5(( " empty\n" )); 443aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 444aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 445aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 4469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod /* we have computed the contents of the `fill' and `flats' tables, */ 4479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod /* now determine the reference and overshoot position of the blue -- */ 4489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod /* we simply take the median value after a simple sort */ 449aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_sort_pos( num_fills, fills ); 4509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_sort_pos( num_flats, flats ); 451aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 452ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease blue = &axis->blues[axis->blue_count]; 453ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease blue_ref = &blue->ref.org; 454ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease blue_shoot = &blue->shoot.org; 455aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 456aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->blue_count++; 457ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 458aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( num_flats == 0 ) 459aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 460ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease *blue_ref = 461aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner *blue_shoot = fills[num_fills / 2]; 462aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 463aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner else if ( num_fills == 0 ) 464aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 465ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease *blue_ref = 466aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner *blue_shoot = flats[num_flats / 2]; 467aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 468aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner else 469aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 470aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner *blue_ref = fills[num_fills / 2]; 471aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner *blue_shoot = flats[num_flats / 2]; 472aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 473aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 474aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* make sure blue_ref >= blue_shoot for top/right or */ 475aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* vice versa for bottom/left */ 476aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( *blue_shoot != *blue_ref ) 477aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 478aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos ref = *blue_ref; 479aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos shoot = *blue_shoot; 480aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Bool under_ref = FT_BOOL( shoot < ref ); 481aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 482aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 483ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* AF_CJK_IS_TOP_BLUE covers `right' and `top' */ 484ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( AF_CJK_IS_TOP_BLUE( bs ) ^ under_ref ) 485ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease { 486ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease *blue_ref = 487ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease *blue_shoot = ( shoot + ref ) / 2; 488ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 4899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_TRACE5(( " [reference smaller than overshoot," 490ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease " taking mean value]\n" )); 491ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease } 492aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 493aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 494aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->flags = 0; 495ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( AF_CJK_IS_TOP_BLUE( bs ) ) 496ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease blue->flags |= AF_CJK_BLUE_TOP; 497aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 498ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " -> reference = %ld\n" 499ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease " overshoot = %ld\n", 500ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease *blue_ref, *blue_shoot )); 501aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 502aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 503ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "\n" )); 504ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 505aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner return; 506aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 507aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 508aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 509aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* Basically the Latin version with type AF_CJKMetrics for metrics. */ 510ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 511aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_LOCAL_DEF( void ) 512aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_metrics_check_digits( AF_CJKMetrics metrics, 513aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Face face ) 514aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 515aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_UInt i; 516aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Bool started = 0, same_width = 1; 517aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Fixed advance, old_advance = 0; 518aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 519aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 520ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* digit `0' is 0x30 in all supported charmaps */ 521aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( i = 0x30; i <= 0x39; i++ ) 522aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 5239c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_ULong glyph_index; 5249c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_Long y_offset; 525aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 526aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 5279c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_get_char_index( &metrics->root, i, &glyph_index, &y_offset ); 528aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( glyph_index == 0 ) 529aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 530aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 531aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( FT_Get_Advance( face, glyph_index, 532aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_LOAD_NO_SCALE | 533aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_LOAD_NO_HINTING | 534aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_LOAD_IGNORE_TRANSFORM, 535aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner &advance ) ) 536aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 537aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 538aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( started ) 539aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 540aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( advance != old_advance ) 541aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 542aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner same_width = 0; 543aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner break; 544aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 545aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 546aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner else 547aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 548aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner old_advance = advance; 549aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner started = 1; 550aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 551aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 552aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 553aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner metrics->root.digits_have_same_width = same_width; 554aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 555aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 556aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 557ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Initialize global metrics. */ 558ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( FT_Error ) 560aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_metrics_init( AF_CJKMetrics metrics, 561aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Face face ) 562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_CharMap oldmap = face->charmap; 564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project metrics->units_per_em = face->units_per_EM; 567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 568ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( !FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) 569295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner { 570727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease af_cjk_metrics_init_widths( metrics, face ); 571ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease af_cjk_metrics_init_blues( metrics, face ); 572aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_metrics_check_digits( metrics, face ); 573295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner } 574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Set_Charmap( face, oldmap ); 576727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return FT_Err_Ok; 577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 580ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Adjust scaling value, then scale and shift widths */ 581ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* and blue zones (if applicable) for given dimension. */ 582ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 584aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_metrics_scale_dim( AF_CJKMetrics metrics, 585aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Scaler scaler, 586aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Dimension dim ) 587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 588aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Fixed scale; 589aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos delta; 590aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKAxis axis; 591aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_UInt nn; 592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ ) 595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 596aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scale = scaler->x_scale; 597aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta = scaler->x_delta; 598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 601aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scale = scaler->y_scale; 602aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta = scaler->y_delta; 603aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 604aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 605ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease axis = &metrics->axis[dim]; 606ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 607aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( axis->org_scale == scale && axis->org_delta == delta ) 608aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner return; 609aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 610aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->org_scale = scale; 611aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->org_delta = delta; 612aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 613aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->scale = scale; 614aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner axis->delta = delta; 615aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 616aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* scale the blue zones */ 617aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( nn = 0; nn < axis->blue_count; nn++ ) 618aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 619aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKBlue blue = &axis->blues[nn]; 620aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos dist; 621aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 622aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 623aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta; 624aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->ref.fit = blue->ref.cur; 625aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta; 626aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->shoot.fit = blue->shoot.cur; 627aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->flags &= ~AF_CJK_BLUE_ACTIVE; 628aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 629aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* a blue zone is only active if it is less than 3/4 pixels tall */ 630aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale ); 631aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( dist <= 48 && dist >= -48 ) 632aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 633aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos delta1, delta2; 634aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 635aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 636aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); 637aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 638aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* shoot is under shoot for cjk */ 639aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta1 = FT_DivFix( blue->ref.fit, scale ) - blue->shoot.org; 640aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta2 = delta1; 641aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( delta1 < 0 ) 642aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta2 = -delta2; 643aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 644aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta2 = FT_MulFix( delta2, scale ); 645aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 646aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_TRACE5(( "delta: %d", delta1 )); 647aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( delta2 < 32 ) 648aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta2 = 0; 649aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#if 0 650aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner else if ( delta2 < 64 ) 651aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 ); 652aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif 653aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner else 654aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta2 = FT_PIX_ROUND( delta2 ); 655aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_TRACE5(( "/%d\n", delta2 )); 656aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 657aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( delta1 < 0 ) 658aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner delta2 = -delta2; 659aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 660aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->shoot.fit = blue->ref.fit - delta2; 661aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 662ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n" 663ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease " ref: cur=%.2f fit=%.2f\n" 664ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease " shoot: cur=%.2f fit=%.2f\n", 665ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V', 666ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease nn, blue->ref.org, blue->shoot.org, 667ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease blue->ref.cur / 64.0, blue->ref.fit / 64.0, 668ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 )); 669aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 670aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue->flags |= AF_CJK_BLUE_ACTIVE; 671aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 676ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Scale global values in both directions. */ 677ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( void ) 679aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_metrics_scale( AF_CJKMetrics metrics, 680aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Scaler scaler ) 681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 682ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* we copy the whole structure since the x and y scaling values */ 683ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* are not modified, contrary to e.g. the `latin' auto-hinter */ 684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project metrics->root.scaler = *scaler; 685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); 687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); 688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K G L Y P H A N A L Y S I S *****/ 695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 699ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 700ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Walk over all contours and compute its segments. */ 701ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_compute_segments( AF_GlyphHints hints, 704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segments = axis->segments; 708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segment_limit = segments + axis->num_segments; 709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg; 711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_latin_hints_compute_segments( hints, dim ); 714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* a segment is round if it doesn't have successive */ 718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* on-curve points. */ 719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg = segments; seg < segment_limit; seg++ ) 720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point pt = seg->first; 722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point last = seg->last; 723fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt f0 = pt->flags & AF_FLAG_CONTROL; 724fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt f1; 725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->flags &= ~AF_EDGE_ROUND; 728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; pt != last; f0 = f1 ) 730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pt = pt->next; 732fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki f1 = pt->flags & AF_FLAG_CONTROL; 733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !f0 && !f1 ) 735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( pt == last ) 738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->flags |= AF_EDGE_ROUND; 739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 742727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease return FT_Err_Ok; 743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_link_segments( AF_GlyphHints hints, 748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segments = axis->segments; 752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segment_limit = segments + axis->num_segments; 753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Direction major_dir = axis->major_dir; 754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg1, seg2; 755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos len_threshold; 756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist_threshold; 757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 ); 760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist_threshold = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale 762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project : hints->y_scale; 763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist_threshold = FT_DivFix( 64 * 3, dist_threshold ); 764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now compare each segment to the others */ 766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg1 = segments; seg1 < segment_limit; seg1++ ) 767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->dir != major_dir ) 769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg2 = segments; seg2 < segment_limit; seg2++ ) 772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 ) 773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist = seg2->pos - seg1->pos; 775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos min = seg1->min_coord; 782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos max = seg1->max_coord; 783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos len; 784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( min < seg2->min_coord ) 787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project min = seg2->min_coord; 788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( max > seg2->max_coord ) 790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project max = seg2->max_coord; 791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = max - min; 793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len >= len_threshold ) 794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist * 8 < seg1->score * 9 && 796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dist * 8 < seg1->score * 7 || seg1->len < len ) ) 797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->score = dist; 799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->len = len; 800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->link = seg2; 801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist * 8 < seg2->score * 9 && 804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dist * 8 < seg2->score * 7 || seg2->len < len ) ) 805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->score = dist; 807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->len = len; 808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->link = seg1; 809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * now compute the `serif' segments 817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * In Hanzi, some strokes are wider on one or both of the ends. 819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We either identify the stems on the ends as serifs or remove 820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * the linkage, depending on the length of the stems. 821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment link1, link2; 826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg1 = segments; seg1 < segment_limit; seg1++ ) 829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project link1 = seg1->link; 831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !link1 || link1->link != seg1 || link1->pos <= seg1->pos ) 832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->score >= dist_threshold ) 835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg2 = segments; seg2 < segment_limit; seg2++ ) 838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->pos > seg1->pos || seg1 == seg2 ) 840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project link2 = seg2->link; 843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !link2 || link2->link != seg2 || link2->pos < link1->pos ) 844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->pos == seg2->pos && link1->pos == link2->pos ) 847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->score <= seg1->score || seg1->score * 4 <= seg2->score ) 850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* seg2 < seg1 < link1 < link2 */ 853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->len >= seg2->len * 3 ) 855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg; 857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg = segments; seg < segment_limit; seg++ ) 860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment link = seg->link; 862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( link == seg2 ) 865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 866fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki seg->link = NULL; 867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->serif = link1; 868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( link == link2 ) 870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 871fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki seg->link = NULL; 872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->serif = seg1; 873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 878fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki seg1->link = link1->link = NULL; 879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg1 = segments; seg1 < segment_limit; seg1++ ) 887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2 = seg1->link; 889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2 ) 891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->num_linked++; 893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->link != seg1 ) 894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 895fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki seg1->link = NULL; 896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 ) 898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->serif = seg2->link; 899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->num_linked--; 901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_compute_edges( AF_GlyphHints hints, 909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 912727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease FT_Error error = FT_Err_Ok; 913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory = hints->memory; 914aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim]; 915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segments = axis->segments; 917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segment_limit = segments + axis->num_segments; 918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg; 919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale; 921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos edge_distance_threshold; 922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project axis->num_edges = 0; 925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale 927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project : hints->y_scale; 928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*********************************************************************/ 930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* We begin by generating a sorted table of edges for the current */ 932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* direction. To do so, we simply scan each segment and try to find */ 933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* an edge in our table that corresponds to its position. */ 934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* If no edge is found, we create and insert a new edge in the */ 936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* sorted table. Otherwise, we simply add the segment to the edge's */ 937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* list which is then processed in the second step to compute the */ 938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* edge's properties. */ 939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Note that the edges table is sorted along the segment/edge */ 941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* position. */ 942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*********************************************************************/ 944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold, 946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale ); 947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge_distance_threshold > 64 / 4 ) 948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_distance_threshold = FT_DivFix( 64 / 4, scale ); 949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_distance_threshold = laxis->edge_distance_threshold; 951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg = segments; seg < segment_limit; seg++ ) 953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 954ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_Edge found = NULL; 955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos best = 0xFFFFU; 956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int ee; 957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* look for an edge corresponding to the segment */ 960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ee = 0; ee < axis->num_edges; ee++ ) 961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge = axis->edges + ee; 963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist; 964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->dir != seg->dir ) 967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = seg->pos - edge->fpos; 970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -dist; 972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < edge_distance_threshold && dist < best ) 974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment link = seg->link; 976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check whether all linked segments of the candidate edge */ 979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* can make a single edge. */ 980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( link ) 981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 982727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease AF_Segment seg1 = edge->first; 983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist2 = 0; 984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 988727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease AF_Segment link1 = seg1->link; 989727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 990727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease 991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( link1 ) 992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist2 = AF_SEGMENT_DIST( link, link1 ); 994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist2 >= edge_distance_threshold ) 995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( ( seg1 = seg1->edge_next ) != edge->first ); 999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist2 >= edge_distance_threshold ) 1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project best = dist; 1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project found = edge; 1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !found ) 1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* insert a new edge in the list and */ 1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* sort according to the position */ 1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_axis_hints_new_edge( axis, seg->pos, 1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Direction)seg->dir, 1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project memory, &edge ); 1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add the segment to the new edge's list */ 1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ZERO( edge ); 1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->first = seg; 1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->last = seg; 1027fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki edge->dir = seg->dir; 1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->fpos = seg->pos; 1029fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki edge->opos = FT_MulFix( seg->pos, scale ); 1030fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki edge->pos = edge->opos; 1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->edge_next = seg; 1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* if an edge was found, simply add the segment to the edge's */ 1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* list */ 1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->edge_next = found->first; 1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project found->last->edge_next = seg; 1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project found->last = seg; 1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1043ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /******************************************************************/ 1044ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* */ 1045ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Good, we now compute each edge's properties according to the */ 1046ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* segments found on its position. Basically, these are */ 1047ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* */ 1048ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* - the edge's main direction */ 1049ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* - stem edge, serif edge or both (which defaults to stem then) */ 1050ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* - rounded edge, straight or both (which defaults to straight) */ 1051ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* - link for edge */ 1052ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* */ 1053ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /******************************************************************/ 1054ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1055ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* first of all, set the `edge' field in each segment -- this is */ 1056ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* required in order to compute edge links */ 1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1058ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* 1059ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease * Note that removing this loop and setting the `edge' field of each 1060ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease * segment directly in the code above slows down execution speed for 1061ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease * some reasons on platforms like the Sun. 1062ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease */ 1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edges = axis->edges; 1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge_limit = edges + axis->num_edges; 1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = edge->first; 1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg ) 1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->edge = edge; 1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now compute each edge properties */ 1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int is_round = 0; /* does it contain round segments? */ 1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int is_straight = 0; /* does it contain straight segments? */ 1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = edge->first; 1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool is_serif; 1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check for roundness of segment */ 1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg->flags & AF_EDGE_ROUND ) 1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project is_round++; 1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project is_straight++; 1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check for links -- if seg->serif is set, then seg->link must */ 1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* be ignored */ 1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge ); 1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg->link || is_serif ) 1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge2; 1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg2; 1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edge->link; 1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2 = seg->link; 1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( is_serif ) 1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2 = seg->serif; 1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edge->serif; 1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge2 ) 1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos edge_delta; 1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos seg_delta; 1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_delta = edge->fpos - edge2->fpos; 1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge_delta < 0 ) 1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_delta = -edge_delta; 1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg_delta = AF_SEGMENT_DIST( seg, seg2 ); 1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg_delta < edge_delta ) 1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = seg2->edge; 1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = seg2->edge; 1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( is_serif ) 1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->serif = edge2; 1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->flags |= AF_EDGE_SERIF; 1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->link = edge2; 1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* set the round/straight flags */ 1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags = AF_EDGE_NORMAL; 1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( is_round > 0 && is_round >= is_straight ) 1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_ROUND; 1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* get rid of serifs if link is set */ 1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* XXX: This gets rid of many unpleasant artefacts! */ 1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Example: the `c' in cour.pfa at size 13 */ 1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->serif && edge->link ) 1162fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki edge->serif = NULL; 1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1171ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Detect segments and edges for given dimension. */ 1172ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_detect_features( AF_GlyphHints hints, 1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_compute_segments( hints, dim ); 1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !error ) 1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_link_segments( hints, dim ); 1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_compute_edges( hints, dim ); 1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1191ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Compute all edges which lie within blue zones. */ 1192ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1193fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki static void 1194aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_hints_compute_blue_edges( AF_GlyphHints hints, 1195aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKMetrics metrics, 1196aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Dimension dim ) 1197aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1198aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_AxisHints axis = &hints->axis[dim]; 1199aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Edge edge = axis->edges; 1200aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Edge edge_limit = edge + axis->num_edges; 1201aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKAxis cjk = &metrics->axis[dim]; 1202aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Fixed scale = cjk->scale; 1203aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos best_dist0; /* initial threshold */ 1204aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1205aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1206aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* compute the initial threshold as a fraction of the EM size */ 1207aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale ); 1208aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1209aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( best_dist0 > 64 / 2 ) /* maximum 1/2 pixel */ 1210aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_dist0 = 64 / 2; 1211aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1212aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* compute which blue zones are active, i.e. have their scaled */ 1213aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* size < 3/4 pixels */ 1214aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1215aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* If the distant between an edge and a blue zone is shorter than */ 1216aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* best_dist0, set the blue zone for the edge. Then search for */ 1217aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* the blue zone with the smallest best_dist to the edge. */ 1218aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1219aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( ; edge < edge_limit; edge++ ) 1220aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1221aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_UInt bb; 1222aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Width best_blue = NULL; 1223aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos best_dist = best_dist0; 1224aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1225aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1226aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( bb = 0; bb < cjk->blue_count; bb++ ) 1227aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1228aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKBlue blue = cjk->blues + bb; 1229aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Bool is_top_right_blue, is_major_dir; 1230aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1231aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1232aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* skip inactive blue zones (i.e., those that are too small) */ 1233aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( !( blue->flags & AF_CJK_BLUE_ACTIVE ) ) 1234aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 1235aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1236aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* if it is a top zone, check for right edges -- if it is a bottom */ 1237aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* zone, check for left edges */ 1238aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* */ 1239aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* of course, that's for TrueType */ 12409c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod is_top_right_blue = 12419c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (FT_Byte)( ( blue->flags & AF_CJK_BLUE_TOP ) != 0 ); 12429c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod is_major_dir = 12439c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_BOOL( edge->dir == axis->major_dir ); 1244aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1245aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* if it is a top zone, the edge must be against the major */ 1246aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* direction; if it is a bottom zone, it must be in the major */ 1247aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* direction */ 1248aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( is_top_right_blue ^ is_major_dir ) 1249aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1250aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos dist; 1251aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Width compare; 1252aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1253aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1254aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* Compare the edge to the closest blue zone type */ 1255aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( FT_ABS( edge->fpos - blue->ref.org ) > 1256aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_ABS( edge->fpos - blue->shoot.org ) ) 1257aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner compare = &blue->shoot; 1258aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner else 1259aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner compare = &blue->ref; 1260aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1261aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner dist = edge->fpos - compare->org; 1262aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( dist < 0 ) 1263aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner dist = -dist; 1264aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1265aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner dist = FT_MulFix( dist, scale ); 1266aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( dist < best_dist ) 1267aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1268aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_dist = dist; 1269aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner best_blue = compare; 1270aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1271aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1272aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1273aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1274aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( best_blue ) 1275aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge->blue_edge = best_blue; 1276aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1277aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1278aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1279aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1280ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Initalize hinting engine. */ 1281ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( FT_Error ) 1283aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_hints_init( AF_GlyphHints hints, 1284aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKMetrics metrics ) 1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Render_Mode mode; 1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt32 scaler_flags, other_flags; 1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 12909c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics ); 1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * correct x_scale and y_scale when needed, since they may have 1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * been modified af_cjk_scale_dim above 1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale; 1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta; 1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale; 1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta; 1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute flags depending on render mode, etc. */ 1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project mode = metrics->root.scaler.render_mode; 1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1304fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#if 0 /* AF_CONFIG_OPTION_USE_WARPER */ 1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V ) 1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL; 1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scaler_flags = hints->scaler_flags; 1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags = 0; 1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We snap the width of vertical stems for the monochrome and 1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * horizontal LCD rendering targets only. 1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD ) 1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_HORZ_SNAP; 1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We snap the width of horizontal stems for the monochrome and 1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * vertical LCD rendering targets only. 1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V ) 1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_VERT_SNAP; 1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We adjust stems to full pixels only if we don't use the `light' mode. 1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode != FT_RENDER_MODE_LIGHT ) 1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_STEM_ADJUST; 1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_MONO ) 1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_MONO; 1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE; 1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1337fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef AF_CONFIG_OPTION_USE_WARPER 1338fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki /* get (global) warper flag */ 1339fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki if ( !metrics->root.globals->module->warping ) 1340fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki scaler_flags |= AF_SCALER_FLAG_NO_WARPER; 1341fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif 1342fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki 1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->scaler_flags = scaler_flags; 1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->other_flags = other_flags; 1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1346ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease return FT_Err_Ok; 1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K G L Y P H G R I D - F I T T I N G *****/ 1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1358ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Snap a given width in scaled coordinates to one of the */ 1359ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* current standard widths. */ 1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_snap_width( AF_Width widths, 1363fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt count, 1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos width ) 1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1366fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt n; 1367fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_Pos best = 64 + 32 + 2; 1368fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_Pos reference = width; 1369fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_Pos scaled; 1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < count; n++ ) 1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos w; 1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist; 1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project w = widths[n].cur; 1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = width - w; 1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -dist; 1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < best ) 1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project best = dist; 1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project reference = w; 1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scaled = FT_PIX_ROUND( reference ); 1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( width >= reference ) 1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( width < scaled + 48 ) 1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project width = reference; 1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( width > scaled - 48 ) 1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project width = reference; 1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return width; 1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1406ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Compute the snapped width of a given stem. */ 1407ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* There is a lot of voodoo in this function; changing the hard-coded */ 1408ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* parameters influence the whole hinting process. */ 1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_compute_stem_width( AF_GlyphHints hints, 1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim, 1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos width, 1414fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt base_flags, 1415fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_UInt stem_flags ) 1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1417ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_CJKMetrics metrics = (AF_CJKMetrics)hints->metrics; 1418ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_CJKAxis axis = &metrics->axis[dim]; 1419aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos dist = width; 1420aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Int sign = 0; 1421aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Bool vertical = FT_BOOL( dim == AF_DIMENSION_VERT ); 1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( base_flags ); 1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( stem_flags ); 1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ) 1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return width; 1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -width; 1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project sign = 1; 1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || 1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) 1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* smooth hinting process: very lightly quantize the stem width */ 1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( axis->width_count > 0 ) 1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( dist - axis->widths[0].cur ) < 40 ) 1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = axis->widths[0].cur; 1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 48 ) 1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = 48; 1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Done_Width; 1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 54 ) 1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += ( 54 - dist ) / 2 ; 1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( dist < 3 * 64 ) 1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta; 1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = dist & 63; 1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist &= -64; 1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta < 10 ) 1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += delta; 1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 22 ) 1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += 10; 1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 42 ) 1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += delta; 1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 54 ) 1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += 54; 1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += delta; 1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* strong hinting process: snap the stem width to integer pixels */ 1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = af_cjk_snap_width( axis->widths, axis->width_count, dist ); 1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( vertical ) 1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* in the case of vertical hinting, always round */ 1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the stem heights to integer pixels */ 1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist >= 64 ) 1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 16 ) & ~63; 1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = 64; 1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( AF_LATIN_HINTS_DO_MONO( hints ) ) 1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* monochrome horizontal hinting: snap widths to integer pixels */ 1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* with a different threshold */ 1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 64 ) 1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = 64; 1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 32 ) & ~63; 1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* for horizontal anti-aliased hinting, we adopt a more subtle */ 1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* approach: we strengthen small stems, round stems whose size */ 1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* is between 1 and 2 pixels to an integer, otherwise nothing */ 1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 48 ) 1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 64 ) >> 1; 1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( dist < 128 ) 1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 22 ) & ~63; 1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* round otherwise to prevent color fringes in LCD mode */ 1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 32 ) & ~63; 1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Done_Width: 1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( sign ) 1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -dist; 1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return dist; 1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1529ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Align one stem edge relative to the previous stem edge. */ 1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_linked_edge( AF_GlyphHints hints, 1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim, 1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge base_edge, 1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge stem_edge ) 1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist = stem_edge->opos - base_edge->opos; 1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1539fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki FT_Pos fitted_width = af_cjk_compute_stem_width( hints, dim, dist, 1540fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki base_edge->flags, 1541fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki stem_edge->flags ); 1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stem_edge->pos = base_edge->pos + fitted_width; 15459c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 15469c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_TRACE5(( " CJKLINK: edge %d @%d (opos=%.2f) linked to %.2f," 15479c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod " dist was %.2f, now %.2f\n", 15489c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod stem_edge - hints->axis[dim].edges, stem_edge->fpos, 15499c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod stem_edge->opos / 64.0, stem_edge->pos / 64.0, 15509c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod dist / 64.0, fitted_width / 64.0 )); 1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1554ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Shift the coordinates of the `serif' edge by the same amount */ 1555ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* as the corresponding `base' edge has been moved already. */ 1556ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( AF_GlyphHints hints, 1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge base, 1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge serif ) 1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( hints ); 1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project serif->pos = base->pos + ( serif->opos - base->opos ); 1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /**** ****/ 1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /**** E D G E H I N T I N G ****/ 1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /**** ****/ 1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LIGHT_MODE_MAX_HORZ_GAP 9 1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LIGHT_MODE_MAX_VERT_GAP 15 1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LIGHT_MODE_MAX_DELTA_ABS 14 1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( AF_GlyphHints hints, 1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge, 1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge2, 1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos anchor, 1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos org_len, cur_len, org_center; 1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos cur_pos1, cur_pos2; 1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos d_off1, u_off1, d_off2, u_off2, delta; 1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos offset; 1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos threshold = 64; 1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ) 1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( edge->flags & AF_EDGE_ROUND ) && 1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edge2->flags & AF_EDGE_ROUND ) ) 1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_VERT ) 1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP; 1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP; 1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_VERT ) 1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP / 3; 1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP / 3; 1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_len = edge2->opos - edge->opos; 1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_len = af_cjk_compute_stem_width( hints, dim, org_len, 1619fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki edge->flags, 1620fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki edge2->flags ); 1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_center = ( edge->opos + edge2->opos ) / 2 + anchor; 1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_pos1 = org_center - cur_len / 2; 1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_pos2 = cur_pos1 + cur_len; 1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off1 = cur_pos1 - FT_PIX_FLOOR( cur_pos1 ); 1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off2 = cur_pos2 - FT_PIX_FLOOR( cur_pos2 ); 1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off1 = 64 - d_off1; 1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off2 = 64 - d_off2; 1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = 0; 1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off1 == 0 || d_off2 == 0 ) 1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( cur_len <= threshold ) 1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off2 < cur_len ) 1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( u_off1 <= d_off2 ) 1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = u_off1; 1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = -d_off2; 1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( threshold < 64 ) 1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off1 >= threshold || u_off1 >= threshold || 1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off2 >= threshold || u_off2 >= threshold ) 1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 165541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier offset = cur_len & 63; 1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( offset < 32 ) 1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( u_off1 <= offset || d_off2 <= offset ) 1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project offset = 64 - threshold; 1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off1 = threshold - u_off1; 1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off1 = u_off1 - offset; 1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off2 = threshold - d_off2; 1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off2 = d_off2 - offset; 1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off1 <= u_off1 ) 1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off1 = -d_off1; 1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off2 <= u_off2 ) 1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off2 = -d_off2; 1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( u_off1 ) <= FT_ABS( u_off2 ) ) 1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = u_off1; 1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = u_off2; 1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1 1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ) 1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta > AF_LIGHT_MODE_MAX_DELTA_ABS ) 1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = AF_LIGHT_MODE_MAX_DELTA_ABS; 1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < -AF_LIGHT_MODE_MAX_DELTA_ABS ) 1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = -AF_LIGHT_MODE_MAX_DELTA_ABS; 1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_pos1 += delta; 1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->opos < edge2->opos ) 1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->pos = cur_pos1; 1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->pos = cur_pos1 + cur_len; 1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->pos = cur_pos1 + cur_len; 1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->pos = cur_pos1; 1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return delta; 1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1710ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* The main grid-fitting routine. */ 1711ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hint_edges( AF_GlyphHints hints, 1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edges = axis->edges; 1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge_limit = edges + axis->num_edges; 1719295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_PtrDist n_edges; 1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 1721fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki AF_Edge anchor = NULL; 1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta = 0; 1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int skipped = 0; 1724aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Bool has_last_stem = FALSE; 1725aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Pos last_stem_pos = 0; 1726aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1727ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE 1728ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_UInt num_actions = 0; 1729ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif 1730ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1731ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 17329c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod FT_TRACE5(( "cjk %s edge hinting (style `%s')\n", 1733ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease dim == AF_DIMENSION_VERT ? "horizontal" : "vertical", 17349c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod af_style_names[hints->metrics->style_class->style] )); 1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1736aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* we begin by aligning all stems relative to the blue zone */ 1737aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1738aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( AF_HINTS_DO_BLUES( hints ) ) 1739aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1740aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner for ( edge = edges; edge < edge_limit; edge++ ) 1741aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1742aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Width blue; 1743aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_Edge edge1, edge2; 1744aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1745aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1746aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( edge->flags & AF_EDGE_DONE ) 1747aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 1748aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1749aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue = edge->blue_edge; 1750aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge1 = NULL; 1751aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge2 = edge->link; 1752aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1753aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( blue ) 1754aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1755aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge1 = edge; 1756aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1757aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner else if ( edge2 && edge2->blue_edge ) 1758aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1759aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner blue = edge2->blue_edge; 1760aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge1 = edge2; 1761aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge2 = edge; 1762aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1763aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1764aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( !edge1 ) 1765aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 1766aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1767ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE 1768ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " CJKBLUE: edge %d @%d (opos=%.2f) snapped to %.2f," 1769ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease " was %.2f\n", 1770ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease edge1 - edges, edge1->fpos, edge1->opos / 64.0, 1771ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease blue->fit / 64.0, edge1->pos / 64.0 )); 1772ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1773ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease num_actions++; 1774ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif 1775aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1776aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge1->pos = blue->fit; 1777aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge1->flags |= AF_EDGE_DONE; 1778aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1779aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( edge2 && !edge2->blue_edge ) 1780aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1781aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_align_linked_edge( hints, dim, edge1, edge2 ); 1782aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge2->flags |= AF_EDGE_DONE; 1783ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1784ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE 1785ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease num_actions++; 1786ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif 1787aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1788aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1789aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( !anchor ) 1790aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner anchor = edge; 1791aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1792aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now we align all stem edges. */ 1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge2; 1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->flags & AF_EDGE_DONE ) 1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* skip all non-stem edges */ 1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edge->link; 1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !edge2 ) 1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project skipped++; 1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1811aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* Some CJK characters have so many stems that 1812aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * the hinter is likely to merge two adjacent ones. 1813aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * To solve this problem, if either edge of a stem 1814aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * is too close to the previous one, we avoid 1815aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * aligning the two edges, but rather interpolate 1816aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * their locations at the end of this function in 1817aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * order to preserve the space between the stems. 1818aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner */ 1819aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( has_last_stem && 1820aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner ( edge->pos < last_stem_pos + 64 || 1821aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge2->pos < last_stem_pos + 64 ) ) 1822aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1823aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner skipped++; 1824aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 1825aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1826aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now align the stem */ 1828ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1829aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* this should not happen, but it's better to be safe */ 1830aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner if ( edge2->blue_edge ) 1831aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner { 1832aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges )); 1833aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 1834aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_align_linked_edge( hints, dim, edge2, edge ); 1835aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner edge->flags |= AF_EDGE_DONE; 1836ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1837ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE 1838ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease num_actions++; 1839ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif 1840ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1841aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner continue; 1842aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner } 1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge2 < edge ) 1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_linked_edge( hints, dim, edge2, edge ); 1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_DONE; 1848ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1849ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE 1850ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease num_actions++; 1851ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif 1852ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 1853aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner /* We rarely reaches here it seems; 1854aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * usually the two edges belonging 1855aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner * to one stem are marked as DONE together 1856aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner */ 1857aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner has_last_stem = TRUE; 1858aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner last_stem_pos = edge->pos; 1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim != AF_DIMENSION_VERT && !anchor ) 1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0 1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( fixedpitch ) 1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge left = edge; 1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge right = edge_limit - 1; 1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_EdgeRec left1, left2, right1, right2; 1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos target, center1, center2; 1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta1, delta2, d1, d2; 1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( right > left && !right->link ) 1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right--; 1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left1 = *left; 1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left2 = *left->link; 1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right1 = *right->link; 1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right2 = *right; 1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = ( ( ( hinter->pp2.x + 32 ) & -64 ) - hinter->pp2.x ) / 2; 1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project target = left->opos + ( right->opos - left->opos ) / 2 + delta - 16; 1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1 = delta; 1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1 += af_hint_normal_stem( hints, left, left->link, 1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1, 0 ); 1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left->link != right ) 1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( hints, right->link, right, delta1, 0 ); 1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project center1 = left->pos + ( right->pos - left->pos ) / 2; 1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( center1 >= target ) 1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta2 = delta - 32; 1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta2 = delta + 32; 1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta2 += af_hint_normal_stem( hints, &left1, &left2, delta2, 0 ); 1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta1 != delta2 ) 1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left->link != right ) 1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( hints, &right1, &right2, delta2, 0 ); 1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project center2 = left1.pos + ( right2.pos - left1.pos ) / 2; 1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d1 = center1 - target; 1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d2 = center2 - target; 1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( d2 ) < FT_ABS( d1 ) ) 1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left->pos = left1.pos; 1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left->link->pos = left2.pos; 1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left->link != right ) 1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->link->pos = right1.pos; 1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->pos = right2.pos; 1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1 = delta2; 1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = delta1; 1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->link->flags |= AF_EDGE_DONE; 1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->flags |= AF_EDGE_DONE; 1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 0 */ 1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = af_hint_normal_stem( hints, edge, edge2, 0, 1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_DIMENSION_HORZ ); 1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( hints, edge, edge2, delta, dim ); 1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0 1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project printf( "stem (%d,%d) adjusted (%.1f,%.1f)\n", 1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge - edges, edge2 - edges, 1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edge->pos - edge->opos ) / 64.0, 1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edge2->pos - edge2->opos ) / 64.0 ); 1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project anchor = edge; 1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_DONE; 1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->flags |= AF_EDGE_DONE; 1951aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner has_last_stem = TRUE; 1952aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner last_stem_pos = edge2->pos; 1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* make sure that lowercase m's maintain their symmetry */ 1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* In general, lowercase m's have six vertical edges if they are sans */ 1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* serif, or twelve if they are with serifs. This implementation is */ 1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* based on that assumption, and seems to work very well with most */ 1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* faces. However, if for a certain face this assumption is not */ 1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* true, the m is just rendered like before. In addition, any stem */ 1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* correction will only be applied to symmetrical glyphs (even if the */ 1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* glyph is not an m), so the potential for unwanted distortion is */ 1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* relatively low. */ 1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* We don't handle horizontal edges since we can't easily assure that */ 1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the third (lowest) stem aligns with the base line; it might end up */ 1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* one pixel higher or lower. */ 1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project n_edges = edge_limit - edges; 1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) ) 1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge1, edge2, edge3; 1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist1, dist2, span; 1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( n_edges == 6 ) 1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge1 = edges; 1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edges + 2; 1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3 = edges + 4; 1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge1 = edges + 1; 1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edges + 5; 1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3 = edges + 9; 1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist1 = edge2->opos - edge1->opos; 1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist2 = edge3->opos - edge2->opos; 1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project span = dist1 - dist2; 1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( span < 0 ) 1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project span = -span; 1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge1->link == edge1 + 1 && 1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->link == edge2 + 1 && 1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->link == edge3 + 1 && span < 8 ) 2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); 2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->pos -= delta; 2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge3->link ) 2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->link->pos -= delta; 2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* move the serifs along with the stem */ 2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( n_edges == 12 ) 2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edges + 8 )->pos -= delta; 2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edges + 11 )->pos -= delta; 2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->flags |= AF_EDGE_DONE; 2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge3->link ) 2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->link->flags |= AF_EDGE_DONE; 2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !skipped ) 2020ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease goto Exit; 2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * now hint the remaining edges (serifs and single) in order 2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * to complete our processing 2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->flags & AF_EDGE_DONE ) 2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->serif ) 2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( hints, edge->serif, edge ); 2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_DONE; 2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project skipped--; 2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !skipped ) 2040ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease goto Exit; 2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge before, after; 2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->flags & AF_EDGE_DONE ) 2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = after = edge; 2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( --before >= edges ) 2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before->flags & AF_EDGE_DONE ) 2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( ++after < edge_limit ) 2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( after->flags & AF_EDGE_DONE ) 2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before >= edges || after < edge_limit ) 2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before < edges ) 2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( hints, after, edge ); 2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( after >= edge_limit ) 2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( hints, before, edge ); 2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 20670a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project { 20680a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project if ( after->fpos == before->fpos ) 20690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project edge->pos = before->pos; 20700a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project else 20710a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project edge->pos = before->pos + 20720a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project FT_MulDiv( edge->fpos - before->fpos, 20730a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project after->pos - before->pos, 20740a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project after->fpos - before->fpos ); 20750a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project } 2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2078ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2079ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease Exit: 2080ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2081ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE 2082ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease if ( !num_actions ) 2083ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( " (none)\n" )); 2084ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease FT_TRACE5(( "\n" )); 2085ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif 2086ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2087ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease return; 2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_edge_points( AF_GlyphHints hints, 2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = & hints->axis[dim]; 2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edges = axis->edges; 2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge_limit = edges + axis->num_edges; 2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool snapping; 2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project snapping = FT_BOOL( ( dim == AF_DIMENSION_HORZ && 2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) || 2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dim == AF_DIMENSION_VERT && 2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ); 2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* move the points of each segment */ 2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* in each edge to the edge's position */ 2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg = edge->first; 2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( snapping ) 2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point point = seg->first; 2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for (;;) 2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ ) 2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->x = edge->pos; 2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_X; 2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->y = edge->pos; 2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_Y; 2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point == seg->last ) 2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = point->next; 2138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta = edge->pos - edge->opos; 2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point point = seg->first; 2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for (;;) 2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ ) 2157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->x += delta; 2159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_X; 2160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->y += delta; 2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_Y; 2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point == seg->last ) 2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = point->next; 2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2181ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease /* Apply the complete hinting algorithm to a CJK glyph. */ 2182ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( FT_Error ) 2184aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_hints_apply( AF_GlyphHints hints, 2185aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner FT_Outline* outline, 2186aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner AF_CJKMetrics metrics ) 2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project int dim; 2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( metrics ); 2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2194aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich error = af_glyph_hints_reload( hints, outline ); 2195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* analyze glyph outline */ 2199fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#ifdef AF_CONFIG_OPTION_USE_WARPER 2200fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki if ( ( metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && 2201fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki AF_HINTS_DO_WARP( hints ) ) || 2202fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki AF_HINTS_DO_HORIZONTAL( hints ) ) 2203fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#else 2204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( AF_HINTS_DO_HORIZONTAL( hints ) ) 2205fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#endif 2206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ ); 2208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2210aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 2211aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_HORZ ); 2212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( AF_HINTS_DO_VERTICAL( hints ) ) 2215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT ); 2217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2219aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner 2220aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_VERT ); 2221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* grid-fit the outline */ 2224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) 2225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || 2227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) 2228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2230aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER 2231fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki if ( dim == AF_DIMENSION_HORZ && 2232fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki metrics->root.scaler.render_mode == FT_RENDER_MODE_LIGHT && 2233fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki AF_HINTS_DO_WARP( hints ) ) 2234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_WarperRec warper; 2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale; 2237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta; 2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2240aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_warper_compute( &warper, hints, (AF_Dimension)dim, 2241aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner &scale, &delta ); 2242aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner af_glyph_hints_scale_dim( hints, (AF_Dimension)dim, 2243aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner scale, delta ); 2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2246aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner#endif /* AF_CONFIG_OPTION_USE_WARPER */ 2247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hint_edges( hints, (AF_Dimension)dim ); 2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_edge_points( hints, (AF_Dimension)dim ); 2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); 2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); 2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_save( hints, outline ); 2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K S C R I P T C L A S S *****/ 2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2271ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_DEFINE_WRITING_SYSTEM_CLASS( 2272ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease af_cjk_writing_system_class, 2273ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2274ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_WRITING_SYSTEM_CJK, 2275ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2276ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease sizeof ( AF_CJKMetricsRec ), 2277ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 22789c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_InitMetricsFunc) af_cjk_metrics_init, 22799c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_ScaleMetricsFunc)af_cjk_metrics_scale, 22809c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_DoneMetricsFunc) NULL, 2281ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 22829c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_InitHintsFunc) af_cjk_hints_init, 22839c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_ApplyHintsFunc) af_cjk_hints_apply 2284ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease ) 2285ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2286ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2287ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#else /* !AF_CONFIG_OPTION_CJK */ 2288ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 22899c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod 2290ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_DEFINE_WRITING_SYSTEM_CLASS( 2291ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease af_cjk_writing_system_class, 2292ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease 2293ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease AF_WRITING_SYSTEM_CJK, 2294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 229541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier sizeof ( AF_CJKMetricsRec ), 2296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 22979c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_InitMetricsFunc) NULL, 22989c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_ScaleMetricsFunc)NULL, 22999c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_DoneMetricsFunc) NULL, 2300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 23019c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_InitHintsFunc) NULL, 23029c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod (AF_WritingSystem_ApplyHintsFunc) NULL 2303295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner ) 2304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2306ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif /* !AF_CONFIG_OPTION_CJK */ 2307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */ 2310