static void draw_page (GtkPrintOperation *operation, GtkPrintContext *context, int page_nr, PrintData *print_data) { cairo_t *cr; GList *pagebreak; int start, end, i; PangoLayoutIter *iter; double start_pos; if (page_nr == 0) start = 0; else { pagebreak = g_list_nth (print_data->page_breaks, page_nr - 1); start = GPOINTER_TO_INT (pagebreak->data); } pagebreak = g_list_nth (print_data->page_breaks, page_nr); if (pagebreak == NULL) end = pango_layout_get_line_count (print_data->layout); else end = GPOINTER_TO_INT (pagebreak->data); cr = gtk_print_context_get_cairo_context (context); cairo_set_source_rgb (cr, 0, 0, 0); i = 0; start_pos = 0; iter = pango_layout_get_iter (print_data->layout); do { PangoRectangle logical_rect; PangoLayoutLine *line; int baseline; if (i >= start) { line = pango_layout_iter_get_line (iter); pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); baseline = pango_layout_iter_get_baseline (iter); if (i == start) start_pos = logical_rect.y / 1024.0; cairo_move_to (cr, logical_rect.x / 1024.0, baseline / 1024.0 - start_pos); pango_cairo_show_layout_line (cr, line); } i++; } while (i < end && pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); }
static PyObject * pango_GetLayoutLinePos(PyObject *self, PyObject *args) { int i, len; double baseline, dy; void *LayoutObj; PangoLayout *layout; PangoLayoutIter *iter; PyObject *ret; if (!PyArg_ParseTuple(args, "O", &LayoutObj)) { return NULL; } layout = PyCObject_AsVoidPtr(LayoutObj); len = pango_layout_get_line_count(layout); ret = PyTuple_New(len); iter = pango_layout_get_iter(layout); dy = ((double) pango_layout_iter_get_baseline(iter)) / PANGO_SCALE; for (i = 0; i < len; i++) { baseline = -1.0 * ((double) pango_layout_iter_get_baseline(iter)) / PANGO_SCALE + dy; PyTuple_SetItem(ret, i, PyFloat_FromDouble(baseline)); pango_layout_iter_next_line(iter); } pango_layout_iter_free(iter); return ret; }
static void test_file (const gchar *filename, GString *string) { gchar *contents; gchar *markup; gsize length; GError *error = NULL; PangoLayout *layout; gchar *p; gint width = 0; gint ellipsize_at = 0; PangoEllipsizeMode ellipsize = PANGO_ELLIPSIZE_NONE; PangoWrapMode wrap = PANGO_WRAP_WORD; PangoFontDescription *desc; if (!g_file_get_contents (filename, &contents, &length, &error)) { fprintf (stderr, "%s\n", error->message); g_error_free (error); return; } p = strchr (contents, '\n'); g_assert (p); markup = p + 1; *p = '\0'; parse_params (contents, &width, &ellipsize_at, &ellipsize, &wrap); layout = pango_layout_new (context); desc = pango_font_description_from_string ("Cantarell 11"); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); pango_layout_set_markup (layout, markup, length); g_free (contents); if (width != 0) pango_layout_set_width (layout, width * PANGO_SCALE); pango_layout_set_ellipsize (layout, ellipsize); pango_layout_set_wrap (layout, wrap); g_string_append (string, pango_layout_get_text (layout)); g_string_append (string, "\n---\n\n"); g_string_append_printf (string, "wrapped: %d\n", pango_layout_is_wrapped (layout)); g_string_append_printf (string, "ellipsized: %d\n", pango_layout_is_ellipsized (layout)); g_string_append_printf (string, "lines: %d\n", pango_layout_get_line_count (layout)); if (width != 0) g_string_append_printf (string, "width: %d\n", pango_layout_get_width (layout)); g_string_append (string, "\n---\n\n"); dump_attrs (pango_layout_get_attributes (layout), string); g_string_append (string, "\n---\n\n"); dump_lines (layout, string); g_string_append (string, "\n---\n\n"); dump_runs (layout, string); g_object_unref (layout); }
static void begin_print (GtkPrintOperation *operation, GtkPrintContext *context, PrintData *print_data) { PangoFontDescription *desc; PangoLayoutLine *layout_line; double width, height; double page_height; GList *page_breaks; int num_lines; int line; width = gtk_print_context_get_width (context); height = gtk_print_context_get_height (context); print_data->layout = gtk_print_context_create_pango_layout (context); desc = pango_font_description_from_string (print_data->font); pango_layout_set_font_description (print_data->layout, desc); pango_font_description_free (desc); pango_layout_set_width (print_data->layout, width * PANGO_SCALE); pango_layout_set_text (print_data->layout, print_data->text, -1); num_lines = pango_layout_get_line_count (print_data->layout); page_breaks = NULL; page_height = 0; for (line = 0; line < num_lines; line++) { PangoRectangle ink_rect, logical_rect; double line_height; layout_line = pango_layout_get_line (print_data->layout, line); pango_layout_line_get_extents (layout_line, &ink_rect, &logical_rect); line_height = logical_rect.height / 1024.0; if (page_height + line_height > height) { page_breaks = g_list_prepend (page_breaks, GINT_TO_POINTER (line)); page_height = 0; } page_height += line_height; } page_breaks = g_list_reverse (page_breaks); gtk_print_operation_set_n_pages (operation, g_list_length (page_breaks) + 1); print_data->page_breaks = page_breaks; }
static void _draw_page_results (GtkPrintContext *context, GwPageInfo *page, GwPrintData *data) { //Declarations GtkTextView *view; GtkTextBuffer *buffer; PangoLayout *layout; char *text; PangoFontDescription *desc; int width; int height; gdouble drawable_width, drawable_height; cairo_t *cr; gint line_start; gint line_end; //Initializations view = gw_searchwindow_get_current_textview (data->window); buffer = gtk_text_view_get_buffer (view); text = gtk_text_buffer_get_text (buffer, &(page->start), &(page->end), FALSE); layout = gtk_print_context_create_pango_layout (context); desc = pango_font_description_from_string ("sans 10"); drawable_width = gtk_print_context_get_width (context); drawable_height = gtk_print_context_get_height (context); cr = gtk_print_context_get_cairo_context (context); line_start = 0; line_end = 0; //Draw if (text != NULL) { cairo_move_to (cr, 5, 10); pango_layout_set_font_description (layout, desc); pango_layout_set_markup (layout, text, -1); pango_layout_set_width (layout, drawable_width * PANGO_SCALE); pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); pango_layout_set_height (layout, drawable_height * PANGO_SCALE); pango_layout_get_size (layout, &width, &height); pango_cairo_show_layout (cr, layout); //Adjust the end GtkTextIter to the cutoff in the visible cairo context line_start = gtk_text_iter_get_line (&page->start); line_end = line_start + pango_layout_get_line_count (layout) - 1; gtk_text_buffer_get_iter_at_line (buffer, &(page->end), line_end); } //Cleanup if (text != NULL) g_free (text); if (layout != NULL) g_object_unref (layout); if (desc != NULL) pango_font_description_free (desc); }
void buffer_to_pdf (Ebook * ebook) { GtkTextBuffer * buffer; GtkTextIter start, end; Pqueue queue; gchar * size, *editor_font; /* A4 initial */ queue.ebook = ebook; queue.pos = 0; queue.page_count = 1; queue.width = 8.3 * POINTS; queue.height = 11.7 * POINTS; queue.page_height = 40.0; g_return_if_fail (ebook); g_return_if_fail (ebook->filename); size = gconf_client_get_string (ebook->client, ebook->paper_size.key, NULL); buffer = GTK_TEXT_BUFFER(gtk_builder_get_object (ebook->builder, "textbuffer1")); queue.progressbar = GTK_PROGRESS_BAR(gtk_builder_get_object (ebook->builder, "progressbar")); queue.statusbar = GTK_STATUSBAR(gtk_builder_get_object (ebook->builder, "statusbar")); gtk_text_buffer_get_bounds (buffer, &start, &end); queue.text = g_strdup(gtk_text_buffer_get_text (buffer, &start, &end, TRUE)); editor_font = gconf_client_get_string(ebook->client, ebook->editor_font.key, NULL); if (0 == g_strcmp0 (size, "A5")) { queue.width = a5_width * POINTS; queue.height = a5_height * POINTS; } if (0 == g_strcmp0 (size, "B5")) { queue.width = b5_width * POINTS; queue.height = b5_height * POINTS; } queue.surface = cairo_pdf_surface_create (ebook->filename, queue.width, queue.height); queue.cr = cairo_create (queue.surface); queue.context = pango_cairo_create_context (queue.cr); /* pango_cairo_create_layout is wasteful with a lot of text. */ queue.desc = pango_font_description_from_string (editor_font); queue.layout = make_new_page (queue.context, queue.desc, queue.height, queue.width); pango_layout_set_text (queue.layout, queue.text, -1); cairo_move_to (queue.cr, SIDE_MARGIN / 2, EDGE_MARGIN / 2); gtk_progress_bar_set_fraction (queue.progressbar, 0.0); queue.lines_per_page = pango_layout_get_line_count (queue.layout); queue.iter = pango_layout_get_iter (queue.layout); create_pages (&queue); }
static void real_set_value (GdauiEntryWrapper *mgwrap, const GValue *value) { GdauiEntryString *mgstr; GdaDataHandler *dh; PangoLayout *layout; gchar *text; g_return_if_fail (GDAUI_IS_ENTRY_STRING (mgwrap)); mgstr = GDAUI_ENTRY_STRING (mgwrap); GdauiEntryStringPrivate *priv = gdaui_entry_string_get_instance_private (mgstr); dh = gdaui_data_entry_get_handler (GDAUI_DATA_ENTRY (mgwrap)); /* do we need to go into multi line mode ? */ text = gda_data_handler_get_str_from_value (dh, value); layout = gtk_widget_create_pango_layout (GTK_WIDGET (mgwrap), text); if (pango_layout_get_line_count (layout) > 1) g_object_set (G_OBJECT (mgwrap), "multiline", TRUE, NULL); g_object_unref (G_OBJECT (layout)); /* fill the single line widget */ if (value) { if (gda_value_is_null ((GValue *) value)) gdaui_entry_set_text (GDAUI_ENTRY (priv->entry), NULL); else gdaui_entry_set_text (GDAUI_ENTRY (priv->entry), text); } else gdaui_entry_set_text (GDAUI_ENTRY (priv->entry), NULL); /* fill the multiline widget */ if (value) { if (gda_value_is_null ((GValue *) value) || !text) gtk_text_buffer_set_text (priv->buffer, "", -1); else gtk_text_buffer_set_text (priv->buffer, text, -1); } else gtk_text_buffer_set_text (priv->buffer, "", -1); g_free (text); }
/* force to wrap truncated label by setting explicit size request * see N#27000 and G#329646 */ static void force_to_wrap_truncated (HildonBanner *banner) { PangoLayout *layout; int lines; int width; int height = -1; PangoRectangle logical; GtkRequisition requisition; HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner); g_return_if_fail (priv); width = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED : HILDON_BANNER_LABEL_MAX_PROGRESS; /* Force the label to compute its layout using the maximum * available width rather than its default one. */ gtk_widget_set_size_request (priv->label, width, height); gtk_widget_size_request (priv->label, &requisition); layout = gtk_label_get_layout (GTK_LABEL (priv->label)); pango_layout_get_extents (layout, NULL, &logical); /* Now get the actual width needed by the pango layout */ width = PANGO_PIXELS (logical.width); /* If the layout has now been wrapped and exceeds 3 lines, we truncate * the rest of the label according to spec. */ lines = pango_layout_get_line_count (layout); if (pango_layout_is_wrapped (layout) && lines > 3) { /* This calculation assumes that the same font is used * throughout the banner -- this is usually the case on maemo * * FIXME: Pango >= 1.20 has pango_layout_set_height(). */ height = (PANGO_PIXELS (logical.height) * 3) / lines + 1; } /* Set the final width/height */ gtk_widget_set_size_request (priv->label, width, height); }
gui2::tpoint ttext::get_cursor_position( const unsigned column, const unsigned line) const { recalculate(); // First we need to determine the byte offset, if more routines need it it // would be a good idea to make it a separate function. titor itor(layout_); // Go the wanted line. if(line != 0) { if(pango_layout_get_line_count(layout_) >= static_cast<int>(line)) { return gui2::tpoint(0, 0); } for(size_t i = 0; i < line; ++i) { pango_layout_iter_next_line(itor); } } // Go the wanted column. for(size_t i = 0; i < column; ++i) { if(!pango_layout_iter_next_char(itor)) { // It seems that the documentation is wrong and causes and off by // one error... the result should be false if already at the end of // the data when started. if(i + 1 == column) { break; } // We are beyond data. return gui2::tpoint(0, 0); } } // Get the byte offset const int offset = pango_layout_iter_get_index(itor); // Convert the byte offset in a position. PangoRectangle rect; pango_layout_get_cursor_pos(layout_, offset, &rect, nullptr); return gui2::tpoint(PANGO_PIXELS(rect.x), PANGO_PIXELS(rect.y)); }
/* Split a list of paragraphs into a list of lines. */ gchar *paps_layout_to_postscript_strdup(paps_t *paps_, double pos_x, double pos_y, PangoLayout *layout) { paps_private_t *paps = (paps_private_t*)paps_; GString *layout_str = g_string_new(""); gchar *ret_str; int para_num_lines, line_idx; double scale = 72.0 / PANGO_SCALE / PAPS_DPI; para_num_lines = pango_layout_get_line_count(layout); for (line_idx=0; line_idx<para_num_lines; line_idx++) { PangoRectangle logical_rect, ink_rect; PangoLayoutLine *pango_line = pango_layout_get_line(layout, line_idx); pango_layout_line_get_extents(pango_line, &ink_rect, &logical_rect); add_line_to_postscript(paps, layout_str, pos_x, pos_y, pango_line); pos_y -= logical_rect.height * scale; } ret_str = layout_str->str; g_string_free(layout_str, FALSE); return ret_str; }
static void cb_begin_print(GtkPrintOperation *op, GtkPrintContext *ctx, gpointer data) { gint layout_height; gchar *text; GtkTextIter start, end; GtkTextBuffer *buffer = gtk_text_view_get_buffer(data); PangoTabArray *tabs; gtk_text_buffer_get_bounds(buffer, &start, &end); text = g_strchomp(gtk_text_buffer_get_text(buffer, &start, &end, FALSE)); page_width = gtk_print_context_get_width(ctx); page_height = gtk_print_context_get_height(ctx); font_desc = gtk_widget_get_style(data)->font_desc; layout = gtk_print_context_create_pango_layout(ctx); pango_layout_set_width(layout, page_width * PANGO_SCALE); pango_layout_set_font_description(layout, font_desc); pango_layout_set_text(layout, text, -1); get_tab_array(&tabs, ctx, data); if (tabs) { pango_layout_set_tabs(layout, tabs); pango_tab_array_free(tabs); } pango_layout_get_size(layout, NULL, &layout_height); line_count = pango_layout_get_line_count(layout); text_height = pango_font_description_get_size(font_desc) / PANGO_SCALE; lines_per_page = page_height / text_height; n_pages = (line_count - 1) / lines_per_page + 1; gtk_print_operation_set_n_pages(op, n_pages); g_free(text); }
static void draw_text_line(DiaRenderer *self, TextLine *text_line, Point *pos, Alignment alignment, Color *color) { DiaPsFt2Renderer *renderer = DIA_PS_FT2_RENDERER(self); PangoLayout *layout; int line, linecount; double xpos = pos->x, ypos = pos->y; char *text = text_line_get_string(text_line); /* TODO: we could probably pass the alignment down to the PS file? */ xpos -= text_line_get_alignment_adjustment (text_line, alignment); /* Using the global PangoContext does not allow to have renderer specific * different ones. Or it implies the push/pop _context mess. Anyway just * get rid of warnings for now. But the local code may be resurreted * sooner or later... --hb */ #define USE_GLOBAL_CONTEXT #ifndef USE_GLOBAL_CONTEXT PangoAttrList* list; PangoAttribute* attr; guint length; #endif if ((!text)||(text == (const char *)(1))) return; lazy_setcolor(DIA_PS_RENDERER(renderer),color); #define ANNOYING_SCALE_FACTOR 5.9 /* Make sure the letters aren't too wide. */ #ifdef USE_GLOBAL_CONTEXT layout = dia_font_build_layout(text, text_line_get_font(text_line), text_line_get_height(text_line)*ANNOYING_SCALE_FACTOR); #else /* approximately what would be required but w/o dia_font_get_context() */ dia_font_set_height(text_line_get_font(text_line), text_line_get_height(text_line)); layout = pango_layout_new(dia_font_get_context()); length = text ? strlen(text) : 0; pango_layout_set_text(layout,text,length); list = pango_attr_list_new(); attr = pango_attr_font_desc_new(dia_font_get_description(text_line_get_font(text_line))); attr->start_index = 0; attr->end_index = length; pango_attr_list_insert(list,attr); pango_layout_set_attributes(layout,list); pango_attr_list_unref(list); pango_layout_set_indent(layout,0); pango_layout_set_justify(layout,FALSE); #endif pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT); linecount = pango_layout_get_line_count(layout); for (line = 0; line < linecount; line++) { PangoLayoutLine *layoutline = pango_layout_get_line(layout, line); /* Not sure scale is the right one here. */ text_line_adjust_layout_line(text_line, layoutline, ANNOYING_SCALE_FACTOR); postscript_draw_contour(DIA_PS_RENDERER(renderer), DPI, /* dpi_x */ layoutline, xpos, ypos); ypos += 10;/* Some line height thing??? */ } }
void gnm_rendered_value_remeasure (GnmRenderedValue *rv) { if (rv->rotation) { GnmRenderedRotatedValue *rrv = (GnmRenderedRotatedValue *)rv; PangoContext *context = pango_layout_get_context (rv->layout); double sin_a, abs_sin_a, cos_a; int sdx = 0; int x0 = 0, x1 = 0; PangoLayoutIter *iter; int l = 0; int lwidth; sin_a = rrv->rotmat.xy; abs_sin_a = fabs (sin_a); cos_a = rrv->rotmat.xx; pango_context_set_matrix (context, &rrv->rotmat); pango_layout_context_changed (rv->layout); rrv->linecount = pango_layout_get_line_count (rv->layout); rrv->lines = g_new (struct GnmRenderedRotatedValueInfo, rrv->linecount); pango_layout_get_size (rv->layout, &lwidth, NULL); rv->layout_natural_height = 0; iter = pango_layout_get_iter (rv->layout); do { PangoRectangle logical; int x, dx, dy, indent; int h, ytop, ybot, baseline; pango_layout_iter_get_line_extents (iter, NULL, &logical); pango_layout_iter_get_line_yrange (iter, &ytop, &ybot); baseline = pango_layout_iter_get_baseline (iter); indent = logical.x; if (sin_a < 0) indent -= lwidth; if (l == 0 && rv->noborders) sdx = (int)(baseline * sin_a - ybot / sin_a); dx = sdx + (int)(ybot / sin_a + indent * cos_a); dy = (int)((baseline - ybot) * cos_a - indent * sin_a); rrv->lines[l].dx = dx; rrv->lines[l].dy = dy; /* Left edge. */ x = dx - (int)((baseline - ytop) * sin_a); x0 = MIN (x0, x); /* Right edge. */ x = dx + (int)(logical.width * cos_a + (ybot - baseline) * sin_a); x1 = MAX (x1, x); h = logical.width * abs_sin_a + logical.height * cos_a; if (h > rv->layout_natural_height) rv->layout_natural_height = h; l++; } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); rv->layout_natural_width = x1 - x0; if (sin_a < 0) { int dx = rv->layout_natural_width; for (l = 0; l < rrv->linecount; l++) rrv->lines[l].dx += dx; } for (l = 0; l < rrv->linecount; l++) rrv->lines[l].dy += rv->layout_natural_height; #if 0 g_print ("Natural size: %d x %d\n", rv->layout_natural_width, rv->layout_natural_height); #endif pango_context_set_matrix (context, NULL); pango_layout_context_changed (rv->layout); } else
static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, uint32_t y) { uint32_t width = swaynag->width * swaynag->scale; int border = swaynag->type->details_border_thickness * swaynag->scale; int padding = swaynag->type->message_padding * swaynag->scale; int decor = padding + border; swaynag->details.x = decor; swaynag->details.y = y * swaynag->scale + decor; swaynag->details.width = width - decor * 2; PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font, swaynag->details.message, swaynag->scale, false); pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_single_paragraph_mode(layout, false); pango_cairo_update_layout(cairo, layout); swaynag->details.total_lines = pango_layout_get_line_count(layout); PangoLayoutLine *line; line = pango_layout_get_line_readonly(layout, swaynag->details.offset); gint offset = line->start_index; const char *text = pango_layout_get_text(layout); pango_layout_set_text(layout, text + offset, strlen(text) - offset); int text_width, text_height; pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, &text_width, &text_height); bool show_buttons = swaynag->details.offset > 0; int button_width = get_detailed_scroll_button_width(cairo, swaynag); if (show_buttons) { swaynag->details.width -= button_width; pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); } uint32_t ideal_height; do { ideal_height = swaynag->details.y + text_height + decor + padding * 2; if (ideal_height > SWAYNAG_MAX_HEIGHT) { ideal_height = SWAYNAG_MAX_HEIGHT; if (!show_buttons) { show_buttons = true; swaynag->details.width -= button_width; pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); } } swaynag->details.height = ideal_height - swaynag->details.y - decor; pango_layout_set_height(layout, (swaynag->details.height - padding * 2) * PANGO_SCALE); pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, &text_width, &text_height); } while (text_height != (swaynag->details.height - padding * 2)); swaynag->details.visible_lines = pango_layout_get_line_count(layout); if (show_buttons) { swaynag->details.button_up.x = swaynag->details.x + swaynag->details.width; swaynag->details.button_up.y = swaynag->details.y; swaynag->details.button_up.width = button_width; swaynag->details.button_up.height = swaynag->details.height / 2; render_details_scroll_button(cairo, swaynag, &swaynag->details.button_up); swaynag->details.button_down.x = swaynag->details.x + swaynag->details.width; swaynag->details.button_down.y = swaynag->details.button_up.y + swaynag->details.button_up.height; swaynag->details.button_down.width = button_width; swaynag->details.button_down.height = swaynag->details.height / 2; render_details_scroll_button(cairo, swaynag, &swaynag->details.button_down); } cairo_set_source_u32(cairo, swaynag->type->border); cairo_rectangle(cairo, swaynag->details.x, swaynag->details.y, swaynag->details.width, swaynag->details.height); cairo_fill(cairo); cairo_move_to(cairo, swaynag->details.x + padding, swaynag->details.y + padding); cairo_set_source_u32(cairo, swaynag->type->text); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); return ideal_height / swaynag->scale; }
/* * update_window_decoration_name * * Returns: void * Description: frees the last window name and gets the new one from * wnck. Also checks to see if the name has a length (slight optimization) * and re-creates the pango context to re-render the name */ void update_window_decoration_name (WnckWindow *win) { decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); const gchar *name; glong name_length; PangoLayoutLine *line; if (d->name) { g_free (d->name); d->name = NULL; } /* Only operate if the window name has a length */ name = wnck_window_get_name (win); if (name && (name_length = strlen (name))) { gint w; /* Cairo mode: w = SHRT_MAX */ if (theme_draw_window_decoration != draw_window_decoration) { w = SHRT_MAX; } /* Need to get a minimum width for the name */ else { gint width; wnck_window_get_client_window_geometry (win, NULL, NULL, &width, NULL); w = width - ICON_SPACE - 2 - d->button_width; if (w < 1) w = 1; } /* Set the maximum width for the layout (in case * decoration size < text width) since we * still need to show the buttons and the window name */ pango_layout_set_auto_dir (d->layout, FALSE); pango_layout_set_width (d->layout, w * PANGO_SCALE); pango_layout_set_text (d->layout, name, name_length); line = pango_layout_get_line (d->layout, 0); name_length = line->length; if (pango_layout_get_line_count (d->layout) > 1) { if (name_length < 4) { pango_layout_set_text (d->layout, NULL, 0); return; } d->name = g_strndup (name, name_length); strcpy (d->name + name_length - 3, "..."); } else d->name = g_strndup (name, name_length); /* Truncate the text */ pango_layout_set_text (d->layout, d->name, name_length); } }
static void _paint_lyrics (OlScrollWindow *scroll, cairo_t *cr) { ol_assert (OL_IS_SCROLL_WINDOW (scroll)); GtkWidget *widget = GTK_WIDGET (scroll); ol_assert (GTK_WIDGET_REALIZED (widget)); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); int line_height = ol_scroll_window_get_font_height (scroll) + priv->line_margin; int count = ol_scroll_window_compute_line_count (scroll); gint width, height; gdk_drawable_get_size (gtk_widget_get_window (GTK_WIDGET (scroll)), &width, &height); /* set the font */ PangoLayout *layout = _get_pango (scroll, cr); pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); pango_layout_set_width (layout, (width - priv->padding_x*2) * PANGO_SCALE); pango_layout_set_indent (layout, -20 * PANGO_SCALE); /* paint the lyrics*/ cairo_save (cr); cairo_new_path (cr); cairo_rectangle (cr, priv->padding_x, 0, width - priv->padding_x * 2, height - priv->padding_y * 2); cairo_close_path (cr); cairo_clip (cr); int i; gint current_lyric_id; gint lrc_y; _calc_paint_pos (scroll, ¤t_lyric_id, &lrc_y); int begin = current_lyric_id - count / 2; int end = current_lyric_id + count / 2 + 1; int ypos = height / 2 - lrc_y - (count / 2 + 1) * line_height; cairo_set_source_rgb(cr, priv->inactive_color.r, priv->inactive_color.g, priv->inactive_color.b); if (scroll->whole_lyrics != NULL) { for (i = begin; i < end; i++) { ypos += line_height; if (i < 0) continue; if (i >= scroll->whole_lyrics->len) break; pango_layout_set_text (layout, g_ptr_array_index (scroll->whole_lyrics, i), -1); cairo_save (cr); double ratio = _get_active_color_ratio (scroll, i); double alpha = 1.0; if (ypos < line_height / 2.0 + priv->padding_y) alpha = 1.0 - (line_height / 2.0 + priv->padding_y - ypos) * 1.0 / line_height * 2; else if (ypos > height - line_height * 1.5 - priv->padding_y) alpha = (height - line_height - priv->padding_y - ypos) * 1.0 / line_height * 2; if (alpha < 0.0) alpha = 0.0; cairo_set_source_rgba (cr, priv->active_color.r * ratio + priv->inactive_color.r * (1 - ratio), priv->active_color.g * ratio + priv->inactive_color.g * (1 - ratio), priv->active_color.b * ratio + priv->inactive_color.b * (1 - ratio), alpha); cairo_move_to (cr, priv->padding_x, ypos); pango_cairo_update_layout (cr, layout); pango_cairo_show_layout (cr, layout); cairo_restore (cr); if (pango_layout_is_wrapped (layout)) { // There is more than one line, offset ypos according to the number of // additional lines ypos += (pango_layout_get_line_count (layout) - 1) * ol_scroll_window_get_font_height (scroll); } } } g_object_unref (layout); cairo_reset_clip (cr); cairo_restore (cr); }
GpStatus pango_MeasureString (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, GDIPCONST RectF *rc, GDIPCONST GpStringFormat *format, RectF *boundingBox, int *codepointsFitted, int *linesFilled) { PangoLayout *layout; PangoLayoutLine *line; PangoRectangle logical; PangoLayoutIter *iter; int *charsRemoved = NULL; cairo_save (graphics->ct); layout = gdip_pango_setup_layout (graphics, stringUnicode, length, font, rc, boundingBox, format, &charsRemoved); if (!layout) { cairo_restore (graphics->ct); return OutOfMemory; } if (codepointsFitted) { int charsFitted; int lastIndex; int y0; int y1; double min_x; double max_x; double max_y; const char *layoutText; if (boundingBox && format && (format->formatFlags & StringFormatFlagsDirectionVertical)) { min_x = boundingBox->Y; max_x = boundingBox->Y + boundingBox->Height; max_y = boundingBox->X + boundingBox->Width; } else if (boundingBox) { min_x = boundingBox->X; max_x = boundingBox->X + boundingBox->Width; max_y = boundingBox->Y + boundingBox->Height; } else if (format && (format->formatFlags & StringFormatFlagsDirectionVertical)) { min_x = rc->Y; max_x = rc->Y + rc->Height; max_y = rc->X + rc->Width; } else { min_x = rc->X; max_x = rc->X + rc->Width; max_y = rc->Y + rc->Height; } lastIndex = 0; iter = pango_layout_get_iter (layout); do { if (iter == NULL) break; pango_layout_iter_get_line_yrange (iter, &y0, &y1); if (y0 / PANGO_SCALE >= max_y) break; if (pango_layout_iter_at_last_line (iter)) { do { pango_layout_iter_get_char_extents (iter, &logical); /* check both max and min to catch right-to-left text, also width may be negative */ if ((logical.x / PANGO_SCALE > max_x || (logical.x + logical.width) / PANGO_SCALE > max_x) || (logical.x / PANGO_SCALE < min_x || (logical.x + logical.width) / PANGO_SCALE < min_x)) break; lastIndex = pango_layout_iter_get_index (iter); } while (pango_layout_iter_next_char (iter)); break; } else { line = pango_layout_iter_get_line_readonly (iter); lastIndex = line->start_index + line->length - 1; } } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); layoutText = pango_layout_get_text (layout); /* this can happen when the string ends in a newline */ if (lastIndex >= strlen (layoutText)) lastIndex = strlen (layoutText) - 1; /* Add back in any & characters removed and the final newline characters (if any) */ charsFitted = g_utf8_strlen (layoutText, lastIndex + 1) + charsRemoved [lastIndex]; //g_warning("lastIndex: %d\t\tcharsRemoved: %d", lastIndex, charsRemoved[lastIndex]); /* safe because of null termination */ switch (layoutText [lastIndex + 1]) { case '\r': charsFitted++; if (layoutText [lastIndex + 2] == '\n') charsFitted++; break; case '\n': charsFitted++; break; } *codepointsFitted = charsFitted; } GdipFree (charsRemoved); if (linesFilled) { *linesFilled = pango_layout_get_line_count (layout); // g_warning ("linesFilled %d", *linesFilled); } // else g_warning ("linesFilled %d", pango_layout_get_line_count (layout)); g_object_unref (layout); cairo_restore (graphics->ct); return Ok; }
static void gimp_text_tool_move_cursor (GimpTextTool *text_tool, GtkMovementStep step, gint count, gboolean extend_selection) { GtkTextBuffer *buffer = GTK_TEXT_BUFFER (text_tool->buffer); GtkTextIter cursor; GtkTextIter selection; GtkTextIter *sel_start; gboolean cancel_selection = FALSE; gint x_pos = -1; GIMP_LOG (TEXT_EDITING, "%s count = %d, select = %s", g_enum_get_value (g_type_class_ref (GTK_TYPE_MOVEMENT_STEP), step)->value_name, count, extend_selection ? "TRUE" : "FALSE"); gtk_text_buffer_get_iter_at_mark (buffer, &cursor, gtk_text_buffer_get_insert (buffer)); gtk_text_buffer_get_iter_at_mark (buffer, &selection, gtk_text_buffer_get_selection_bound (buffer)); if (extend_selection) { sel_start = &selection; } else { /* when there is a selection, moving the cursor without * extending it should move the cursor to the end of the * selection that is in moving direction */ if (count > 0) gtk_text_iter_order (&selection, &cursor); else gtk_text_iter_order (&cursor, &selection); sel_start = &cursor; /* if we actually have a selection, just move *to* the beginning/end * of the selection and not *from* there on LOGICAL_POSITIONS * and VISUAL_POSITIONS movement */ if (! gtk_text_iter_equal (&cursor, &selection)) cancel_selection = TRUE; } switch (step) { case GTK_MOVEMENT_LOGICAL_POSITIONS: if (! cancel_selection) gtk_text_iter_forward_visible_cursor_positions (&cursor, count); break; case GTK_MOVEMENT_VISUAL_POSITIONS: if (! cancel_selection) { PangoLayout *layout; const gchar *text; if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); text = pango_layout_get_text (layout); while (count != 0) { const gunichar word_joiner = 8288; /*g_utf8_get_char(WORD_JOINER);*/ gint index; gint trailing = 0; gint new_index; index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (count > 0) { if (g_utf8_get_char (text + index) == word_joiner) pango_layout_move_cursor_visually (layout, TRUE, index, 0, 1, &new_index, &trailing); else new_index = index; pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, 1, &new_index, &trailing); count--; } else { pango_layout_move_cursor_visually (layout, TRUE, index, 0, -1, &new_index, &trailing); if (new_index != -1 && new_index != G_MAXINT && g_utf8_get_char (text + new_index) == word_joiner) { pango_layout_move_cursor_visually (layout, TRUE, new_index, trailing, -1, &new_index, &trailing); } count++; } if (new_index != G_MAXINT && new_index != -1) index = new_index; else break; gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, index, TRUE); gtk_text_iter_forward_chars (&cursor, trailing); } } break; case GTK_MOVEMENT_WORDS: if (count < 0) { gtk_text_iter_backward_visible_word_starts (&cursor, -count); } else if (count > 0) { if (! gtk_text_iter_forward_visible_word_ends (&cursor, count)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINES: { GtkTextIter start; GtkTextIter end; gint cursor_index; PangoLayout *layout; PangoLayoutLine *layout_line; PangoLayoutIter *layout_iter; PangoRectangle logical; gint line; gint trailing; gint i; gtk_text_buffer_get_bounds (buffer, &start, &end); cursor_index = gimp_text_buffer_get_iter_index (text_tool->buffer, &cursor, TRUE); if (! gimp_text_tool_ensure_layout (text_tool)) break; layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_index_to_line_x (layout, cursor_index, FALSE, &line, &x_pos); layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); x_pos += logical.x; pango_layout_iter_free (layout_iter); /* try to go to the remembered x_pos if it exists *and* we are at * the beginning or at the end of the current line */ if (text_tool->x_pos != -1 && (x_pos <= logical.x || x_pos >= logical.x + logical.width)) x_pos = text_tool->x_pos; line += count; if (line < 0) { cursor = start; break; } else if (line >= pango_layout_get_line_count (layout)) { cursor = end; break; } layout_iter = pango_layout_get_iter (layout); for (i = 0; i < line; i++) pango_layout_iter_next_line (layout_iter); layout_line = pango_layout_iter_get_line_readonly (layout_iter); pango_layout_iter_get_line_extents (layout_iter, NULL, &logical); pango_layout_iter_free (layout_iter); pango_layout_line_x_to_index (layout_line, x_pos - logical.x, &cursor_index, &trailing); gimp_text_buffer_get_iter_at_index (text_tool->buffer, &cursor, cursor_index, TRUE); while (trailing--) gtk_text_iter_forward_char (&cursor); } break; case GTK_MOVEMENT_PAGES: /* well... */ case GTK_MOVEMENT_BUFFER_ENDS: if (count < 0) { gtk_text_buffer_get_start_iter (buffer, &cursor); } else if (count > 0) { gtk_text_buffer_get_end_iter (buffer, &cursor); } break; case GTK_MOVEMENT_PARAGRAPH_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; case GTK_MOVEMENT_DISPLAY_LINE_ENDS: if (count < 0) { gtk_text_iter_set_line_offset (&cursor, 0); } else if (count > 0) { if (! gtk_text_iter_ends_line (&cursor)) gtk_text_iter_forward_to_line_end (&cursor); } break; default: return; } text_tool->x_pos = x_pos; gimp_draw_tool_pause (GIMP_DRAW_TOOL (text_tool)); gimp_text_tool_reset_im_context (text_tool); gtk_text_buffer_select_range (buffer, &cursor, sel_start); gimp_draw_tool_resume (GIMP_DRAW_TOOL (text_tool)); }
static VALUE rg_line_count(VALUE self) { return INT2NUM(pango_layout_get_line_count(_SELF(self))); }