1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/ 2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* afcjk.c */ 4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* Auto-fitter hinting routines for CJK script (body). */ 6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* */ 7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* Copyright 2006-2013 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 25c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#include <ft2build.h> 26c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#include FT_ADVANCES_H 27c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#include FT_INTERNAL_DEBUG_H 28c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aftypes.h" 30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aflatin.h" 31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef AF_CONFIG_OPTION_CJK 34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 35c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#undef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT 36c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afcjk.h" 38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "aferrors.h" 39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 41c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER 42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "afwarp.h" 43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 47c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* */ 48c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 49c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 50c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* messages during execution. */ 51c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* */ 52c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#undef FT_COMPONENT 53c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#define FT_COMPONENT trace_afcjk 54c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 55c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 56c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /*************************************************************************/ 57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K G L O B A L M E T R I C S *****/ 60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 64c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 65c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Basically the Latin version with AF_CJKMetrics */ 66c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* to replace AF_LatinMetrics. */ 67c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 68c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_LOCAL_DEF( void ) 69c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_init_widths( AF_CJKMetrics metrics, 70a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Face face ) 71c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 72c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* scan the array of segments in each direction */ 73c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_GlyphHintsRec hints[1]; 74c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 75c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 76c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_glyph_hints_init( hints, face->memory ); 77c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 78c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner metrics->axis[AF_DIMENSION_HORZ].width_count = 0; 79c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner metrics->axis[AF_DIMENSION_VERT].width_count = 0; 80c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 81c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 82c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Error error; 83c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt glyph_index; 84c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner int dim; 85c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKMetricsRec dummy[1]; 86c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Scaler scaler = &dummy->root.scaler; 87c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 88c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 89a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang glyph_index = FT_Get_Char_Index( face, 90a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang metrics->root.clazz->standard_char ); 91c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( glyph_index == 0 ) 92c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 93c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 94c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); 95c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error || face->glyph->outline.n_points <= 0 ) 96c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 97c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 98c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_ZERO( dummy ); 99c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 100c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dummy->units_per_em = metrics->units_per_em; 101c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 102c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scaler->x_scale = 0x10000L; 103c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scaler->y_scale = 0x10000L; 104c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scaler->x_delta = 0; 105c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scaler->y_delta = 0; 106c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 107c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scaler->face = face; 108c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scaler->render_mode = FT_RENDER_MODE_NORMAL; 109c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scaler->flags = 0; 110c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 111c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_glyph_hints_rescale( hints, (AF_ScriptMetrics)dummy ); 112c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 113c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = af_glyph_hints_reload( hints, &face->glyph->outline ); 114c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 115c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 116c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 117c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) 118c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 119c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKAxis axis = &metrics->axis[dim]; 120c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_AxisHints axhints = &hints->axis[dim]; 121c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Segment seg, limit, link; 122c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt num_widths = 0; 123c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 124c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 125c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = af_latin_hints_compute_segments( hints, (AF_Dimension)dim ); 126c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error ) 127c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner goto Exit; 128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 129c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_latin_hints_link_segments( hints, (AF_Dimension)dim ); 130c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 131c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner seg = axhints->segments; 132c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner limit = seg + axhints->num_segments; 133c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 134c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( ; seg < limit; seg++ ) 135c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 136c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner link = seg->link; 137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 138c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* we only consider stem segments there! */ 139c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( link && link->link == seg && link > seg ) 140c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 141c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos dist; 142c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 143c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 144c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dist = seg->pos - link->pos; 145c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( dist < 0 ) 146c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dist = -dist; 147c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 148c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( num_widths < AF_CJK_MAX_WIDTHS ) 149c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->widths[num_widths++].org = dist; 150c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 151c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 152c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 153a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* this also replaces multiple almost identical stem widths */ 154a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang /* with a single one (the value 100 is heuristic) */ 155a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang af_sort_and_quantize_widths( &num_widths, axis->widths, 156a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang dummy->units_per_em / 100 ); 157c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->width_count = num_widths; 158c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 159c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 160c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner Exit: 161c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) 162c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 163c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKAxis axis = &metrics->axis[dim]; 164c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos stdw; 165c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 166c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 167c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner stdw = ( axis->width_count > 0 ) ? axis->widths[0].org 168c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner : AF_LATIN_CONSTANT( metrics, 50 ); 169c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 170c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* let's try 20% of the smallest width */ 171c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->edge_distance_threshold = stdw / 5; 172c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->standard_width = stdw; 173c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->extra_light = 0; 174c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 175c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 176c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 177c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_glyph_hints_done( hints ); 178c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 179c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 180c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 181c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#define AF_CJK_MAX_TEST_CHARACTERS 32 182c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 183c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 184c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Each blue zone has two types of fill and unfill, this is, */ 185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* filling the entire glyph square or not. */ 186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 187c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner enum 188c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 189c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJK_BLUE_TYPE_FILL, 190c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJK_BLUE_TYPE_UNFILL, 191c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJK_BLUE_TYPE_MAX 192c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }; 193c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 194c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 195c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Put some common and representative Han Ideographs characters here. */ 196c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner static const FT_ULong af_cjk_hani_blue_chars[AF_CJK_BLUE_MAX] 197c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner [AF_CJK_BLUE_TYPE_MAX] 198c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner [AF_CJK_MAX_TEST_CHARACTERS] = 199c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 200c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 201c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 202c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x4ED6, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730, 203c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x5BF9, 0x5C0D, 0x5C31, 0x5E2D, 0x6211, 0x65F6, 0x6642, 0x6703, 204c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x6765, 0x70BA, 0x80FD, 0x8230, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019, 205c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x9F4A /* top fill */ 206c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }, 207c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 208c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x519B, 0x540C, 0x5DF2, 0x613F, 0x65E2, 0x661F, 0x662F, 0x666F, 209c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x6C11, 0x7167, 0x73B0, 0x73FE, 0x7406, 0x7528, 0x7F6E, 0x8981, 210c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x8ECD, 0x90A3, 0x914D, 0x91CC, 0x958B, 0x96F7, 0x9732, 0x9762, 211c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x987E /* top unfill */ 212c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 213c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }, 214c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 215c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 216c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x4E2A, 0x4E3A, 0x4EBA, 0x4ED6, 0x4EE5, 0x4EEC, 0x4F60, 0x4F86, 217c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x500B, 0x5011, 0x5230, 0x548C, 0x5927, 0x5BF9, 0x5C0D, 0x5C31, 218c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x6211, 0x65F6, 0x6642, 0x6709, 0x6765, 0x70BA, 0x8981, 0x8AAA, 219c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x8BF4 /* bottom fill */ 220c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }, 221c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 222c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x4E3B, 0x4E9B, 0x56E0, 0x5B83, 0x60F3, 0x610F, 0x7406, 0x751F, 223c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x7576, 0x770B, 0x7740, 0x7F6E, 0x8005, 0x81EA, 0x8457, 0x88E1, 224c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x8FC7, 0x8FD8, 0x8FDB, 0x9032, 0x904E, 0x9053, 0x9084, 0x91CC, 225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x9762 /* bottom unfill */ 226c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }, 228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#ifndef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT 229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { {0x0000}, {0x0000} }, 230c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { {0x0000}, {0x0000} } 231c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#else 232c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 233c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 234c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x4E9B, 0x4EEC, 0x4F60, 0x4F86, 0x5011, 0x5230, 0x548C, 0x5730, 235c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x5979, 0x5C06, 0x5C07, 0x5C31, 0x5E74, 0x5F97, 0x60C5, 0x6700, 236c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x6837, 0x6A23, 0x7406, 0x80FD, 0x8AAA, 0x8BF4, 0x8FD9, 0x9019, 237c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x901A /* left fill */ 238c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }, 239c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 240c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x5373, 0x5417, 0x5427, 0x542C, 0x5462, 0x54C1, 0x54CD, 0x55CE, 241c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x5E08, 0x5E2B, 0x6536, 0x65AD, 0x65B7, 0x660E, 0x773C, 0x9593, 242c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x95F4, 0x9645, 0x9648, 0x9650, 0x9664, 0x9673, 0x968F, 0x969B, 243c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x96A8 /* left unfill */ 244c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }, 246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 248c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x4E8B, 0x524D, 0x5B78, 0x5C06, 0x5C07, 0x60C5, 0x60F3, 0x6216, 249c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x653F, 0x65AF, 0x65B0, 0x6837, 0x6A23, 0x6C11, 0x6C92, 0x6CA1, 250c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x7136, 0x7279, 0x73B0, 0x73FE, 0x7403, 0x7B2C, 0x7D93, 0x8C01, 251c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x8D77 /* right fill */ 252c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }, 253c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 254c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x4F8B, 0x5225, 0x522B, 0x5236, 0x52A8, 0x52D5, 0x5417, 0x55CE, 255c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x589E, 0x6307, 0x660E, 0x671D, 0x671F, 0x6784, 0x7269, 0x786E, 256c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x79CD, 0x8ABF, 0x8C03, 0x8CBB, 0x8D39, 0x90A3, 0x90FD, 0x9593, 257c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 0x95F4 /* right unfill */ 258c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 259c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 260c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */ 261c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }; 262c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 263c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 264c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Calculate blue zones for all the CJK_BLUE_XXX's. */ 265c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 266c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner static void 267c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_init_blues( AF_CJKMetrics metrics, 268c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Face face, 269c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner const FT_ULong blue_chars 270c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner [AF_CJK_BLUE_MAX] 271c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner [AF_CJK_BLUE_TYPE_MAX] 272c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner [AF_CJK_MAX_TEST_CHARACTERS] ) 273c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 274c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos fills[AF_CJK_MAX_TEST_CHARACTERS]; 275c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos flats[AF_CJK_MAX_TEST_CHARACTERS]; 276c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 277c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int num_fills; 278c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int num_flats; 279c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 280c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int bb; 281c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKBlue blue; 282c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Error error; 283c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKAxis axis; 284c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_GlyphSlot glyph = face->glyph; 285c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 286c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#ifdef FT_DEBUG_LEVEL_TRACE 287c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_String* cjk_blue_name[AF_CJK_BLUE_MAX] = { 288c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_String*)"top", 289c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_String*)"bottom", 290c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_String*)"left", 291c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_String*)"right" 292c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }; 293c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_String* cjk_blue_type_name[AF_CJK_BLUE_TYPE_MAX] = { 294c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_String*)"filled", 295c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner (FT_String*)"unfilled" 296c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner }; 297c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#endif 298c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 299c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 300c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* We compute the blues simply by loading each character from the */ 301c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* `blue_chars[blues]' string, then computing its extreme points */ 302c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* (depending blue zone type etc.). */ 303c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 304c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "cjk blue zones computation\n" )); 305c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "------------------------------------------------\n" )); 306c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 307c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( bb = 0; bb < AF_CJK_BLUE_MAX; bb++ ) 308c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 309c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int fill_type; 310c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos* blue_ref; 311c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos* blue_shoot; 312c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 313c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 314c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner num_fills = 0; 315c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner num_flats = 0; 316c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 317c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( fill_type = 0; fill_type < AF_CJK_BLUE_TYPE_MAX; fill_type++ ) 318c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 319c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner const FT_ULong* p = blue_chars[bb][fill_type]; 320c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner const FT_ULong* limit = p + AF_CJK_MAX_TEST_CHARACTERS; 321c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool fill = FT_BOOL( 322c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner fill_type == AF_CJK_BLUE_TYPE_FILL ); 323c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 324c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 325c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "cjk blue %s/%s\n", cjk_blue_name[bb], 326c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner cjk_blue_type_name[fill_type] )); 327c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 328c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 329c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( ; p < limit && *p; p++ ) 330c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 331c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt glyph_index; 332c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos best_pos; /* same as points.y */ 333c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int best_point; 334c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Vector* points; 335c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 336c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 337c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( " U+%lX...", *p )); 338c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 339c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* load the character in the face -- skip unknown or empty ones */ 340c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner glyph_index = FT_Get_Char_Index( face, *p ); 341c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( glyph_index == 0 ) 342c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 343c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "unavailable\n" )); 344c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 345c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 346c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 347c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE ); 348c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( error || glyph->outline.n_points <= 0 ) 349c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 350c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "no outline\n" )); 351c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 352c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 353c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 354c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* now compute min or max point indices and coordinates */ 355c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner points = glyph->outline.points; 356c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_point = -1; 357c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_pos = 0; /* make compiler happy */ 358c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 359c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 360c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int nn; 361c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int first = 0; 362c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int last = -1; 363c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 364c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 365c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( nn = 0; 366c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner nn < glyph->outline.n_contours; 367c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner first = last + 1, nn++ ) 368c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 369c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int pp; 370c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 371c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 372c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner last = glyph->outline.contours[nn]; 373c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 374c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Avoid single-point contours since they are never */ 375c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* rasterized. In some fonts, they correspond to mark */ 376c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* attachment points which are way outside of the glyph's */ 377c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* real outline. */ 378c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( last <= first ) 379c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 380c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 381c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner switch ( bb ) 382c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 383c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner case AF_CJK_BLUE_TOP: 384c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 385c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( best_point < 0 || points[pp].y > best_pos ) 386c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 387c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_point = pp; 388c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_pos = points[pp].y; 389c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 390c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner break; 391c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 392c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner case AF_CJK_BLUE_BOTTOM: 393c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 394c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( best_point < 0 || points[pp].y < best_pos ) 395c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 396c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_point = pp; 397c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_pos = points[pp].y; 398c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 399c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner break; 400c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 401c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner case AF_CJK_BLUE_LEFT: 402c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 403c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( best_point < 0 || points[pp].x < best_pos ) 404c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 405c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_point = pp; 406c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_pos = points[pp].x; 407c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 408c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner break; 409c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 410c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner case AF_CJK_BLUE_RIGHT: 411c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( pp = first; pp <= last; pp++ ) 412c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( best_point < 0 || points[pp].x > best_pos ) 413c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 414c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_point = pp; 415c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_pos = points[pp].x; 416c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 417c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner break; 418c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 419c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner default: 420c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ; 421c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 422c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 423c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "best_pos=%5ld\n", best_pos )); 424c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 425c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 426c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( fill ) 427c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner fills[num_fills++] = best_pos; 428c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 429c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner flats[num_flats++] = best_pos; 430c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 431c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 432c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 433c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( num_flats == 0 && num_fills == 0 ) 434c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 435c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* 436c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * we couldn't find a single glyph to compute this blue zone, 437c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * we will simply ignore it then 438c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner */ 439c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "empty\n" )); 440c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 441c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 442c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 443c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* we have computed the contents of the `fill' and `flats' tables, */ 444c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* now determine the reference position of the blue -- */ 445c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* we simply take the median value after a simple sort */ 446c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_sort_pos( num_flats, flats ); 447c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_sort_pos( num_fills, fills ); 448c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 449c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_BOTTOM == bb ) 450c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis = &metrics->axis[AF_DIMENSION_VERT]; 451c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 452c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis = &metrics->axis[AF_DIMENSION_HORZ]; 453c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 454c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue = & axis->blues[axis->blue_count]; 455c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue_ref = & blue->ref.org; 456c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue_shoot = & blue->shoot.org; 457c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 458c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->blue_count++; 459c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( num_flats == 0 ) 460c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 461c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *blue_ref = fills[num_fills / 2]; 462c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *blue_shoot = fills[num_fills / 2]; 463c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 464c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( num_fills == 0 ) 465c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 466c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *blue_ref = flats[num_flats / 2]; 467c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *blue_shoot = flats[num_flats / 2]; 468c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 469c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 470c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 471c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *blue_ref = fills[num_fills / 2]; 472c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *blue_shoot = flats[num_flats / 2]; 473c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 474c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 475c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* make sure blue_ref >= blue_shoot for top/right or */ 476c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* vice versa for bottom/left */ 477c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( *blue_shoot != *blue_ref ) 478c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 479c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos ref = *blue_ref; 480c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos shoot = *blue_shoot; 481c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool under_ref = FT_BOOL( shoot < ref ); 482c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 483c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 484a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang if ( ( AF_CJK_BLUE_TOP == bb || 485a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang AF_CJK_BLUE_RIGHT == bb ) ^ under_ref ) 486c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner *blue_shoot = *blue_ref = ( shoot + ref ) / 2; 487c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 488c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 489c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->flags = 0; 490c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( AF_CJK_BLUE_TOP == bb ) 491c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->flags |= AF_CJK_BLUE_IS_TOP; 492c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( AF_CJK_BLUE_RIGHT == bb ) 493c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->flags |= AF_CJK_BLUE_IS_RIGHT; 494c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 495c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "-- cjk %s bluezone ref = %ld shoot = %ld\n", 496c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner cjk_blue_name[bb], *blue_ref, *blue_shoot )); 497c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 498c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 499c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner return; 500c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 501c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 502c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 503c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Basically the Latin version with type AF_CJKMetrics for metrics. */ 504c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_LOCAL_DEF( void ) 505c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_check_digits( AF_CJKMetrics metrics, 506c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Face face ) 507c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 508c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt i; 509c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool started = 0, same_width = 1; 510c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed advance, old_advance = 0; 511c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 512c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 513c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* check whether all ASCII digits have the same advance width; */ 514c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* digit `0' is 0x30 in all supported charmaps */ 515c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( i = 0x30; i <= 0x39; i++ ) 516c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 517c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt glyph_index; 518c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 519c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 520c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner glyph_index = FT_Get_Char_Index( face, i ); 521c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( glyph_index == 0 ) 522c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 523c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 524c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( FT_Get_Advance( face, glyph_index, 525c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_LOAD_NO_SCALE | 526c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_LOAD_NO_HINTING | 527c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_LOAD_IGNORE_TRANSFORM, 528c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &advance ) ) 529c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 530c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 531c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( started ) 532c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 533c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( advance != old_advance ) 534c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 535c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner same_width = 0; 536c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner break; 537c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 538c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 539c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 540c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 541c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner old_advance = advance; 542c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner started = 1; 543c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 544c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 545c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 546c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner metrics->root.digits_have_same_width = same_width; 547c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 548c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 549c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( FT_Error ) 551c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_init( AF_CJKMetrics metrics, 552c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Face face ) 553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_CharMap oldmap = face->charmap; 555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project metrics->units_per_em = face->units_per_EM; 558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_Select_Charmap( face, FT_ENCODING_UNICODE ) ) 560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project face->charmap = NULL; 561295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner else 562295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner { 563a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang af_cjk_metrics_init_widths( metrics, face ); 564c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars ); 565c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_check_digits( metrics, face ); 566295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner } 567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Set_Charmap( face, oldmap ); 569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 570a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return FT_Err_Ok; 571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 575c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_scale_dim( AF_CJKMetrics metrics, 576c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Scaler scaler, 577c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Dimension dim ) 578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 579c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed scale; 580c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos delta; 581c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKAxis axis; 582c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt nn; 583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project axis = &metrics->axis[dim]; 586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ ) 588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 589c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scale = scaler->x_scale; 590c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta = scaler->x_delta; 591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 594c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scale = scaler->y_scale; 595c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta = scaler->y_delta; 596c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 597c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 598c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( axis->org_scale == scale && axis->org_delta == delta ) 599c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner return; 600c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 601c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->org_scale = scale; 602c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->org_delta = delta; 603c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 604c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->scale = scale; 605c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner axis->delta = delta; 606c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 607c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* scale the blue zones */ 608c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( nn = 0; nn < axis->blue_count; nn++ ) 609c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 610c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKBlue blue = &axis->blues[nn]; 611c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos dist; 612c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 613c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 614c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->ref.cur = FT_MulFix( blue->ref.org, scale ) + delta; 615c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->ref.fit = blue->ref.cur; 616c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta; 617c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->shoot.fit = blue->shoot.cur; 618c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->flags &= ~AF_CJK_BLUE_ACTIVE; 619c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 620c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* a blue zone is only active if it is less than 3/4 pixels tall */ 621c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale ); 622c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( dist <= 48 && dist >= -48 ) 623c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 624c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos delta1, delta2; 625c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 626c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 627c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->ref.fit = FT_PIX_ROUND( blue->ref.cur ); 628c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 629c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* shoot is under shoot for cjk */ 630c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta1 = FT_DivFix( blue->ref.fit, scale ) - blue->shoot.org; 631c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta2 = delta1; 632c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( delta1 < 0 ) 633c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta2 = -delta2; 634c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 635c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta2 = FT_MulFix( delta2, scale ); 636c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 637c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "delta: %d", delta1 )); 638c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( delta2 < 32 ) 639c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta2 = 0; 640c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#if 0 641c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( delta2 < 64 ) 642c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 ); 643c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#endif 644c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 645c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta2 = FT_PIX_ROUND( delta2 ); 646c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "/%d\n", delta2 )); 647c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 648c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( delta1 < 0 ) 649c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner delta2 = -delta2; 650c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 651c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->shoot.fit = blue->ref.fit - delta2; 652c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 653c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]: " 654c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner "ref: cur=%.2f fit=%.2f shoot: cur=%.2f fit=%.2f\n", 655c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V', 656c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner nn, blue->ref.org, blue->shoot.org, 657c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->ref.cur / 64.0, blue->ref.fit / 64.0, 658c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 )); 659c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 660c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue->flags |= AF_CJK_BLUE_ACTIVE; 661c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( void ) 667c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_metrics_scale( AF_CJKMetrics metrics, 668c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Scaler scaler ) 669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project metrics->root.scaler = *scaler; 671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ ); 673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT ); 674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K G L Y P H A N A L Y S I S *****/ 681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_compute_segments( AF_GlyphHints hints, 687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segments = axis->segments; 691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segment_limit = segments + axis->num_segments; 692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg; 694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_latin_hints_compute_segments( hints, dim ); 697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* a segment is round if it doesn't have successive */ 701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* on-curve points. */ 702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg = segments; seg < segment_limit; seg++ ) 703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point pt = seg->first; 705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point last = seg->last; 706a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang AF_Flags f0 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); 707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Flags f1; 708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->flags &= ~AF_EDGE_ROUND; 711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ; pt != last; f0 = f1 ) 713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project pt = pt->next; 715a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL ); 716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !f0 && !f1 ) 718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( pt == last ) 721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->flags |= AF_EDGE_ROUND; 722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 725a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang return FT_Err_Ok; 726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_link_segments( AF_GlyphHints hints, 731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segments = axis->segments; 735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segment_limit = segments + axis->num_segments; 736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Direction major_dir = axis->major_dir; 737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg1, seg2; 738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos len_threshold; 739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist_threshold; 740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 ); 743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist_threshold = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale 745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project : hints->y_scale; 746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist_threshold = FT_DivFix( 64 * 3, dist_threshold ); 747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now compare each segment to the others */ 749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg1 = segments; seg1 < segment_limit; seg1++ ) 750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the fake segments are for metrics hinting only */ 752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->first == seg1->last ) 753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->dir != major_dir ) 756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg2 = segments; seg2 < segment_limit; seg2++ ) 759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 ) 760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist = seg2->pos - seg1->pos; 762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos min = seg1->min_coord; 769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos max = seg1->max_coord; 770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos len; 771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( min < seg2->min_coord ) 774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project min = seg2->min_coord; 775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( max > seg2->max_coord ) 777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project max = seg2->max_coord; 778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project len = max - min; 780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( len >= len_threshold ) 781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist * 8 < seg1->score * 9 && 783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dist * 8 < seg1->score * 7 || seg1->len < len ) ) 784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->score = dist; 786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->len = len; 787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->link = seg2; 788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist * 8 < seg2->score * 9 && 791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dist * 8 < seg2->score * 7 || seg2->len < len ) ) 792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->score = dist; 794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->len = len; 795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->link = seg1; 796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * now compute the `serif' segments 804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * In Hanzi, some strokes are wider on one or both of the ends. 806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We either identify the stems on the ends as serifs or remove 807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * the linkage, depending on the length of the stems. 808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * 809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment link1, link2; 813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg1 = segments; seg1 < segment_limit; seg1++ ) 816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project link1 = seg1->link; 818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !link1 || link1->link != seg1 || link1->pos <= seg1->pos ) 819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->score >= dist_threshold ) 822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg2 = segments; seg2 < segment_limit; seg2++ ) 825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->pos > seg1->pos || seg1 == seg2 ) 827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project link2 = seg2->link; 830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !link2 || link2->link != seg2 || link2->pos < link1->pos ) 831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->pos == seg2->pos && link1->pos == link2->pos ) 834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->score <= seg1->score || seg1->score * 4 <= seg2->score ) 837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* seg2 < seg1 < link1 < link2 */ 840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg1->len >= seg2->len * 3 ) 842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg; 844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg = segments; seg < segment_limit; seg++ ) 847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment link = seg->link; 849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( link == seg2 ) 852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->link = 0; 854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->serif = link1; 855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( link == link2 ) 857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->link = 0; 859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->serif = seg1; 860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->link = link1->link = 0; 866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg1 = segments; seg1 < segment_limit; seg1++ ) 874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2 = seg1->link; 876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2 ) 878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->num_linked++; 880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->link != seg1 ) 881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->link = 0; 883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg2->score < dist_threshold || seg1->score < seg2->score * 4 ) 885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg1->serif = seg2->link; 886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2->num_linked--; 888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_compute_edges( AF_GlyphHints hints, 896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 899a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang FT_Error error = FT_Err_Ok; 900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Memory memory = hints->memory; 901c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim]; 902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segments = axis->segments; 904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment segment_limit = segments + axis->num_segments; 905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg; 906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale; 908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos edge_distance_threshold; 909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project axis->num_edges = 0; 912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale 914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project : hints->y_scale; 915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*********************************************************************/ 917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* We begin by generating a sorted table of edges for the current */ 919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* direction. To do so, we simply scan each segment and try to find */ 920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* an edge in our table that corresponds to its position. */ 921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* If no edge is found, we create and insert a new edge in the */ 923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* sorted table. Otherwise, we simply add the segment to the edge's */ 924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* list which is then processed in the second step to compute the */ 925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* edge's properties. */ 926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Note that the edges table is sorted along the segment/edge */ 928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* position. */ 929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*********************************************************************/ 931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold, 933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scale ); 934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge_distance_threshold > 64 / 4 ) 935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_distance_threshold = FT_DivFix( 64 / 4, scale ); 936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_distance_threshold = laxis->edge_distance_threshold; 938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( seg = segments; seg < segment_limit; seg++ ) 940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge found = 0; 942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos best = 0xFFFFU; 943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int ee; 944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* look for an edge corresponding to the segment */ 947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( ee = 0; ee < axis->num_edges; ee++ ) 948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge = axis->edges + ee; 950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist; 951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->dir != seg->dir ) 954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = seg->pos - edge->fpos; 957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -dist; 959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < edge_distance_threshold && dist < best ) 961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment link = seg->link; 963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check whether all linked segments of the candidate edge */ 966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* can make a single edge. */ 967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( link ) 968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 969a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang AF_Segment seg1 = edge->first; 970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist2 = 0; 971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 975a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang AF_Segment link1 = seg1->link; 976a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 977a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( link1 ) 979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist2 = AF_SEGMENT_DIST( link, link1 ); 981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist2 >= edge_distance_threshold ) 982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( ( seg1 = seg1->edge_next ) != edge->first ); 986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist2 >= edge_distance_threshold ) 988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project best = dist; 992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project found = edge; 993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !found ) 997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* insert a new edge in the list and */ 1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* sort according to the position */ 1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_axis_hints_new_edge( axis, seg->pos, 1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Direction)seg->dir, 1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project memory, &edge ); 1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* add the segment to the new edge's list */ 1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_ZERO( edge ); 1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->first = seg; 1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->last = seg; 1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->fpos = seg->pos; 1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->opos = edge->pos = FT_MulFix( seg->pos, scale ); 1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->edge_next = seg; 1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->dir = seg->dir; 1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* if an edge was found, simply add the segment to the edge's */ 1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* list */ 1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->edge_next = found->first; 1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project found->last->edge_next = seg; 1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project found->last = seg; 1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*********************************************************************/ 1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Good, we now compute each edge's properties according to segments */ 1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* found on its position. Basically, these are as follows. */ 1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* - edge's main direction */ 1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* - stem edge, serif edge or both (which defaults to stem then) */ 1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* - rounded edge, straight or both (which defaults to straight) */ 1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* - link for edge */ 1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*********************************************************************/ 1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* first of all, set the `edge' field in each segment -- this is */ 1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* required in order to compute edge links */ 1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* */ 1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Note that removing this loop and setting the `edge' field of each */ 1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* segment directly in the code above slows down execution speed for */ 1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* some reasons on platforms like the Sun. */ 1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edges = axis->edges; 1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge_limit = edges + axis->num_edges; 1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = edge->first; 1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg ) 1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg->edge = edge; 1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now compute each edge properties */ 1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int is_round = 0; /* does it contain round segments? */ 1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int is_straight = 0; /* does it contain straight segments? */ 1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = edge->first; 1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 1076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool is_serif; 1078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check for roundness of segment */ 1081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg->flags & AF_EDGE_ROUND ) 1082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project is_round++; 1083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project is_straight++; 1085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* check for links -- if seg->serif is set, then seg->link must */ 1087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* be ignored */ 1088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge ); 1089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg->link || is_serif ) 1091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge2; 1093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg2; 1094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edge->link; 1097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2 = seg->link; 1098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( is_serif ) 1100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg2 = seg->serif; 1102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edge->serif; 1103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge2 ) 1106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos edge_delta; 1108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos seg_delta; 1109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_delta = edge->fpos - edge2->fpos; 1112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge_delta < 0 ) 1113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge_delta = -edge_delta; 1114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg_delta = AF_SEGMENT_DIST( seg, seg2 ); 1116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( seg_delta < edge_delta ) 1118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = seg2->edge; 1119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = seg2->edge; 1122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( is_serif ) 1124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->serif = edge2; 1126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->flags |= AF_EDGE_SERIF; 1127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->link = edge2; 1130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 1133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 1135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* set the round/straight flags */ 1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags = AF_EDGE_NORMAL; 1138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( is_round > 0 && is_round >= is_straight ) 1140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_ROUND; 1141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* get rid of serifs if link is set */ 1143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* XXX: This gets rid of many unpleasant artefacts! */ 1144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* Example: the `c' in cour.pfa at size 13 */ 1145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->serif && edge->link ) 1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->serif = 0; 1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Error 1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_detect_features( AF_GlyphHints hints, 1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_compute_segments( hints, dim ); 1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !error ) 1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hints_link_segments( hints, dim ); 1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_compute_edges( hints, dim ); 1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1174c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_LOCAL_DEF( void ) 1175c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_hints_compute_blue_edges( AF_GlyphHints hints, 1176c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKMetrics metrics, 1177c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Dimension dim ) 1178c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1179c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_AxisHints axis = &hints->axis[dim]; 1180c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Edge edge = axis->edges; 1181c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Edge edge_limit = edge + axis->num_edges; 1182c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKAxis cjk = &metrics->axis[dim]; 1183c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Fixed scale = cjk->scale; 1184c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos best_dist0; /* initial threshold */ 1185c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1186c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1187c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute the initial threshold as a fraction of the EM size */ 1188c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale ); 1189c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1190c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( best_dist0 > 64 / 2 ) /* maximum 1/2 pixel */ 1191c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_dist0 = 64 / 2; 1192c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1193c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* compute which blue zones are active, i.e. have their scaled */ 1194c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* size < 3/4 pixels */ 1195c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1196c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* If the distant between an edge and a blue zone is shorter than */ 1197c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* best_dist0, set the blue zone for the edge. Then search for */ 1198c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* the blue zone with the smallest best_dist to the edge. */ 1199c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1200c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( ; edge < edge_limit; edge++ ) 1201c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1202c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_UInt bb; 1203c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Width best_blue = NULL; 1204c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos best_dist = best_dist0; 1205c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1206c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1207c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( bb = 0; bb < cjk->blue_count; bb++ ) 1208c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1209c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKBlue blue = cjk->blues + bb; 1210c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool is_top_right_blue, is_major_dir; 1211c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1212c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1213c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* skip inactive blue zones (i.e., those that are too small) */ 1214c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !( blue->flags & AF_CJK_BLUE_ACTIVE ) ) 1215c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1216c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1217c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if it is a top zone, check for right edges -- if it is a bottom */ 1218c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* zone, check for left edges */ 1219c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* */ 1220c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* of course, that's for TrueType */ 1221c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner is_top_right_blue = 1222c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_BOOL( ( ( blue->flags & AF_CJK_BLUE_IS_TOP ) != 0 ) || 1223c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ( ( blue->flags & AF_CJK_BLUE_IS_RIGHT ) != 0 ) ); 1224c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner is_major_dir = FT_BOOL( edge->dir == axis->major_dir ); 1225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1226c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* if it is a top zone, the edge must be against the major */ 1227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* direction; if it is a bottom zone, it must be in the major */ 1228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* direction */ 1229c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( is_top_right_blue ^ is_major_dir ) 1230c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1231c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos dist; 1232c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Width compare; 1233c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1234c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1235c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Compare the edge to the closest blue zone type */ 1236c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( FT_ABS( edge->fpos - blue->ref.org ) > 1237c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_ABS( edge->fpos - blue->shoot.org ) ) 1238c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner compare = &blue->shoot; 1239c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else 1240c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner compare = &blue->ref; 1241c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1242c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dist = edge->fpos - compare->org; 1243c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( dist < 0 ) 1244c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dist = -dist; 1245c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1246c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dist = FT_MulFix( dist, scale ); 1247c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( dist < best_dist ) 1248c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1249c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_dist = dist; 1250c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner best_blue = compare; 1251c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1252c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1253c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1254c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1255c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( best_blue ) 1256c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge->blue_edge = best_blue; 1257c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1258c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1259c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1260c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( FT_Error ) 1262c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_hints_init( AF_GlyphHints hints, 1263c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKMetrics metrics ) 1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Render_Mode mode; 1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UInt32 scaler_flags, other_flags; 1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_rescale( hints, (AF_ScriptMetrics)metrics ); 1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * correct x_scale and y_scale when needed, since they may have 1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * been modified af_cjk_scale_dim above 1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale; 1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta; 1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale; 1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta; 1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute flags depending on render mode, etc. */ 1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project mode = metrics->root.scaler.render_mode; 1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1283c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER 1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V ) 1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL; 1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scaler_flags = hints->scaler_flags; 1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags = 0; 1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We snap the width of vertical stems for the monochrome and 1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * horizontal LCD rendering targets only. 1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD ) 1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_HORZ_SNAP; 1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We snap the width of horizontal stems for the monochrome and 1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * vertical LCD rendering targets only. 1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V ) 1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_VERT_SNAP; 1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * We adjust stems to full pixels only if we don't use the `light' mode. 1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode != FT_RENDER_MODE_LIGHT ) 1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_STEM_ADJUST; 1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( mode == FT_RENDER_MODE_MONO ) 1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project other_flags |= AF_LATIN_HINTS_MONO; 1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE; 1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->scaler_flags = scaler_flags; 1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints->other_flags = other_flags; 1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return 0; 1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K G L Y P H G R I D - F I T T I N G *****/ 1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* snap a given width in scaled coordinates to one of the */ 1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* current standard widths */ 1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_snap_width( AF_Width widths, 1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int count, 1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos width ) 1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project int n; 1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos best = 64 + 32 + 2; 1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos reference = width; 1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos scaled; 1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( n = 0; n < count; n++ ) 1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos w; 1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist; 1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project w = widths[n].cur; 1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = width - w; 1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -dist; 1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < best ) 1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project best = dist; 1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project reference = w; 1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project scaled = FT_PIX_ROUND( reference ); 1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( width >= reference ) 1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( width < scaled + 48 ) 1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project width = reference; 1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( width > scaled - 48 ) 1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project width = reference; 1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return width; 1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* compute the snapped width of a given stem */ 1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_compute_stem_width( AF_GlyphHints hints, 1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim, 1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos width, 1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge_Flags base_flags, 1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge_Flags stem_flags ) 1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1388c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKMetrics metrics = (AF_CJKMetrics) hints->metrics; 1389c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKAxis axis = & metrics->axis[dim]; 1390c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos dist = width; 1391c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Int sign = 0; 1392c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool vertical = FT_BOOL( dim == AF_DIMENSION_VERT ); 1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( base_flags ); 1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( stem_flags ); 1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ) 1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return width; 1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 0 ) 1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -width; 1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project sign = 1; 1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) || 1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) ) 1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* smooth hinting process: very lightly quantize the stem width */ 1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( axis->width_count > 0 ) 1413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( dist - axis->widths[0].cur ) < 40 ) 1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = axis->widths[0].cur; 1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 48 ) 1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = 48; 1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Done_Width; 1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 54 ) 1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += ( 54 - dist ) / 2 ; 1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( dist < 3 * 64 ) 1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta; 1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = dist & 63; 1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist &= -64; 1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta < 10 ) 1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += delta; 1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 22 ) 1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += 10; 1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 42 ) 1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += delta; 1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < 54 ) 1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += 54; 1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist += delta; 1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* strong hinting process: snap the stem width to integer pixels */ 1449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = af_cjk_snap_width( axis->widths, axis->width_count, dist ); 1451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( vertical ) 1453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* in the case of vertical hinting, always round */ 1455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the stem heights to integer pixels */ 1456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist >= 64 ) 1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 16 ) & ~63; 1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = 64; 1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( AF_LATIN_HINTS_DO_MONO( hints ) ) 1465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* monochrome horizontal hinting: snap widths to integer pixels */ 1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* with a different threshold */ 1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 64 ) 1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = 64; 1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 32 ) & ~63; 1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* for horizontal anti-aliased hinting, we adopt a more subtle */ 1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* approach: we strengthen small stems, round stems whose size */ 1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* is between 1 and 2 pixels to an integer, otherwise nothing */ 1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dist < 48 ) 1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 64 ) >> 1; 1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( dist < 128 ) 1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 22 ) & ~63; 1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* round otherwise to prevent color fringes in LCD mode */ 1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = ( dist + 32 ) & ~63; 1488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Done_Width: 1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( sign ) 1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist = -dist; 1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return dist; 1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* align one stem edge relative to the previous stem edge */ 1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_linked_edge( AF_GlyphHints hints, 1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim, 1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge base_edge, 1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge stem_edge ) 1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist = stem_edge->opos - base_edge->opos; 1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos fitted_width = af_cjk_compute_stem_width( 1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project hints, dim, dist, 1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Edge_Flags)base_edge->flags, 1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Edge_Flags)stem_edge->flags ); 1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project stem_edge->pos = base_edge->pos + fitted_width; 1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( AF_GlyphHints hints, 1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge base, 1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge serif ) 1524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( hints ); 1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project serif->pos = base->pos + ( serif->opos - base->opos ); 1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /**** ****/ 1535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /**** E D G E H I N T I N G ****/ 1536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /**** ****/ 1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LIGHT_MODE_MAX_HORZ_GAP 9 1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LIGHT_MODE_MAX_VERT_GAP 15 1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define AF_LIGHT_MODE_MAX_DELTA_ABS 14 1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static FT_Pos 1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( AF_GlyphHints hints, 1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge, 1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge2, 1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos anchor, 1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 1553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos org_len, cur_len, org_center; 1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos cur_pos1, cur_pos2; 1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos d_off1, u_off1, d_off2, u_off2, delta; 1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos offset; 1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos threshold = 64; 1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ) 1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( edge->flags & AF_EDGE_ROUND ) && 1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edge2->flags & AF_EDGE_ROUND ) ) 1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_VERT ) 1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP; 1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP; 1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_VERT ) 1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_HORZ_GAP / 3; 1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project threshold = 64 - AF_LIGHT_MODE_MAX_VERT_GAP / 3; 1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_len = edge2->opos - edge->opos; 1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_len = af_cjk_compute_stem_width( hints, dim, org_len, 1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Edge_Flags)edge->flags, 1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Edge_Flags)edge2->flags ); 1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project org_center = ( edge->opos + edge2->opos ) / 2 + anchor; 1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_pos1 = org_center - cur_len / 2; 1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_pos2 = cur_pos1 + cur_len; 1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off1 = cur_pos1 - FT_PIX_FLOOR( cur_pos1 ); 1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off2 = cur_pos2 - FT_PIX_FLOOR( cur_pos2 ); 1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off1 = 64 - d_off1; 1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off2 = 64 - d_off2; 1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = 0; 1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off1 == 0 || d_off2 == 0 ) 1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( cur_len <= threshold ) 1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off2 < cur_len ) 1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( u_off1 <= d_off2 ) 1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = u_off1; 1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = -d_off2; 1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( threshold < 64 ) 1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off1 >= threshold || u_off1 >= threshold || 1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off2 >= threshold || u_off2 >= threshold ) 1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1618e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang offset = cur_len & 63; 1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( offset < 32 ) 1621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( u_off1 <= offset || d_off2 <= offset ) 1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project offset = 64 - threshold; 1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off1 = threshold - u_off1; 1629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off1 = u_off1 - offset; 1630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off2 = threshold - d_off2; 1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d_off2 = d_off2 - offset; 1632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off1 <= u_off1 ) 1634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off1 = -d_off1; 1635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( d_off2 <= u_off2 ) 1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project u_off2 = -d_off2; 1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( u_off1 ) <= FT_ABS( u_off2 ) ) 1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = u_off1; 1641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = u_off2; 1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 1 1647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ) 1648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta > AF_LIGHT_MODE_MAX_DELTA_ABS ) 1650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = AF_LIGHT_MODE_MAX_DELTA_ABS; 1651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( delta < -AF_LIGHT_MODE_MAX_DELTA_ABS ) 1652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = -AF_LIGHT_MODE_MAX_DELTA_ABS; 1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project cur_pos1 += delta; 1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->opos < edge2->opos ) 1659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->pos = cur_pos1; 1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->pos = cur_pos1 + cur_len; 1662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->pos = cur_pos1 + cur_len; 1666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->pos = cur_pos1; 1667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return delta; 1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hint_edges( AF_GlyphHints hints, 1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = &hints->axis[dim]; 1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edges = axis->edges; 1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge_limit = edges + axis->num_edges; 1680295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner FT_PtrDist n_edges; 1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge anchor = 0; 1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta = 0; 1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Int skipped = 0; 1685c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Bool has_last_stem = FALSE; 1686c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Pos last_stem_pos = 0; 1687c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1689c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* we begin by aligning all stems relative to the blue zone */ 1690c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "==== cjk hinting %s edges =====\n", 1691c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" )); 1692c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1693c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( AF_HINTS_DO_BLUES( hints ) ) 1694c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1695c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner for ( edge = edges; edge < edge_limit; edge++ ) 1696c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1697c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Width blue; 1698c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_Edge edge1, edge2; 1699c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1700c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1701c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( edge->flags & AF_EDGE_DONE ) 1702c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1703c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1704c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue = edge->blue_edge; 1705c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge1 = NULL; 1706c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge2 = edge->link; 1707c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1708c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( blue ) 1709c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1710c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge1 = edge; 1711c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1712c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner else if ( edge2 && edge2->blue_edge ) 1713c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1714c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner blue = edge2->blue_edge; 1715c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge1 = edge2; 1716c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge2 = edge; 1717c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1718c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1719c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !edge1 ) 1720c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1721c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1722c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "CJKBLUE: edge %d @%d (opos=%.2f) snapped to (%.2f), " 1723c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner "was (%.2f)\n", 1724c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge1-edges, edge1->fpos, edge1->opos / 64.0, blue->fit / 64.0, 1725c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge1->pos / 64.0 )); 1726c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1727c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge1->pos = blue->fit; 1728c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge1->flags |= AF_EDGE_DONE; 1729c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1730c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( edge2 && !edge2->blue_edge ) 1731c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1732c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_align_linked_edge( hints, dim, edge1, edge2 ); 1733c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge2->flags |= AF_EDGE_DONE; 1734c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1735c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1736c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( !anchor ) 1737c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner anchor = edge; 1738c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1739c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now we align all stem edges. */ 1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge2; 1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->flags & AF_EDGE_DONE ) 1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* skip all non-stem edges */ 1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edge->link; 1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !edge2 ) 1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project skipped++; 1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1758c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* Some CJK characters have so many stems that 1759c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * the hinter is likely to merge two adjacent ones. 1760c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * To solve this problem, if either edge of a stem 1761c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * is too close to the previous one, we avoid 1762c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * aligning the two edges, but rather interpolate 1763c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * their locations at the end of this function in 1764c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * order to preserve the space between the stems. 1765c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner */ 1766c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( has_last_stem && 1767c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner ( edge->pos < last_stem_pos + 64 || 1768c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge2->pos < last_stem_pos + 64 ) ) 1769c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1770c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner skipped++; 1771c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1772c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1773c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* now align the stem */ 1775c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* this should not happen, but it's better to be safe */ 1776c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner if ( edge2->blue_edge ) 1777c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner { 1778c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges )); 1779c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 1780c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_align_linked_edge( hints, dim, edge2, edge ); 1781c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner edge->flags |= AF_EDGE_DONE; 1782c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner continue; 1783c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner } 1784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge2 < edge ) 1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_linked_edge( hints, dim, edge2, edge ); 1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_DONE; 1789c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* We rarely reaches here it seems; 1790c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * usually the two edges belonging 1791c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner * to one stem are marked as DONE together 1792c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner */ 1793c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner has_last_stem = TRUE; 1794c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner last_stem_pos = edge->pos; 1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim != AF_DIMENSION_VERT && !anchor ) 1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0 1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( fixedpitch ) 1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge left = edge; 1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge right = edge_limit - 1; 1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_EdgeRec left1, left2, right1, right2; 1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos target, center1, center2; 1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta1, delta2, d1, d2; 1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( right > left && !right->link ) 1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right--; 1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left1 = *left; 1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left2 = *left->link; 1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right1 = *right->link; 1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right2 = *right; 1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = ( ( ( hinter->pp2.x + 32 ) & -64 ) - hinter->pp2.x ) / 2; 1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project target = left->opos + ( right->opos - left->opos ) / 2 + delta - 16; 1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1 = delta; 1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1 += af_hint_normal_stem( hints, left, left->link, 1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1, 0 ); 1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left->link != right ) 1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( hints, right->link, right, delta1, 0 ); 1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project center1 = left->pos + ( right->pos - left->pos ) / 2; 1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( center1 >= target ) 1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta2 = delta - 32; 1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta2 = delta + 32; 1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta2 += af_hint_normal_stem( hints, &left1, &left2, delta2, 0 ); 1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( delta1 != delta2 ) 1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left->link != right ) 1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( hints, &right1, &right2, delta2, 0 ); 1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project center2 = left1.pos + ( right2.pos - left1.pos ) / 2; 1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d1 = center1 - target; 1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project d2 = center2 - target; 1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( FT_ABS( d2 ) < FT_ABS( d1 ) ) 1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left->pos = left1.pos; 1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project left->link->pos = left2.pos; 1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( left->link != right ) 1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->link->pos = right1.pos; 1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->pos = right2.pos; 1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta1 = delta2; 1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = delta1; 1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->link->flags |= AF_EDGE_DONE; 1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project right->flags |= AF_EDGE_DONE; 1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* 0 */ 1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = af_hint_normal_stem( hints, edge, edge2, 0, 1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_DIMENSION_HORZ ); 1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_hint_normal_stem( hints, edge, edge2, delta, dim ); 1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0 1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project printf( "stem (%d,%d) adjusted (%.1f,%.1f)\n", 1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge - edges, edge2 - edges, 1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edge->pos - edge->opos ) / 64.0, 1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edge2->pos - edge2->opos ) / 64.0 ); 1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project anchor = edge; 1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_DONE; 1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->flags |= AF_EDGE_DONE; 1887c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner has_last_stem = TRUE; 1888c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner last_stem_pos = edge2->pos; 1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* make sure that lowercase m's maintain their symmetry */ 1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* In general, lowercase m's have six vertical edges if they are sans */ 1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* serif, or twelve if they are with serifs. This implementation is */ 1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* based on that assumption, and seems to work very well with most */ 1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* faces. However, if for a certain face this assumption is not */ 1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* true, the m is just rendered like before. In addition, any stem */ 1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* correction will only be applied to symmetrical glyphs (even if the */ 1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* glyph is not an m), so the potential for unwanted distortion is */ 1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* relatively low. */ 1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* We don't handle horizontal edges since we can't easily assure that */ 1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* the third (lowest) stem aligns with the base line; it might end up */ 1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* one pixel higher or lower. */ 1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project n_edges = edge_limit - edges; 1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) ) 1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge1, edge2, edge3; 1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos dist1, dist2, span; 1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( n_edges == 6 ) 1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge1 = edges; 1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edges + 2; 1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3 = edges + 4; 1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge1 = edges + 1; 1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2 = edges + 5; 1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3 = edges + 9; 1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist1 = edge2->opos - edge1->opos; 1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project dist2 = edge3->opos - edge2->opos; 1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project span = dist1 - dist2; 1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( span < 0 ) 1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project span = -span; 1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge1->link == edge1 + 1 && 1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge2->link == edge2 + 1 && 1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->link == edge3 + 1 && span < 8 ) 1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); 1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->pos -= delta; 1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge3->link ) 1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->link->pos -= delta; 1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* move the serifs along with the stem */ 1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( n_edges == 12 ) 1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edges + 8 )->pos -= delta; 1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( edges + 11 )->pos -= delta; 1947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->flags |= AF_EDGE_DONE; 1950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge3->link ) 1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge3->link->flags |= AF_EDGE_DONE; 1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !skipped ) 1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* 1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * now hint the remaining edges (serifs and single) in order 1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project * to complete our processing 1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project */ 1962049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->flags & AF_EDGE_DONE ) 1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->serif ) 1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( hints, edge->serif, edge ); 1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project edge->flags |= AF_EDGE_DONE; 1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project skipped--; 1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( !skipped ) 1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return; 1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge before, after; 1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( edge->flags & AF_EDGE_DONE ) 1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project before = after = edge; 1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( --before >= edges ) 1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before->flags & AF_EDGE_DONE ) 1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project while ( ++after < edge_limit ) 1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( after->flags & AF_EDGE_DONE ) 1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before >= edges || after < edge_limit ) 1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( before < edges ) 1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( hints, after, edge ); 2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else if ( after >= edge_limit ) 2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_serif_edge( hints, before, edge ); 2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 20030a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project { 20040a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project if ( after->fpos == before->fpos ) 20050a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project edge->pos = before->pos; 20060a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project else 20070a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project edge->pos = before->pos + 20080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project FT_MulDiv( edge->fpos - before->fpos, 20090a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project after->pos - before->pos, 20100a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project after->fpos - before->fpos ); 20110a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project } 2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static void 2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_edge_points( AF_GlyphHints hints, 2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Dimension dim ) 2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_AxisHints axis = & hints->axis[dim]; 2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edges = axis->edges; 2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge_limit = edges + axis->num_edges; 2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Edge edge; 2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Bool snapping; 2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project snapping = FT_BOOL( ( dim == AF_DIMENSION_HORZ && 2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) || 2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dim == AF_DIMENSION_VERT && 2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ); 2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( edge = edges; edge < edge_limit; edge++ ) 2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* move the points of each segment */ 2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* in each edge to the edge's position */ 2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Segment seg = edge->first; 2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( snapping ) 2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point point = seg->first; 2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for (;;) 2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ ) 2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->x = edge->pos; 2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_X; 2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->y = edge->pos; 2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_Y; 2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point == seg->last ) 2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = point->next; 2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta = edge->pos - edge->opos; 2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project do 2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_Point point = seg->first; 2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for (;;) 2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ ) 2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->x += delta; 2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_X; 2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project else 2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->y += delta; 2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point->flags |= AF_FLAG_TOUCH_Y; 2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( point == seg->last ) 2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project break; 2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project point = point->next; 2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project seg = seg->edge_next; 2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } while ( seg != edge->first ); 2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_LOCAL_DEF( FT_Error ) 2108c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_hints_apply( AF_GlyphHints hints, 2109c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner FT_Outline* outline, 2110c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_CJKMetrics metrics ) 2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Error error; 2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project int dim; 2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_UNUSED( metrics ); 2116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2118aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich error = af_glyph_hints_reload( hints, outline ); 2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* analyze glyph outline */ 2123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( AF_HINTS_DO_HORIZONTAL( hints ) ) 2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_detect_features( hints, AF_DIMENSION_HORZ ); 2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2128c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2129c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_HORZ ); 2130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( AF_HINTS_DO_VERTICAL( hints ) ) 2133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project error = af_cjk_hints_detect_features( hints, AF_DIMENSION_VERT ); 2135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( error ) 2136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project goto Exit; 2137c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2138c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_cjk_hints_compute_blue_edges( hints, metrics, AF_DIMENSION_VERT ); 2139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /* grid-fit the outline */ 2142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ ) 2143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) || 2145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) ) ) 2146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2148c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#ifdef AF_CONFIG_OPTION_USE_WARPER 2149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project if ( dim == AF_DIMENSION_HORZ && 2150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL ) 2151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_WarperRec warper; 2153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Fixed scale; 2154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project FT_Pos delta; 2155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2157c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_warper_compute( &warper, hints, (AF_Dimension)dim, 2158c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner &scale, &delta ); 2159c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner af_glyph_hints_scale_dim( hints, (AF_Dimension)dim, 2160c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner scale, delta ); 2161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project continue; 2162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2163c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner#endif /* AF_CONFIG_OPTION_USE_WARPER */ 2164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_hint_edges( hints, (AF_Dimension)dim ); 2166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_align_edge_points( hints, (AF_Dimension)dim ); 2167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim ); 2168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim ); 2169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if 0 2173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_dump_points( hints ); 2174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_dump_segments( hints ); 2175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_dump_edges( hints ); 2176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif 2177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_glyph_hints_save( hints, outline ); 2179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project Exit: 2181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project return error; 2182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project } 2183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 2188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** C J K S C R I P T C L A S S *****/ 2189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /***** *****/ 2190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project /*************************************************************************/ 2192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2194c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner /* this corresponds to Unicode 6.0 */ 2195c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner 2196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static const AF_Script_UniRangeRec af_cjk_uniranges[] = 2197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2198a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang AF_UNIRANGE_REC( 0x1100UL, 0x11FFUL ), /* Hangul Jamo */ 2199295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x2E80UL, 0x2EFFUL ), /* CJK Radicals Supplement */ 2200295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x2F00UL, 0x2FDFUL ), /* Kangxi Radicals */ 2201c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0x2FF0UL, 0x2FFFUL ), /* Ideographic Description Characters */ 2202295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x3000UL, 0x303FUL ), /* CJK Symbols and Punctuation */ 2203295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x3040UL, 0x309FUL ), /* Hiragana */ 2204295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x30A0UL, 0x30FFUL ), /* Katakana */ 2205295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x3100UL, 0x312FUL ), /* Bopomofo */ 2206295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x3130UL, 0x318FUL ), /* Hangul Compatibility Jamo */ 2207c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0x3190UL, 0x319FUL ), /* Kanbun */ 2208295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x31A0UL, 0x31BFUL ), /* Bopomofo Extended */ 2209295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x31C0UL, 0x31EFUL ), /* CJK Strokes */ 2210295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x31F0UL, 0x31FFUL ), /* Katakana Phonetic Extensions */ 2211295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x3200UL, 0x32FFUL ), /* Enclosed CJK Letters and Months */ 2212295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x3300UL, 0x33FFUL ), /* CJK Compatibility */ 2213295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x3400UL, 0x4DBFUL ), /* CJK Unified Ideographs Extension A */ 2214295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x4DC0UL, 0x4DFFUL ), /* Yijing Hexagram Symbols */ 2215295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x4E00UL, 0x9FFFUL ), /* CJK Unified Ideographs */ 2216c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0xA960UL, 0xA97FUL ), /* Hangul Jamo Extended-A */ 2217c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0xAC00UL, 0xD7AFUL ), /* Hangul Syllables */ 2218c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0xD7B0UL, 0xD7FFUL ), /* Hangul Jamo Extended-B */ 2219295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0xF900UL, 0xFAFFUL ), /* CJK Compatibility Ideographs */ 2220c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0xFE10UL, 0xFE1FUL ), /* Vertical forms */ 2221295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0xFE30UL, 0xFE4FUL ), /* CJK Compatibility Forms */ 2222295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0xFF00UL, 0xFFEFUL ), /* Halfwidth and Fullwidth Forms */ 2223c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0x1B000UL, 0x1B0FFUL ), /* Kana Supplement */ 2224c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0x1D300UL, 0x1D35FUL ), /* Tai Xuan Hing Symbols */ 2225c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0x1F200UL, 0x1F2FFUL ), /* Enclosed Ideographic Supplement */ 2226295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x20000UL, 0x2A6DFUL ), /* CJK Unified Ideographs Extension B */ 2227c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0x2A700UL, 0x2B73FUL ), /* CJK Unified Ideographs Extension C */ 2228c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner AF_UNIRANGE_REC( 0x2B740UL, 0x2B81FUL ), /* CJK Unified Ideographs Extension D */ 2229295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0x2F800UL, 0x2FA1FUL ), /* CJK Compatibility Ideographs Supplement */ 2230295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0UL, 0UL ) 2231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project }; 2232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2234e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class, 2235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_SCRIPT_CJK, 2236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_uniranges, 2237a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 0x7530, /* 田 */ 2238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2239e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang sizeof ( AF_CJKMetricsRec ), 2240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_InitMetricsFunc) af_cjk_metrics_init, 2242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_ScaleMetricsFunc)af_cjk_metrics_scale, 2243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_DoneMetricsFunc) NULL, 2244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_InitHintsFunc) af_cjk_hints_init, 2246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_ApplyHintsFunc) af_cjk_hints_apply 2247295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner ) 2248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* !AF_CONFIG_OPTION_CJK */ 2250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project static const AF_Script_UniRangeRec af_cjk_uniranges[] = 2252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project { 2253295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner AF_UNIRANGE_REC( 0UL, 0UL ) 2254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project }; 2255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2257e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class, 2258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project AF_SCRIPT_CJK, 2259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project af_cjk_uniranges, 2260a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang 0, 2261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2262e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang sizeof ( AF_CJKMetricsRec ), 2263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_InitMetricsFunc) NULL, 2265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_ScaleMetricsFunc)NULL, 2266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_DoneMetricsFunc) NULL, 2267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_InitHintsFunc) NULL, 2269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project (AF_Script_ApplyHintsFunc) NULL 2270295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner ) 2271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* !AF_CONFIG_OPTION_CJK */ 2273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project 2275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */ 2276