⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fribidi_utils.c

📁 share BIDI DEMO code
💻 C
字号:
/* FriBidi - Library of BiDi algorithm * Copyright (C) 1999 Dov Grobgeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//*======================================================================//  This file contains various utility functions that are commonly//  needed by programs that implement BiDi functionality. The more//  code that may be put here, the easier it is for the application//  writers.//----------------------------------------------------------------------*/#include "fribidi.h"/*======================================================================//  The find_visual_ranges() function is used to convert between a//  continous span in either logical or visual space to a one, two or//  three discontinous spans in the other space. The function outputs//  the number of ranges needed to display the mapped range as//  well as the resolved ranges.////  The variable is_v2l_map indicates whether the position map is//  is in the direction of visual-to-logical. This information is//  needed in order to look up the correct character from the//  embedding_level_list which is assumed to be in logical order.////  This function is typically used to resolve a logical range to visual//  ranges e.g. to display the selection.////  Example://     The selection is between logical characters 10 to 45. Calculate//     the corresponding visual selection(s):////     gint sel_span[2] = {10,45};////     fribidi_map_range(sel_span,//                       TRUE,//                       length,//                       vis2log_map,//                       embedding_levels,//                       // output //                       &num_vis_ranges,//                       vis_ranges);////----------------------------------------------------------------------*/voidfribidi_map_range(gint in_span[2],          /* Start and end span */		  int len,		  gboolean is_v2l_map,      /* Needed for embedding_level */		  guint16 *position_map,		  guint8 *embedding_level_list,		  /* output */		  int *num_mapped_spans,		  int mapped_spans[3][2]){  gint ch_idx;  gboolean in_range = FALSE;  gint start_idx = in_span[0];  gint end_idx = in_span[1];  if (start_idx == -1)    start_idx = 0;    if (end_idx == -1)    end_idx = len;    *num_mapped_spans = 0;  /* This is a loop in the source space of the map... */  for (ch_idx = 0; ch_idx <= len; ch_idx++)    {      int mapped_pos;      gboolean is_char_rtl;            if (ch_idx < len)	{	  mapped_pos = position_map[ch_idx];	  if (is_v2l_map)	    is_char_rtl = embedding_level_list[mapped_pos];	  else	    is_char_rtl = embedding_level_list[ch_idx];	}      else	mapped_pos = -1; /* Will cause log_pos < start_idx to trigger below */            if (!in_range && mapped_pos >= start_idx && mapped_pos < end_idx)	{	  in_range = TRUE;	  (*num_mapped_spans)++;	  mapped_spans[(*num_mapped_spans)-1][0] = ch_idx;	}      else if (in_range && (mapped_pos < start_idx || mapped_pos >= end_idx))	{	  mapped_spans[(*num_mapped_spans)-1][1] = ch_idx;	  in_range = FALSE;	}    }}/*======================================================================//  fribidi_find_string_changes() finds the bounding box of the section//  of characters that need redrawing. It returns the start and the//  length of the section in the new string that needs redrawing.//----------------------------------------------------------------------*/voidfribidi_find_string_changes(/* input */			    FriBidiChar *old_str,			    int old_len,			    FriBidiChar *new_str,			    int new_len,			    /* output */			    int *change_start,			    int *change_len			    ){  int i;  int num_bol, num_eol;  /* Search forwards */  i = 0;  while(    i < old_len	 && i < new_len	 && old_str[i] == new_str[i])    i++;  num_bol = i;  /* Search backwards */  i = 0;  while(    i <old_len	 && i <new_len	 && old_str[old_len-1-i] == new_str[new_len-1-i])    i++;  num_eol = i;  /* Assign output */  *change_start = num_bol;  *change_len = new_len - num_eol - num_bol;}/*======================================================================//  fribidi_xpos_resolve() does the complicated translation of//  an x-coordinate, e.g. as received through a mouse press event,//  to the logical and the visual position the xcoordinate is closest//  to. It will also resolve the direction of the cursor according//  to the embedding level of the closest character.////  It does this through the following logics://  Here are the different possibilities:////        Pointer              =>          Log Pos         Vis pos//  //     Before first vis char             log_pos(vis=0)L       0//     After last vis char               log_pos(vis=n-1)R     n//     Within 1/2 width of vis char i    log_pos(vis=i)L       i//     Within last 1/2 width of vchar i  log_pos(vis=i)R       i+1//     Border between vis chars i,i+1       resolve!           i+1////  Input://     x_pos        The pixel position to be resolved measured in pixels.//     x_offset     The x_offset is the pixel position of the left side//                  of the leftmost visual character. //     len          The length of the embedding level, the vis2log and//                  the char width arrays.//     base_dir     The resolved base direction of the line.//     vis2log      The vis2log mapping.//                  x_position and the character widths. The position//                  (x_pos-x_offset) is number of pixels from the left//                  of logical character 0.//     char_widths  Width in pixels of each character. Note that the//                  widths should be provided in logical order.////  Output://     res_log_pos  Resolved logical position.//     res_vis_pos  Resolved visual position//     res_cursor_x_pos   The resolved pixel position to the left or//                  the right of the character position x_pos.//     res_cursor_dir_is_rtl   Whether the resolved dir of the character//                  at position x_pos is rtl.//     res_attach_before  Whether the x_pos is cutting the bounding//                  box in such a way that the visual cursor should be//                  be positioned before the following logical character.//                  Note that in the bidi context, the positions "after//                  a logical character" and "before the following logical//                  character" is not necessarily the same. If x_pos is//                  beyond the end of the line, res_attach_before is true.////----------------------------------------------------------------------*/void fribidi_xpos_resolve(gint x_pos,			  gint x_offset,			  gint len,			  guint8 *embedding_level_list,			  FriBidiCharType base_dir,			  guint16 *vis2log,			  gint16 *char_widths,			  /* output */			  gint *res_log_pos,			  gint *res_vis_pos,			  gint *res_cursor_x_pos,			  gboolean *res_cursor_dir_is_rtl,			  gboolean *res_attach_before			  ){  int char_width_sum=0;  int char_idx;  char_width_sum = 0;  *res_vis_pos = 0;  /* Check if we are to the left of the line bounding box */  if (x_pos < x_offset)    {      *res_cursor_dir_is_rtl = (base_dir == FRIBIDI_TYPE_RTL);      if (*res_cursor_dir_is_rtl) 	*res_log_pos = len;      else	*res_log_pos = 0;            *res_cursor_x_pos = x_offset;      *res_vis_pos = 0;      *res_attach_before = 1;    }  else    {      /* Find the cursor pos by a linear search on the row */      for (char_idx=0; char_idx < len; char_idx++)	{	  gint log_pos = vis2log[char_idx];	  gint char_width = char_widths[log_pos];	  	  if (x_offset + char_width_sum + char_width > x_pos)	    {	      /* Found position */	      *res_cursor_dir_is_rtl = fribidi_is_char_rtl(embedding_level_list,							   base_dir,							   log_pos);	      /* Are we in the left hand side of the clicked character? */	      if (x_pos - (x_offset + char_width_sum + char_width/2)<0)		{		  /* RTL? */		  if (*res_cursor_dir_is_rtl)		    {		      log_pos++;		      *res_attach_before = FALSE;		    }		  /* LTR */		  else		    *res_attach_before = TRUE;		  *res_cursor_x_pos = x_offset + char_width_sum;		}	      /* We are in the right hand side. */	      else		{		  /* LTR? */		  if (!*res_cursor_dir_is_rtl)		    {		      log_pos++;		      *res_attach_before = FALSE;		    }		  /* RTL */		  else		    *res_attach_before = TRUE;		  		  *res_cursor_x_pos = x_offset + char_width_sum + char_width;		  (*res_vis_pos)++;		}	      *res_log_pos = log_pos;	      break;	    }	  char_width_sum+= char_width;	  (*res_vis_pos)++;	}      /* If we still haven't found the position we are to the left of the	 character bounding box */      if (char_idx == len)	{	  *res_cursor_dir_is_rtl = (base_dir == FRIBIDI_TYPE_RTL);	  	  if (*res_cursor_dir_is_rtl) 	    *res_log_pos = 0;	  else	    *res_log_pos = len;	  *res_cursor_x_pos = char_width_sum + x_offset;	  *res_vis_pos = len;	  *res_attach_before = TRUE;	}    }  /*  printf("x l,v = %d %d,%d\n", *res_cursor_x_pos, *res_log_pos, *res_vis_pos); */}/*======================================================================//  fribidi_is_char_rtl() answers the question whether a character//  was resolved in the rtl direction. This simply involves asking//  if the embedding level for the character is odd.//----------------------------------------------------------------------*/gbooleanfribidi_is_char_rtl(guint8 *embedding_level_list,		    FriBidiCharType base_dir,		    int idx){  if (!embedding_level_list)      return FALSE;  else if (idx==-1)      return base_dir == FRIBIDI_TYPE_RTL;  /* Otherwise check if the embedding level is odd */  else      return embedding_level_list[idx] % 2;}/*======================================================================//  fribidi_runs_log2vis takes a list of logical runs and returns a//  a list of visual runs. A run is defined as a sequence that has//  the same attributes.//----------------------------------------------------------------------*/voidfribidi_runs_log2vis(/* input */		     GList *logical_runs,          /* List of FriBidiRunType */		     gint len,		     guint16 *log2vis,		     FriBidiCharType base_dir,		     /* output */		     GList **visual_runs){  void **visual_attribs = (void**)g_new(void*, len);  void *current_attrib;  int pos, i;  GList *list, *last;  int current_idx;  /* 1. Open up the runlength encoded list and at the same time apply     the log2vis map. The result is a visual array of attributes.  */  pos = 0;   list = logical_runs;  while(list)    {      FriBidiRunType *run = (FriBidiRunType*)(list->data);      int length = run->length;      void *attrib = run->attribute;      for (i = pos; i < pos+length; i++)	  visual_attribs[ log2vis[i] ] = attrib;      list = list->next;    }  /* 2. Run length encode the resulting attributes. */  *visual_runs = last = NULL;  current_attrib = visual_attribs[0];  current_idx = 0;  for (i=0; i<=len; i++)    {      if (i==len || current_attrib != visual_attribs[i])	{	  FriBidiRunType *run = g_new(FriBidiRunType, 1);	  run->length = i-current_idx;	  run->attribute = current_attrib;	  /* Keeping track of the last node is crucial for efficiency	     for long lists... */	  if (last == NULL) 	    last = *visual_runs = g_list_append(NULL, run);	  else	    {	      g_list_append(last, run);	      last = last->next;	    }	  if (i==len)	    break;	  	  current_attrib = visual_attribs[i];	  current_idx = i;	}    }  g_free(visual_runs);}		     

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -