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

📄 ellipsize.c

📁 GTK+-2.0源码之pango-1.15.6.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
		     int                new_index){  int start, end;  do    {      pango_attr_iterator_range (iter, &start, &end);      if (end > new_index)	break;    }  while (pango_attr_iterator_next (iter));}/* Updates the shaping of the ellipsis if necessary when we move the * position of the start of the gap. * * The shaping of the ellipsis is determined by two things: * * - The font attributes applied to the first character in the gap * - Whether the first character in the gap is wide or not. If the *   first character is wide, then we assume that we are ellipsizing *   East-Asian text, so prefer a mid-line ellipsizes to a baseline *   ellipsis, since that's typical practice for Chinese/Japanese/Korean. */static voidupdate_ellipsis_shape (EllipsizeState *state){  gboolean recompute = FALSE;  gunichar start_wc;  gboolean is_cjk;  /* Unfortunately, we can only advance PangoAttrIterator forward; so each   * time we back up we need to go forward to find the new position. To make   * this not utterly slow, we cache an iterator at the start of the line   */  if (!state->line_start_attr)    {      state->line_start_attr = pango_attr_list_get_iterator (state->attrs);      advance_iterator_to (state->line_start_attr, state->run_info[0].run->item->offset);    }  if (state->gap_start_attr)    {      /* See if the current attribute range contains the new start position       */      int start, end;      pango_attr_iterator_range (state->gap_start_attr, &start, &end);      if (state->gap_start_iter.run_iter.start_index < start)	{	  pango_attr_iterator_destroy (state->gap_start_attr);	  state->gap_start_attr = NULL;	}    }  /* Check whether we need to recompute the ellipsis because of new font attributes   */  if (!state->gap_start_attr)    {      state->gap_start_attr = pango_attr_iterator_copy (state->line_start_attr);      advance_iterator_to (state->gap_start_attr,			   state->run_info[state->gap_start_iter.run_index].run->item->offset);      recompute = TRUE;    }  /* Check whether we need to recompute the ellipsis because we switch from CJK to not   * or vice-versa   */  start_wc = g_utf8_get_char (state->layout->text + state->gap_start_iter.run_iter.start_index);  is_cjk = g_unichar_iswide (start_wc);  if (is_cjk != state->ellipsis_is_cjk)    {      state->ellipsis_is_cjk = is_cjk;      recompute = TRUE;    }  if (recompute)    shape_ellipsis (state);}/* Computes the position of the gap center and finds the smallest span containing it */static voidfind_initial_span (EllipsizeState *state){  PangoGlyphItem *glyph_item;  PangoGlyphItemIter *run_iter;  gboolean have_cluster;  int i;  int x;  int cluster_width;  switch (state->layout->ellipsize)    {    case PANGO_ELLIPSIZE_NONE:    default:      g_assert_not_reached ();    case PANGO_ELLIPSIZE_START:      state->gap_center = 0;      break;    case PANGO_ELLIPSIZE_MIDDLE:      state->gap_center = state->total_width / 2;      break;    case PANGO_ELLIPSIZE_END:      state->gap_center = state->total_width;      break;    }  /* Find the run containing the gap center   */  x = 0;  for (i = 0; i < state->n_runs; i++)    {      if (x + state->run_info[i].width > state->gap_center)	break;      x += state->run_info[i].width;    }  if (i == state->n_runs)	/* Last run is a closed interval, so back off one run */    {      i--;      x -= state->run_info[i].width;    }  /* Find the cluster containing the gap center   */  state->gap_start_iter.run_index = i;  run_iter = &state->gap_start_iter.run_iter;  glyph_item = state->run_info[i].run;  cluster_width = 0;		/* Quiet GCC, the line must have at least one cluster */  for (have_cluster = _pango_glyph_item_iter_init_start (run_iter, glyph_item, state->layout->text);       have_cluster;       have_cluster = _pango_glyph_item_iter_next_cluster (run_iter))    {      cluster_width = get_cluster_width (&state->gap_start_iter);      if (x + cluster_width > state->gap_center)	break;      x += cluster_width;    }  if (!have_cluster)	/* Last cluster is a closed interval, so back off one cluster */    x -= cluster_width;  state->gap_end_iter = state->gap_start_iter;  state->gap_start_x = x;  state->gap_end_x = x + cluster_width;  /* Expand the gap to a full span   */  while (!starts_at_ellipsization_boundary (state, &state->gap_start_iter))    {      line_iter_prev_cluster (state, &state->gap_start_iter);      state->gap_start_x -= get_cluster_width (&state->gap_start_iter);    }  while (!ends_at_ellipsization_boundary (state, &state->gap_end_iter))    {      line_iter_next_cluster (state, &state->gap_end_iter);      state->gap_end_x += get_cluster_width (&state->gap_end_iter);    }  update_ellipsis_shape (state);}/* Removes one run from the start or end of the gap. Returns FALSE * if there's nothing left to remove in either direction. */static gbooleanremove_one_span (EllipsizeState *state){  LineIter new_gap_start_iter;  LineIter new_gap_end_iter;  int new_gap_start_x;  int new_gap_end_x;  int width;  /* Find one span backwards and forward from the gap   */  new_gap_start_iter = state->gap_start_iter;  new_gap_start_x = state->gap_start_x;  do    {      if (!line_iter_prev_cluster (state, &new_gap_start_iter))	break;      width = get_cluster_width (&new_gap_start_iter);      new_gap_start_x -= width;    }  while (!starts_at_ellipsization_boundary (state, &new_gap_start_iter) ||	 width == 0);  new_gap_end_iter = state->gap_end_iter;  new_gap_end_x = state->gap_end_x;  do    {      if (!line_iter_next_cluster (state, &new_gap_end_iter))	break;      width = get_cluster_width (&new_gap_end_iter);      new_gap_end_x += width;    }  while (!ends_at_ellipsization_boundary (state, &new_gap_end_iter) ||	 width == 0);  if (state->gap_end_x == new_gap_end_x && state->gap_start_x == new_gap_start_x)    return FALSE;  /* In the case where we could remove a span from either end of the   * gap, we look at which causes the smaller increase in the   * MAX (gap_end - gap_center, gap_start - gap_center)   */  if (state->gap_end_x == new_gap_end_x ||      (state->gap_start_x != new_gap_start_x &&       state->gap_center - new_gap_start_x < new_gap_end_x - state->gap_center))    {      state->gap_start_iter = new_gap_start_iter;      state->gap_start_x = new_gap_start_x;      update_ellipsis_shape (state);    }  else    {      state->gap_end_iter = new_gap_end_iter;      state->gap_end_x = new_gap_end_x;    }  return TRUE;}/* Fixes up the properties of the ellipsis run once we've determined the final extents * of the gap */static voidfixup_ellipsis_run (EllipsizeState *state){  PangoGlyphString *glyphs = state->ellipsis_run->glyphs;  PangoItem *item = state->ellipsis_run->item;  int level;  int i;  /* Make the entire glyphstring into a single logical cluster */  for (i = 0; i < glyphs->num_glyphs; i++)    {      glyphs->log_clusters[i] = 0;      glyphs->glyphs[i].attr.is_cluster_start = FALSE;    }  glyphs->glyphs[0].attr.is_cluster_start = TRUE;  /* Fix up the item to point to the entire elided text */  item->offset = state->gap_start_iter.run_iter.start_index;  item->length = state->gap_end_iter.run_iter.end_index - item->offset;  item->num_chars = g_utf8_strlen (state->layout->text + item->offset, item->length);  /* The level for the item is the minimum level of the elided text */  level = G_MAXINT;  for (i = state->gap_start_iter.run_index; i <= state->gap_end_iter.run_index; i++)    level = MIN (level, state->run_info[i].run->item->analysis.level);  item->analysis.level = level;}/* Computes the new list of runs for the line */static GSList *get_run_list (EllipsizeState *state){  PangoGlyphItem *partial_start_run = NULL;  PangoGlyphItem *partial_end_run = NULL;  GSList *result = NULL;  RunInfo *run_info;  PangoGlyphItemIter *run_iter;  int i;  /* We first cut out the pieces of the starting and ending runs we want to   * preserve; we do the end first in case the end and the start are   * the same. Doing the start first would disturb the indices for the end.   */  run_info = &state->run_info[state->gap_end_iter.run_index];  run_iter = &state->gap_end_iter.run_iter;  if (run_iter->end_char != run_info->run->item->num_chars)    {      partial_end_run = run_info->run;      run_info->run = pango_glyph_item_split (run_info->run, state->layout->text,					      run_iter->end_index - run_info->run->item->offset);    }  run_info = &state->run_info[state->gap_start_iter.run_index];  run_iter = &state->gap_start_iter.run_iter;  if (run_iter->start_char != 0)    {      partial_start_run = pango_glyph_item_split (run_info->run, state->layout->text,						  run_iter->start_index - run_info->run->item->offset);    }  /* Now assemble the new list of runs   */  for (i = 0; i < state->gap_start_iter.run_index; i++)    result = g_slist_prepend (result, state->run_info[i].run);  if (partial_start_run)    result = g_slist_prepend (result, partial_start_run);  result = g_slist_prepend (result, state->ellipsis_run);  if (partial_end_run)    result = g_slist_prepend (result, partial_end_run);  for (i = state->gap_end_iter.run_index + 1; i < state->n_runs; i++)    result = g_slist_prepend (result, state->run_info[i].run);  /* And free the ones we didn't use   */  for (i = state->gap_start_iter.run_index; i <= state->gap_end_iter.run_index; i++)    pango_glyph_item_free (state->run_info[i].run);  return g_slist_reverse (result);}/* Computes the width of the line as currently ellipsized */static intcurrent_width (EllipsizeState *state){  return state->total_width - (state->gap_end_x - state->gap_start_x) + state->ellipsis_width;}/** * _pango_layout_line_ellipsize: * @line: a #PangoLayoutLine * @attrs: Attributes being used for itemization/shaping * * Given a #PangoLayoutLine with the runs still in logical order, ellipsize * it according the layout's policy to fit within the set width of the layout. * * Return value: whether the line had to be ellipsized **/gboolean_pango_layout_line_ellipsize (PangoLayoutLine *line,			      PangoAttrList   *attrs){  EllipsizeState state;  int goal_width;  gboolean is_ellipsized = FALSE;  if (line->layout->ellipsize == PANGO_ELLIPSIZE_NONE ||      line->layout->width < 0)    goto ret;  init_state (&state, line, attrs);  goal_width = state.layout->width;  if (state.layout->indent > 0 && state.layout->alignment != PANGO_ALIGN_CENTER)    goal_width -= state.layout->indent;  if (state.total_width <= goal_width)    goto out;  find_initial_span (&state);  while (current_width (&state) > goal_width)    {      if (!remove_one_span (&state))	break;    }  fixup_ellipsis_run (&state);  g_slist_free (line->runs);  line->runs = get_run_list (&state);  is_ellipsized = TRUE; out:  free_state (&state); ret:  return is_ellipsized;}

⌨️ 快捷键说明

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