Compare commits
2 Commits
render-tex
...
dotted-lin
Author | SHA1 | Date | |
---|---|---|---|
|
4ced8d1803 | ||
|
14b1873e5a |
115
gtk/gskpango.c
115
gtk/gskpango.c
@@ -108,23 +108,88 @@ gsk_pango_renderer_draw_glyph_item (PangoRenderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
gsk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
|
||||||
PangoRenderPart part,
|
PangoRenderPart part,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int width,
|
||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
||||||
GdkRGBA rgba;
|
GdkRGBA rgba;
|
||||||
|
double xx, yy, ww, hh;
|
||||||
|
GtkLineStyle line_style;
|
||||||
|
|
||||||
|
xx = (double)x / PANGO_SCALE;
|
||||||
|
yy = (double)y / PANGO_SCALE;
|
||||||
|
ww = (double)width / PANGO_SCALE;
|
||||||
|
hh = (double)height / PANGO_SCALE;
|
||||||
|
|
||||||
get_color (crenderer, part, &rgba);
|
get_color (crenderer, part, &rgba);
|
||||||
gtk_snapshot_append_color (crenderer->snapshot,
|
|
||||||
&rgba,
|
if (part == PANGO_RENDER_PART_UNDERLINE ||
|
||||||
&GRAPHENE_RECT_INIT ((double)x / PANGO_SCALE,
|
part == PANGO_RENDER_PART_STRIKETHROUGH ||
|
||||||
(double)y / PANGO_SCALE,
|
part == PANGO_RENDER_PART_OVERLINE)
|
||||||
(double)width / PANGO_SCALE,
|
line_style = crenderer->line_style;
|
||||||
(double)height / PANGO_SCALE));
|
else
|
||||||
|
line_style = GTK_LINE_STYLE_SOLID;
|
||||||
|
|
||||||
|
switch (line_style)
|
||||||
|
{
|
||||||
|
case GTK_LINE_STYLE_SOLID:
|
||||||
|
gtk_snapshot_append_color (crenderer->snapshot,
|
||||||
|
&rgba,
|
||||||
|
&GRAPHENE_RECT_INIT (xx, yy, ww, hh));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_LINE_STYLE_DOTTED:
|
||||||
|
{
|
||||||
|
GskRoundedRect dot;
|
||||||
|
double d = hh;
|
||||||
|
graphene_rect_t bounds = GRAPHENE_RECT_INIT (xx, yy, d, d);
|
||||||
|
graphene_size_t rr = GRAPHENE_SIZE_INIT (d/2, d/2);
|
||||||
|
GdkRGBA transparent = { 0.f, 0.f, 0.f, 0.f };
|
||||||
|
|
||||||
|
gsk_rounded_rect_init (&dot, &bounds, &rr, &rr, &rr, &rr);
|
||||||
|
|
||||||
|
gtk_snapshot_push_repeat (crenderer->snapshot,
|
||||||
|
&GRAPHENE_RECT_INIT (xx, yy, ww, hh),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
gtk_snapshot_push_rounded_clip (crenderer->snapshot, &dot);
|
||||||
|
gtk_snapshot_append_color (crenderer->snapshot, &rgba, &bounds);
|
||||||
|
gtk_snapshot_pop (crenderer->snapshot);
|
||||||
|
gtk_snapshot_append_color (crenderer->snapshot, &transparent, &GRAPHENE_RECT_INIT (xx + d, yy, 0.5 * d, d));
|
||||||
|
gtk_snapshot_pop (crenderer->snapshot);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GTK_LINE_STYLE_DASHED:
|
||||||
|
{
|
||||||
|
GskColorStop stops[4];
|
||||||
|
GdkRGBA transparent = { 0.f, 0.f, 0.f, 0.f };
|
||||||
|
|
||||||
|
stops[0].offset = 0;
|
||||||
|
stops[0].color = rgba;
|
||||||
|
stops[1].offset = 0.66;
|
||||||
|
stops[1].color = rgba;
|
||||||
|
stops[2].offset = 0.66;
|
||||||
|
stops[2].color = transparent;
|
||||||
|
stops[3].offset = 1;
|
||||||
|
stops[3].color = transparent;
|
||||||
|
|
||||||
|
gtk_snapshot_append_repeating_linear_gradient (
|
||||||
|
crenderer->snapshot,
|
||||||
|
&GRAPHENE_RECT_INIT (xx, yy, ww, hh),
|
||||||
|
&GRAPHENE_POINT_INIT (xx, yy),
|
||||||
|
&GRAPHENE_POINT_INIT (xx + 9 * MIN (ww, hh), yy),
|
||||||
|
stops, 4);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -343,6 +408,24 @@ get_item_appearance (PangoItem *item)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GtkLineStyle
|
||||||
|
get_item_line_style (PangoItem *item)
|
||||||
|
{
|
||||||
|
GSList *tmp_list = item->analysis.extra_attrs;
|
||||||
|
|
||||||
|
while (tmp_list)
|
||||||
|
{
|
||||||
|
PangoAttribute *attr = tmp_list->data;
|
||||||
|
|
||||||
|
if (attr->klass->type == gtk_text_attr_line_style_type)
|
||||||
|
return ((GtkTextAttrLineStyle *)attr)->value;
|
||||||
|
|
||||||
|
tmp_list = tmp_list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GTK_LINE_STYLE_SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
|
gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
|
||||||
PangoLayoutRun *run)
|
PangoLayoutRun *run)
|
||||||
@@ -351,9 +434,17 @@ gsk_pango_renderer_prepare_run (PangoRenderer *renderer,
|
|||||||
const GdkRGBA *bg_rgba = NULL;
|
const GdkRGBA *bg_rgba = NULL;
|
||||||
const GdkRGBA *fg_rgba = NULL;
|
const GdkRGBA *fg_rgba = NULL;
|
||||||
GtkTextAppearance *appearance;
|
GtkTextAppearance *appearance;
|
||||||
|
GtkLineStyle line_style;
|
||||||
|
|
||||||
PANGO_RENDERER_CLASS (gsk_pango_renderer_parent_class)->prepare_run (renderer, run);
|
PANGO_RENDERER_CLASS (gsk_pango_renderer_parent_class)->prepare_run (renderer, run);
|
||||||
|
|
||||||
|
line_style = get_item_line_style (run->item);
|
||||||
|
if (crenderer->line_style != line_style)
|
||||||
|
{
|
||||||
|
pango_renderer_part_changed (renderer, PANGO_RENDER_PART_UNDERLINE);
|
||||||
|
crenderer->line_style = get_item_line_style (run->item);
|
||||||
|
}
|
||||||
|
|
||||||
appearance = get_item_appearance (run->item);
|
appearance = get_item_appearance (run->item);
|
||||||
|
|
||||||
if (appearance == NULL)
|
if (appearance == NULL)
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <pango/pango.h>
|
#include <pango/pango.h>
|
||||||
#include "gtk/gtksnapshot.h"
|
#include "gtk/gtksnapshot.h"
|
||||||
|
#include "gtk/gtktextlayoutprivate.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -68,6 +69,8 @@ struct _GskPangoRenderer
|
|||||||
guint is_cached_renderer : 1;
|
guint is_cached_renderer : 1;
|
||||||
|
|
||||||
GskPangoShapeHandler shape_handler;
|
GskPangoShapeHandler shape_handler;
|
||||||
|
|
||||||
|
GtkLineStyle line_style;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GskPangoRendererClass
|
struct _GskPangoRendererClass
|
||||||
|
@@ -52,6 +52,7 @@
|
|||||||
#include "gtkdragsourceprivate.h"
|
#include "gtkdragsourceprivate.h"
|
||||||
#include "gtkdragicon.h"
|
#include "gtkdragicon.h"
|
||||||
#include "gtkcsscolorvalueprivate.h"
|
#include "gtkcsscolorvalueprivate.h"
|
||||||
|
#include "gtktextlayoutprivate.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -1259,6 +1260,85 @@ gtk_label_size_allocate (GtkWidget *widget,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_dotted_underline (PangoLayout *layout)
|
||||||
|
{
|
||||||
|
const char *text;
|
||||||
|
char *p;
|
||||||
|
GSList *l, *ll, *a;
|
||||||
|
|
||||||
|
text = pango_layout_get_text (layout);
|
||||||
|
p = strstr (text, "good");
|
||||||
|
|
||||||
|
for (int i = 0; i < pango_layout_get_line_count (layout); i++)
|
||||||
|
{
|
||||||
|
PangoLayoutLine *line = pango_layout_get_line (layout, i);
|
||||||
|
|
||||||
|
for (l = line->runs, ll = NULL; l; ll = l, l = l->next)
|
||||||
|
{
|
||||||
|
PangoGlyphItem *run = l->data;
|
||||||
|
|
||||||
|
if (run == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (p != NULL && text + run->item->offset <= p && p + strlen ("good") <= text + run->item->offset + run->item->length)
|
||||||
|
{
|
||||||
|
/* Match inside this item */
|
||||||
|
if (text + run->item->offset < p)
|
||||||
|
{
|
||||||
|
PangoGlyphItem *before;
|
||||||
|
|
||||||
|
/* split off initial segment */
|
||||||
|
before = pango_glyph_item_split (run, text, p - (text + run->item->offset));
|
||||||
|
if (ll)
|
||||||
|
{
|
||||||
|
ll->next = g_slist_prepend (l, before);
|
||||||
|
ll = ll->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line->runs = g_slist_prepend (line->runs, before);
|
||||||
|
ll = line->runs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p + strlen ("good") < text + run->item->offset + run->item->length)
|
||||||
|
{
|
||||||
|
/* split off final segment */
|
||||||
|
run = pango_glyph_item_split (run, text, strlen ("good"));
|
||||||
|
|
||||||
|
if (ll)
|
||||||
|
ll->next = g_slist_prepend (l, run);
|
||||||
|
else
|
||||||
|
line->runs = g_slist_prepend (line->runs, run);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a = run->item->analysis.extra_attrs; a; a = a->next)
|
||||||
|
{
|
||||||
|
PangoAttribute *attr = a->data;
|
||||||
|
|
||||||
|
if (attr->klass->type == gtk_text_attr_line_style_type)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == NULL)
|
||||||
|
{
|
||||||
|
PangoAttribute *attr;
|
||||||
|
|
||||||
|
attr = gtk_text_attr_line_style_new (GTK_LINE_STYLE_DOTTED);
|
||||||
|
run->item->analysis.extra_attrs =
|
||||||
|
g_slist_prepend (run->item->analysis.extra_attrs, attr);
|
||||||
|
|
||||||
|
attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
|
||||||
|
run->item->analysis.extra_attrs =
|
||||||
|
g_slist_prepend (run->item->analysis.extra_attrs, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define GRAPHENE_RECT_FROM_RECT(_r) (GRAPHENE_RECT_INIT ((_r)->x, (_r)->y, (_r)->width, (_r)->height))
|
#define GRAPHENE_RECT_FROM_RECT(_r) (GRAPHENE_RECT_INIT ((_r)->x, (_r)->y, (_r)->width, (_r)->height))
|
||||||
|
|
||||||
@@ -1280,6 +1360,7 @@ gtk_label_snapshot (GtkWidget *widget,
|
|||||||
context = _gtk_widget_get_style_context (widget);
|
context = _gtk_widget_get_style_context (widget);
|
||||||
get_layout_location (self, &lx, &ly);
|
get_layout_location (self, &lx, &ly);
|
||||||
|
|
||||||
|
add_dotted_underline (self->layout);
|
||||||
gtk_snapshot_render_layout (snapshot, context, lx, ly, self->layout);
|
gtk_snapshot_render_layout (snapshot, context, lx, ly, self->layout);
|
||||||
|
|
||||||
info = self->select_info;
|
info = self->select_info;
|
||||||
|
@@ -1512,6 +1512,51 @@ gtk_text_attr_appearance_new (const GtkTextAppearance *appearance)
|
|||||||
return (PangoAttribute *)result;
|
return (PangoAttribute *)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PangoAttribute *
|
||||||
|
attr_line_style_copy (const PangoAttribute *attr)
|
||||||
|
{
|
||||||
|
const GtkTextAttrLineStyle *a = (GtkTextAttrLineStyle *)attr;
|
||||||
|
return gtk_text_attr_line_style_new (a->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
attr_line_style_destroy (PangoAttribute *attr)
|
||||||
|
{
|
||||||
|
g_slice_free (GtkTextAttrLineStyle, (gpointer)attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
attr_line_style_equal (const PangoAttribute *attr1,
|
||||||
|
const PangoAttribute *attr2)
|
||||||
|
{
|
||||||
|
const GtkTextAttrLineStyle *a1 = (GtkTextAttrLineStyle *)attr1;
|
||||||
|
const GtkTextAttrLineStyle *a2 = (GtkTextAttrLineStyle *)attr2;
|
||||||
|
return a1->value == a2->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PangoAttrType gtk_text_attr_line_style_type = 0;
|
||||||
|
|
||||||
|
PangoAttribute *
|
||||||
|
gtk_text_attr_line_style_new (GtkLineStyle style)
|
||||||
|
{
|
||||||
|
static PangoAttrClass klass = {
|
||||||
|
0,
|
||||||
|
attr_line_style_copy,
|
||||||
|
attr_line_style_destroy,
|
||||||
|
attr_line_style_equal
|
||||||
|
};
|
||||||
|
GtkTextAttrLineStyle *attr;
|
||||||
|
|
||||||
|
if (!klass.type)
|
||||||
|
klass.type = gtk_text_attr_line_style_type =
|
||||||
|
pango_attr_type_register (I_("GtkTextAttrLineStyle"));
|
||||||
|
|
||||||
|
attr = g_slice_new (GtkTextAttrLineStyle);
|
||||||
|
pango_attribute_init (&attr->attr, &klass);
|
||||||
|
attr->value = style;
|
||||||
|
return (PangoAttribute *)attr;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_generic_attrs (GtkTextLayout *layout,
|
add_generic_attrs (GtkTextLayout *layout,
|
||||||
GtkTextAppearance *appearance,
|
GtkTextAppearance *appearance,
|
||||||
|
@@ -219,6 +219,21 @@ struct _GtkTextLineDisplay
|
|||||||
|
|
||||||
#ifdef GTK_COMPILATION
|
#ifdef GTK_COMPILATION
|
||||||
extern G_GNUC_INTERNAL PangoAttrType gtk_text_attr_appearance_type;
|
extern G_GNUC_INTERNAL PangoAttrType gtk_text_attr_appearance_type;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GTK_LINE_STYLE_SOLID,
|
||||||
|
GTK_LINE_STYLE_DASHED,
|
||||||
|
GTK_LINE_STYLE_DOTTED
|
||||||
|
} GtkLineStyle;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PangoAttribute attr;
|
||||||
|
GtkLineStyle value;
|
||||||
|
} GtkTextAttrLineStyle;
|
||||||
|
|
||||||
|
extern PangoAttrType gtk_text_attr_line_style_type;
|
||||||
|
|
||||||
|
PangoAttribute *gtk_text_attr_line_style_new (GtkLineStyle style);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GType gtk_text_layout_get_type (void) G_GNUC_CONST;
|
GType gtk_text_layout_get_type (void) G_GNUC_CONST;
|
||||||
|
@@ -50,7 +50,7 @@ main (int argc, char *argv[])
|
|||||||
g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
|
g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
|
||||||
|
|
||||||
button = gtk_button_new ();
|
button = gtk_button_new ();
|
||||||
gtk_button_set_label (GTK_BUTTON (button), "hello world");
|
gtk_button_set_label (GTK_BUTTON (button), "good world");
|
||||||
gtk_widget_set_margin_top (button, 10);
|
gtk_widget_set_margin_top (button, 10);
|
||||||
gtk_widget_set_margin_bottom (button, 10);
|
gtk_widget_set_margin_bottom (button, 10);
|
||||||
gtk_widget_set_margin_start (button, 10);
|
gtk_widget_set_margin_start (button, 10);
|
||||||
|
Reference in New Issue
Block a user