のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

pango_layout_check_lines

3898
3899 static void
3900 pango_layout_check_lines (PangoLayout *layout)
3901 {
3902     const char *start;
3903     gboolean done = FALSE;
3904     int start_offset;
3905     PangoAttrList *attrs;
3906     PangoAttrList *no_shape_attrs;
3907     PangoAttrIterator *iter;
3908     PangoDirection prev_base_dir = PANGO_DIRECTION_NEUTRAL, base_dir = PANGO_DIRECTION_NEUTRAL;
3909     ParaBreakState state;
3910
3911     check_context_changed (layout);
3912
3913     if (G_LIKELY (layout->lines))
3914         return;
3915
3916     g_assert (!layout->log_attrs);
3917
3918     /* For simplicity, we make sure at this point that layout->text
3919      * is non-NULL even if it is zero length
3920      */
3921     if (G_UNLIKELY (!layout->text))
3922         pango_layout_set_text (layout, NULL, 0);
3923
3924     attrs = pango_layout_get_effective_attributes (layout);
3925     no_shape_attrs = filter_no_shape_attributes (attrs);
3926     iter = pango_attr_list_get_iterator (attrs);
3927
3928     layout->log_attrs = g_new (PangoLogAttr, layout->n_chars + 1);
3929
3930     start_offset = 0;
3931     start = layout->text;
3932
3933     /* Find the first strong direction of the text */
3934     if (layout->auto_dir)
3935     {
3936         prev_base_dir = pango_find_base_dir (layout->text, layout->length);
3937         if (prev_base_dir == PANGO_DIRECTION_NEUTRAL)
3938   	      prev_base_dir = pango_context_get_base_dir (layout->context);
3939     }
3940     else
3941         base_dir = pango_context_get_base_dir (layout->context);
3942
3943     /* these are only used if layout->height >= 0 */
3944     state.remaining_height = layout->height;
3945     state.line_height = -1;
3946     if (layout->height >= 0)
3947     {
3948         PangoRectangle logical;
3949         pango_layout_get_empty_extents_at_index (layout, 0, &logical);
3950         state.line_height = logical.height;
3951     }
3952
3953     do
3954     {
3955         int delim_len;
3956         const char *end;
3957         int delimiter_index, next_para_index;
3958
3959         if (layout->single_paragraph)
3960	 {
3961	     delimiter_index = layout->length;
3962	     next_para_index = layout->length;
3963	 }
3964        else
3965	 {
3966	      pango_find_paragraph_boundary (start,
3967					 (layout->text + layout->length) - start,
3968					 &delimiter_index,
3969					 &next_para_index);
3970	}
3971
3972      g_assert (next_para_index >= delimiter_index);
3973
3974      if (layout->auto_dir)
3975      {
3976          base_dir = pango_find_base_dir (start, delimiter_index);
3977
3978          /* Propagate the base direction for neutral paragraphs */
3979          if (base_dir == PANGO_DIRECTION_NEUTRAL)
3980              base_dir = prev_base_dir;
3981          else
3982              prev_base_dir = base_dir;
3983     }
3984
3985      end = start + delimiter_index;
3986
3987      delim_len = next_para_index - delimiter_index;
3988
3989      if (end == (layout->text + layout->length))
3990          done = TRUE;
3991
3992      g_assert (end <= (layout->text + layout->length));
3993      g_assert (start <= (layout->text + layout->length));
3994      g_assert (delim_len < 4);	/* PS is 3 bytes */
3995      g_assert (delim_len >= 0);
3996
3997      state.attrs = attrs;
3998      state.items = pango_itemize_with_base_dir (layout->context,
3999						 base_dir,
4000						 layout->text,
4001						 start - layout->text,
4002						 end - start,
4003						 attrs,
4004						 iter);
4005
4006      get_items_log_attrs (start, state.items,
4007			   layout->log_attrs + start_offset,
4008			   delim_len);
4009
4010         state.base_dir = base_dir;
4011         state.line_of_par = 1;
4012         state.start_offset = start_offset;
4013         state.line_start_offset = start_offset;
4014         state.line_start_index = start - layout->text;
4015
4016         state.glyphs = NULL;
4017         state.log_widths = NULL;
4018
4019         /* for deterministic bug hunting's sake set everything! */
4020         state.line_width = -1;
4021         state.remaining_width = -1;
4022         state.log_widths_offset = 0;
4023
4024         if (state.items)
4025         {
4026	      while (state.items)
4027	      process_line (layout, &state);
4028         }
4029         else
4030         {
4031              PangoLayoutLine *empty_line;
4032
4033	      empty_line = pango_layout_line_new (layout);
4034	      empty_line->start_index = state.line_start_index;
4035	      empty_line->is_paragraph_start = TRUE;
4036	      line_set_resolved_dir (empty_line, base_dir);
4037
4038	      add_line (empty_line, &state);
4039         }
4040
4041         if (layout->height >= 0 && state.remaining_height < state.line_height)
4042            done = TRUE;
4043
4044         if (!done)
4045             start_offset += pango_utf8_strlen (start, (end - start) + delim_len);
4046
4047         start = end + delim_len;
4048     }
4049     while (!done);
4050
4051     pango_attr_iterator_destroy (iter);
4052     pango_attr_list_unref (attrs);
4053
4054     if (no_shape_attrs)
4055     {
4056         apply_no_shape_attributes (layout, no_shape_attrs);
4057         pango_attr_list_unref (no_shape_attrs);
4058     }
4059
4060     layout->lines = g_slist_reverse (layout->lines);
4061 }
4062
1081 void
1082 pango_layout_set_text (PangoLayout *layout,
1083		       const char  *text,
1084		       int          length)
1085 {
1086     char *old_text, *start, *end;
1087
1088     g_return_if_fail (layout != NULL);
1089     g_return_if_fail (length == 0 || text != NULL);
1090
1091     old_text = layout->text;
1092
1093     if (length < 0)
1094         layout->text = g_strdup (text);
1095     else if (length > 0)
1096         /* This is not exactly what we want.  We don't need the padding...
1097         */
1098        layout->text = g_strndup (text, length);
1099     else
1100         layout->text = g_malloc0 (1);
1101
1102     layout->length = strlen (layout->text);
1103
1104     /* validate it, and replace invalid bytes with '?'
1105     */
1106     start = layout->text;
1107     for (;;) {
1108        gboolean valid;
1109
1110         valid = g_utf8_validate (start, -1, (const char **)&end);
1111
1112         if (!*end)
1113              break;
1114
1115         /* Replace invalid bytes with -1.  The -1 will be converted to
1116          * ((gunichar) -1) by glib, and that in turn yields a glyph value of
1117          * ((PangoGlyph) -1) by PANGO_GET_UNKNOWN_GLYPH(-1),
1118          * and that's PANGO_GLYPH_INVALID_INPUT.
1119          */
1120         if (!valid)
1121             *end++ = -1;
1122
1123         start = end;
1124     }
1125
1126     if (start != layout->text)
1127         /* TODO: Write out the beginning excerpt of text? */
1128         g_warning ("Invalid UTF-8 string passed to pango_layout_set_text()");
1129
1130     layout->n_chars = pango_utf8_strlen (layout->text, -1);
1131
1132     layout_changed (layout);
1133
1134     g_free (old_text);
1135 }
1136