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
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
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
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
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);
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
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
1098 layout->text = g_strndup (text, length);
1099 else
1100 layout->text = g_malloc0 (1);
1101
1102 layout->length = strlen (layout->text);
1103
1104
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
1120 if (!valid)
1121 *end++ = -1;
1122
1123 start = end;
1124 }
1125
1126 if (start != layout->text)
1127 TODO
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