bool wxStaticText::SetFont( const wxFont &font ) { const bool wasUnderlined = GetFont().GetUnderlined(); const bool wasStrickenThrough = GetFont().GetStrikethrough(); bool ret = wxControl::SetFont(font); const bool isUnderlined = GetFont().GetUnderlined(); const bool isStrickenThrough = GetFont().GetStrikethrough(); if ( (isUnderlined != wasUnderlined) || (isStrickenThrough != wasStrickenThrough) ) { // We need to update the Pango attributes used for the text. if ( isUnderlined || isStrickenThrough ) { PangoAttrList* const attrs = pango_attr_list_new(); if ( isUnderlined ) { PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); a->start_index = 0; a->end_index = (guint)-1; pango_attr_list_insert(attrs, a); } if ( isStrickenThrough ) { PangoAttribute *a = pango_attr_strikethrough_new( TRUE ); a->start_index = 0; a->end_index = (guint) -1; pango_attr_list_insert(attrs, a); } gtk_label_set_attributes(GTK_LABEL(m_widget), attrs); pango_attr_list_unref(attrs); } else // No special attributes any more. { // Just remove any attributes we had set. gtk_label_set_attributes(GTK_LABEL(m_widget), NULL); } // The underlines for mnemonics are incompatible with using attributes // so turn them off when setting underlined font. gtk_label_set_use_underline(GTK_LABEL(m_widget), !isUnderlined); } // adjust the label size to the new label unless disabled if (!HasFlag(wxST_NO_AUTORESIZE)) { SetSize( GetBestSize() ); } return ret; }
/** * _st_set_text_from_style: * @text: Target #ClutterText * @theme_node: Source #StThemeNode * * Set various GObject properties of the @text object using * CSS information from @theme_node. */ void _st_set_text_from_style (ClutterText *text, StThemeNode *theme_node) { ClutterColor color; StTextDecoration decoration; PangoAttrList *attribs = NULL; const PangoFontDescription *font; StTextAlign align; st_theme_node_get_foreground_color (theme_node, &color); clutter_text_set_color (text, &color); font = st_theme_node_get_font (theme_node); clutter_text_set_font_description (text, (PangoFontDescription *) font); decoration = st_theme_node_get_text_decoration (theme_node); if (decoration) { attribs = pango_attr_list_new (); if (decoration & ST_TEXT_DECORATION_UNDERLINE) { PangoAttribute *underline = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr_list_insert (attribs, underline); } if (decoration & ST_TEXT_DECORATION_LINE_THROUGH) { PangoAttribute *strikethrough = pango_attr_strikethrough_new (TRUE); pango_attr_list_insert (attribs, strikethrough); } /* Pango doesn't have an equivalent attribute for _OVERLINE, and we deliberately * skip BLINK (for now...) */ } clutter_text_set_attributes (text, attribs); if (attribs) pango_attr_list_unref (attribs); align = st_theme_node_get_text_align (theme_node); if (align == ST_TEXT_ALIGN_JUSTIFY) { clutter_text_set_justify (text, TRUE); clutter_text_set_line_alignment (text, PANGO_ALIGN_LEFT); } else { clutter_text_set_justify (text, FALSE); clutter_text_set_line_alignment (text, (PangoAlignment) align); } }
static int cdfont(cdCtxCanvas *ctxcanvas, const char *typeface, int style, int size) { int is_italic = 0, is_bold = 0; /* default is CD_PLAIN */ int is_strikeout = 0, is_underline = 0; char font[256]; PangoAttrList *attrs; if (cdStrEqualNoCase(typeface, "Courier") || cdStrEqualNoCase(typeface, "Courier New")) typeface = "Monospace"; else if (cdStrEqualNoCase(typeface, "Times") || cdStrEqualNoCase(typeface, "Times New Roman")) typeface = "Serif"; else if (cdStrEqualNoCase(typeface, "Helvetica") || cdStrEqualNoCase(typeface, "Arial")) typeface = "Sans"; if (style & CD_BOLD) is_bold = 1; if (style & CD_ITALIC) is_italic = 1; if (style & CD_UNDERLINE) is_underline = 1; if (style & CD_STRIKEOUT) is_strikeout = 1; size = cdGetFontSizePoints(ctxcanvas->canvas, size); sprintf(font, "%s, %s%s%d", typeface, is_bold?"Bold ":"", is_italic?"Italic ":"", size); if (ctxcanvas->fontdesc) pango_font_description_free(ctxcanvas->fontdesc); ctxcanvas->fontdesc = pango_font_description_from_string(font); if (!ctxcanvas->fontdesc) return 0; if (ctxcanvas->fontlayout) g_object_unref(ctxcanvas->fontlayout); ctxcanvas->fontlayout = pango_layout_new(ctxcanvas->fontcontext); pango_layout_set_font_description(ctxcanvas->fontlayout, ctxcanvas->fontdesc); attrs = pango_attr_list_new(); pango_attr_list_insert(attrs, pango_attribute_copy(pango_attr_strikethrough_new(is_strikeout ? TRUE : FALSE))); pango_attr_list_insert(attrs, pango_attribute_copy(pango_attr_underline_new(is_underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE))); pango_layout_set_attributes(ctxcanvas->fontlayout, attrs); pango_attr_list_unref(attrs); return 1; }
static gboolean s_parse_func (MarkupData *md, OpenTag *tag, const gchar **names, const gchar **values, GMarkupParseContext *context, GError **error) { CHECK_NO_ATTRS("s"); add_attribute (tag, pango_attr_strikethrough_new (TRUE)); return TRUE; }
// Although we don't use this function yet, but we must create it here. // first, for the prepare the unicode drawing support in wxUniv/x11 port. // If we use pango to draw the text, then we must set some attributes // for pango layout, such as "strikethrough" and "underline". bool wxFont::SetPangoAttrs(PangoLayout* layout) const { if ( !IsOk() || !(GetUnderlined() || GetStrikethrough()) ) return false; PangoAttrList* attrs = pango_attr_list_new(); PangoAttribute* a; if ( GetUnderlined() ) { a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr_list_insert(attrs, a); } if ( GetStrikethrough() ) { a = pango_attr_strikethrough_new(true); pango_attr_list_insert(attrs, a); } pango_layout_set_attributes(layout, attrs); pango_attr_list_unref(attrs); return true; }
static PangoLayout * rsvg_text_create_layout (RsvgDrawingCtx * ctx, RsvgState * state, const char *text, PangoContext * context) { PangoFontDescription *font_desc; PangoLayout *layout; PangoAttrList *attr_list; PangoAttribute *attribute; if (state->lang) pango_context_set_language (context, pango_language_from_string (state->lang)); if (state->unicode_bidi == UNICODE_BIDI_OVERRIDE || state->unicode_bidi == UNICODE_BIDI_EMBED) pango_context_set_base_dir (context, state->text_dir); font_desc = pango_font_description_copy (pango_context_get_font_description (context)); if (state->font_family) pango_font_description_set_family_static (font_desc, state->font_family); pango_font_description_set_style (font_desc, state->font_style); pango_font_description_set_variant (font_desc, state->font_variant); pango_font_description_set_weight (font_desc, state->font_weight); pango_font_description_set_stretch (font_desc, state->font_stretch); pango_font_description_set_size (font_desc, _rsvg_css_normalize_font_size (state, ctx) * PANGO_SCALE / ctx->dpi_y * 72); layout = pango_layout_new (context); pango_layout_set_font_description (layout, font_desc); pango_font_description_free (font_desc); attr_list = pango_attr_list_new (); attribute = pango_attr_letter_spacing_new (_rsvg_css_normalize_length (&state->letter_spacing, ctx, 'h') * PANGO_SCALE); attribute->start_index = 0; attribute->end_index = G_MAXINT; pango_attr_list_insert (attr_list, attribute); if (state->has_font_decor && text) { if (state->font_decor & TEXT_UNDERLINE) { attribute = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); attribute->start_index = 0; attribute->end_index = -1; pango_attr_list_insert (attr_list, attribute); } if (state->font_decor & TEXT_STRIKE) { attribute = pango_attr_strikethrough_new (TRUE); attribute->start_index = 0; attribute->end_index = -1; pango_attr_list_insert (attr_list, attribute); } } pango_layout_set_attributes (layout, attr_list); pango_attr_list_unref (attr_list); if (text) pango_layout_set_text (layout, text, -1); else pango_layout_set_text (layout, NULL, 0); pango_layout_set_alignment (layout, (state->text_dir == PANGO_DIRECTION_LTR || state->text_dir == PANGO_DIRECTION_TTB_LTR) ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); return layout; }
/* * This function is used by gail_text_cell_get_offset_at_point() * and gail_text_cell_get_character_extents(). There is no * cached PangoLayout for gailtextcell so we must create a temporary * one using this function. */ static PangoLayout* create_pango_layout(GtkCellRendererText *gtk_renderer, GtkWidget *widget) { PangoAttrList *attr_list; PangoLayout *layout; PangoUnderline uline; PangoFontMask mask; layout = gtk_widget_create_pango_layout (widget, gtk_renderer->text); if (gtk_renderer->extra_attrs) attr_list = pango_attr_list_copy (gtk_renderer->extra_attrs); else attr_list = pango_attr_list_new (); if (gtk_renderer->foreground_set) { PangoColor color; color = gtk_renderer->foreground; add_attr (attr_list, pango_attr_foreground_new (color.red, color.green, color.blue)); } if (gtk_renderer->strikethrough_set) add_attr (attr_list, pango_attr_strikethrough_new (gtk_renderer->strikethrough)); mask = pango_font_description_get_set_fields (gtk_renderer->font); if (mask & PANGO_FONT_MASK_FAMILY) add_attr (attr_list, pango_attr_family_new (pango_font_description_get_family (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_STYLE) add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_VARIANT) add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_WEIGHT) add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_STRETCH) add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (gtk_renderer->font))); if (mask & PANGO_FONT_MASK_SIZE) add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (gtk_renderer->font))); if (gtk_renderer->scale_set && gtk_renderer->font_scale != 1.0) add_attr (attr_list, pango_attr_scale_new (gtk_renderer->font_scale)); if (gtk_renderer->underline_set) uline = gtk_renderer->underline_style; else uline = PANGO_UNDERLINE_NONE; if (uline != PANGO_UNDERLINE_NONE) add_attr (attr_list, pango_attr_underline_new (gtk_renderer->underline_style)); if (gtk_renderer->rise_set) add_attr (attr_list, pango_attr_rise_new (gtk_renderer->rise)); pango_layout_set_attributes (layout, attr_list); pango_layout_set_width (layout, -1); pango_attr_list_unref (attr_list); return layout; }
void GuiSolidLabelElementRenderer::OnElementStateChanged() { FontProperties font = element->GetFont(); Color color = element->GetColor(); int layoutWidth, layoutHeight; AString family = wtoa(font.fontFamily); pango_font_description_set_family(pangoFontDesc, family.Buffer()); pango_font_description_set_absolute_size(pangoFontDesc, font.size * PANGO_SCALE); if(font.italic) pango_font_description_set_style(pangoFontDesc, PANGO_STYLE_ITALIC); else pango_font_description_set_style(pangoFontDesc, PANGO_STYLE_NORMAL); if(attrList) { pango_attr_list_unref(attrList); } attrList = pango_attr_list_new(); pango_attr_list_insert(attrList, pango_attr_underline_new( font.underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE) ); pango_attr_list_insert(attrList, pango_attr_strikethrough_new ( font.strikeline ? TRUE : FALSE ) ); pango_attr_list_insert(attrList, pango_attr_weight_new ( font.bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_MEDIUM ) ); if(layout) { g_object_unref(layout); layout = NULL; } if(cairoContext) { layout = pango_cairo_create_layout(cairoContext); WString wtext = (font.fontFamily == L"Webdings") ? helpers::WebdingsMap(element->GetText()) : element->GetText(); AString text = wtoa(wtext); pango_layout_set_font_description(layout, pangoFontDesc); pango_layout_set_attributes(layout, attrList); pango_layout_set_text(layout, text.Buffer(), text.Length()); pango_layout_set_alignment(layout, element->GetHorizontalAlignment() == Alignment::Left ? PANGO_ALIGN_LEFT : element->GetHorizontalAlignment() == Alignment::Center ? PANGO_ALIGN_CENTER : element->GetHorizontalAlignment() == Alignment::Right ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT ); pango_cairo_update_layout(cairoContext, layout); pango_layout_get_pixel_size( layout, &layoutWidth, &layoutHeight); minSize.x = layoutWidth; minSize.y = layoutHeight; } }
bool wxFont::GTKSetPangoAttrs(PangoLayout* layout) const { if (!IsOk() || !(GetUnderlined() || GetStrikethrough())) return false; PangoAttrList* attrs = pango_attr_list_new(); PangoAttribute* a; if (wx_pango_version_check(1,16,0)) { // a PangoLayout which has leading/trailing spaces with underlined font // is not correctly drawn by this pango version: Pango won't underline the spaces. // This can be a problem; e.g. wxHTML rendering of underlined text relies on // this behaviour. To workaround this problem, we use a special hack here // suggested by pango maintainer Behdad Esfahbod: we prepend and append two // empty space characters and give them a dummy colour attribute. // This will force Pango to underline the leading/trailing spaces, too. const char* text = pango_layout_get_text(layout); const size_t n = strlen(text); if ((n > 0 && text[0] == ' ') || (n > 1 && text[n - 1] == ' ')) { wxCharBuffer buf(n + 6); // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format memcpy(buf.data(), "\342\200\214", 3); // copy the user string memcpy(buf.data() + 3, text, n); // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format memcpy(buf.data() + 3 + n, "\342\200\214", 3); pango_layout_set_text(layout, buf, n + 6); // Add dummy attributes (use colour as it's invisible anyhow for 0 // width spaces) to ensure that the spaces in the beginning/end of the // string are underlined too. a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614); a->start_index = 0; a->end_index = 3; pango_attr_list_insert(attrs, a); a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614); a->start_index = n + 3; a->end_index = n + 6; pango_attr_list_insert(attrs, a); } } if (GetUnderlined()) { a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); pango_attr_list_insert(attrs, a); } if (GetStrikethrough()) { a = pango_attr_strikethrough_new(true); pango_attr_list_insert(attrs, a); } pango_layout_set_attributes(layout, attrs); pango_attr_list_unref(attrs); return true; }
static IgtkFont* gtkFindFont(const char *standardfont) { PangoFontMetrics* metrics; PangoFontDescription* fontdesc; int i, is_underline = 0, is_strikeout = 0, count = iupArrayCount(gtk_fonts); IgtkFont* fonts = (IgtkFont*)iupArrayGetData(gtk_fonts); /* Check if the standardfont already exists in cache */ for (i = 0; i < count; i++) { if (iupStrEqualNoCase(standardfont, fonts[i].standardfont)) return &fonts[i]; } /* not found, create a new one */ { int size; int is_bold = 0, is_italic = 0; char typeface[1024]; char *new_standardfont = NULL; const char* mapped_name; if (!iupFontParsePango(standardfont, typeface, &size, &is_bold, &is_italic, &is_underline, &is_strikeout)) return NULL; mapped_name = iupFontGetPangoName(typeface); if (mapped_name) strcpy(typeface, mapped_name); if (is_underline || is_strikeout || size<0) new_standardfont = iupStrDup(standardfont); if (is_underline) { char* under = strstr(standardfont, "Underline"); int len = strlen(standardfont); int len1 = (size_t)(under-standardfont); memcpy(new_standardfont, standardfont, len1); memcpy(new_standardfont+len1, under+9+1, len-len1-9+1); /* strlen("Underline") */ standardfont = new_standardfont; } if (is_strikeout) { char* strike = strstr(standardfont, "Strikeout"); int len = strlen(standardfont); int len1 = (size_t)(strike-standardfont); memcpy(new_standardfont, standardfont, len1); memcpy(new_standardfont+len1, strike+9+1, len-len1-9+1); /* strlen("Strikeout") */ standardfont = new_standardfont; } if (size<0) { double res; int len1, len2; char *sz, size_str[10]; sprintf(size_str, "%d", size); sz = strstr(standardfont, size_str); len1 = (size_t)(sz-standardfont); res = ((double)gdk_screen_get_width(gdk_screen_get_default()) / (double)gdk_screen_get_width_mm(gdk_screen_get_default())); /* pixels/mm */ /* 1 point = 1/72 inch 1 inch = 25.4 mm */ /* pixel = ((point/72)*25.4)*pixel/mm */ size = (int)((-size/res)*2.83464567 + 0.5); /* from pixels to points */ len2 = sprintf(size_str, "%d", size); memcpy(new_standardfont, standardfont, len1); memcpy(new_standardfont+len1, size_str, len2+1); } fontdesc = pango_font_description_from_string(standardfont); if (new_standardfont) free(new_standardfont); } if (!fontdesc) return NULL; /* create room in the array */ fonts = (IgtkFont*)iupArrayInc(gtk_fonts); strcpy(fonts[i].standardfont, standardfont); fonts[i].fontdesc = fontdesc; fonts[i].strikethrough = pango_attr_strikethrough_new(is_strikeout? TRUE: FALSE); fonts[i].underline = pango_attr_underline_new(is_underline? PANGO_UNDERLINE_SINGLE: PANGO_UNDERLINE_NONE); fonts[i].layout = pango_layout_new(gtk_fonts_context); metrics = pango_context_get_metrics(gtk_fonts_context, fontdesc, pango_context_get_language(gtk_fonts_context)); fonts[i].charheight = pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics); fonts[i].charheight = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charheight); fonts[i].charwidth = pango_font_metrics_get_approximate_char_width(metrics); fonts[i].charwidth = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charwidth); pango_font_metrics_unref(metrics); gtkFontUpdate(&(fonts[i])); return &fonts[i]; }
PangoLayout* gdip_pango_setup_layout (GpGraphics *graphics, GDIPCONST WCHAR *stringUnicode, int length, GDIPCONST GpFont *font, GDIPCONST RectF *rc, RectF *box, GDIPCONST GpStringFormat *format, int **charsRemoved) { GpStringFormat *fmt; PangoLayout *layout; PangoContext *context; PangoRectangle logical; /* logical size of text (used for alignment) */ PangoRectangle ink; /* ink size of text (to pixel boundaries) */ PangoAttrList *list = NULL; GString *ftext; PangoTabArray *tabs; PangoLayoutIter *iter; int i; int FrameWidth; /* rc->Width (or rc->Height if vertical) */ int FrameHeight; /* rc->Height (or rc->Width if vertical) */ int FrameX; /* rc->X (or rc->Y if vertical) */ int FrameY; /* rc->Y (or rc->X if vertical) */ int y0; /* y0,y1,clipNN used for checking line positions vs. clip rectangle */ int y1; double clipx1; double clipx2; double clipy1; double clipy2; int trimSpace; /* whether or not to trim the space */ gchar *text = ucs2_to_utf8 (stringUnicode, length); if (!text) return NULL; length = strlen(text); if (charsRemoved) { (*charsRemoved) = GdipAlloc (sizeof (int) * length); if (!*charsRemoved) { GdipFree (text); return NULL; } memset (*charsRemoved, 0, sizeof (int) * length); } /* TODO - Digit substitution */ // g_warning ("layout >%s< (%d) [x %g, y %g, w %g, h %g] [font %s, %g points]", text, length, rc->X, rc->Y, rc->Width, FrameHeight, font->face, font->emSize); /* a NULL format is valid, it means get the generic default values (and free them later) */ if (!format) { GpStatus status = GdipStringFormatGetGenericDefault ((GpStringFormat **)&fmt); if (status != Ok) { GdipFree (text); return NULL; } } else { fmt = (GpStringFormat *)format; } layout = pango_cairo_create_layout (graphics->ct); /* context is owned by Pango (i.e. not referenced counted) do not free */ context = pango_layout_get_context (layout); pango_layout_set_font_description (layout, gdip_get_pango_font_description ((GpFont*) font)); if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { FrameWidth = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Height)); FrameHeight = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Width)); FrameX = SAFE_FLOAT_TO_UINT32 (rc->Y); FrameY = SAFE_FLOAT_TO_UINT32 (rc->X); } else { FrameWidth = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Width)); FrameHeight = MAKE_SAFE_FOR_PANGO (SAFE_FLOAT_TO_UINT32 (rc->Height)); FrameX = SAFE_FLOAT_TO_UINT32 (rc->X); FrameY = SAFE_FLOAT_TO_UINT32 (rc->Y); } //g_warning("FW: %d\tFH: %d", FrameWidth, FrameHeight); if ((FrameWidth <= 0) || (fmt->formatFlags & StringFormatFlagsNoWrap)) { pango_layout_set_width (layout, -1); //g_warning ("Setting width: %d", -1); } else { pango_layout_set_width (layout, FrameWidth * PANGO_SCALE); //g_warning ("Setting width: %d", FrameWidth * PANGO_SCALE); } if ((rc->Width != 0) && (rc->Height != 0) && ((fmt->formatFlags & StringFormatFlagsNoClip) == 0)) { // g_warning ("\tclip [%g %g %g %g]", rc->X, rc->Y, rc->Width, rc->Height); /* We do not call cairo_reset_clip because we want to take previous clipping into account */ /* Use rc instead of frame variables because this is pre-transform */ gdip_cairo_rectangle (graphics, rc->X, rc->Y, rc->Width, rc->Height, TRUE); cairo_clip (graphics->ct); } /* with GDI+ the API not the renderer makes the direction decision */ pango_layout_set_auto_dir (layout, FALSE); if (!(fmt->formatFlags & StringFormatFlagsDirectionRightToLeft) != !(fmt->formatFlags & StringFormatFlagsDirectionVertical)) { pango_context_set_base_dir (context, PANGO_DIRECTION_WEAK_RTL); pango_layout_context_changed (layout); /* horizontal alignment */ switch (fmt->alignment) { case StringAlignmentNear: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; case StringAlignmentCenter: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; case StringAlignmentFar: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; } } else { /* pango default base dir is WEAK_LTR, which is what we want */ /* horizontal alignment */ switch (fmt->alignment) { case StringAlignmentNear: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; case StringAlignmentCenter: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; case StringAlignmentFar: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; } } #ifdef PANGO_VERSION_CHECK #if PANGO_VERSION_CHECK(1,16,0) if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { if (fmt->formatFlags & StringFormatFlagsDirectionRightToLeft) { cairo_rotate (graphics->ct, M_PI/2.0); cairo_translate (graphics->ct, 0, -FrameHeight); pango_cairo_update_context (graphics->ct, context); } else { cairo_rotate (graphics->ct, 3.0*M_PI/2.0); cairo_translate (graphics->ct, -FrameWidth, 0); pango_cairo_update_context (graphics->ct, context); } /* only since Pango 1.16 */ pango_context_set_base_gravity (context, PANGO_GRAVITY_AUTO); pango_context_set_gravity_hint (context, PANGO_GRAVITY_HINT_LINE); pango_layout_context_changed (layout); } #endif #endif /* TODO - StringFormatFlagsDisplayFormatControl scan and replace them ??? */ /* Trimming options seem to apply only to the end of the string - gdi+ will still wrap * with preference to word first, then character. Unfortunately, pango doesn't have * any way to differentiate wrapping behavior from trimming behavior that I could find */ pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); switch (fmt->trimming) { case StringTrimmingNone: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE); break; case StringTrimmingCharacter: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE); break; case StringTrimmingWord: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_NONE); break; case StringTrimmingEllipsisCharacter: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); if (!(fmt->formatFlags & StringFormatFlagsNoWrap)) pango_layout_set_height (layout, FrameHeight == 0 ? G_MAXINT32 : FrameHeight * PANGO_SCALE); break; case StringTrimmingEllipsisWord: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); if (!(fmt->formatFlags & StringFormatFlagsNoWrap)) pango_layout_set_height (layout, FrameHeight == 0 ? G_MAXINT32 : FrameHeight * PANGO_SCALE); break; case StringTrimmingEllipsisPath: pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_MIDDLE); if (!(fmt->formatFlags & StringFormatFlagsNoWrap)) pango_layout_set_height (layout, FrameHeight == 0 ? G_MAXINT32 : FrameHeight * PANGO_SCALE); break; } /* some stuff can only be done by manipulating the attributes (but we can avoid this most of the time) */ if ((fmt->formatFlags & StringFormatFlagsNoFontFallback) || (font->style & (FontStyleUnderline | FontStyleStrikeout))) { list = gdip_get_layout_attributes (layout); /* StringFormatFlagsNoFontFallback */ if (fmt->formatFlags & StringFormatFlagsNoFontFallback) { PangoAttribute *attr = pango_attr_fallback_new (FALSE); attr->start_index = 0; attr->end_index = length; pango_attr_list_insert (list, attr); } if (font->style & FontStyleUnderline) { PangoAttribute *attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); attr->start_index = 0; attr->end_index = length; pango_attr_list_insert (list, attr); } if (font->style & FontStyleStrikeout) { PangoAttribute *attr = pango_attr_strikethrough_new (TRUE); attr->start_index = 0; attr->end_index = length; pango_attr_list_insert (list, attr); } } if (fmt->numtabStops > 0) { float tabPosition; tabs = pango_tab_array_new (fmt->numtabStops, FALSE); tabPosition = fmt->firstTabOffset; for (i = 0; i < fmt->numtabStops; i++) { tabPosition += fmt->tabStops[i]; pango_tab_array_set_tab (tabs, i, PANGO_TAB_LEFT, (gint)min (tabPosition, PANGO_MAX) * PANGO_SCALE); } pango_layout_set_tabs (layout, tabs); pango_tab_array_free (tabs); } //g_warning ("length before ws removal: %d", length); trimSpace = (fmt->formatFlags & StringFormatFlagsMeasureTrailingSpaces) == 0; switch (fmt->hotkeyPrefix) { case HotkeyPrefixHide: /* we need to remove any accelerator from the string */ ftext = gdip_process_string (text, length, 1, trimSpace, NULL, charsRemoved); break; case HotkeyPrefixShow: /* optimization: is seems that we never see the hotkey when using an underline font */ if (font->style & FontStyleUnderline) { /* so don't bother drawing it (and simply add the '&' character) */ ftext = gdip_process_string (text, length, 1, trimSpace, NULL, charsRemoved); } else { /* find accelerator and add attribute to the next character (unless it's the prefix too) */ if (!list) list = gdip_get_layout_attributes (layout); ftext = gdip_process_string (text, length, 1, trimSpace, list, charsRemoved); } break; default: ftext = gdip_process_string (text, length, 0, trimSpace, NULL, charsRemoved); break; } length = ftext->len; //g_warning ("length after ws removal: %d", length); if (list) { pango_layout_set_attributes (layout, list); pango_attr_list_unref (list); } // g_warning("\tftext>%s< (%d)", ftext->str, -1); pango_layout_set_text (layout, ftext->str, ftext->len); GdipFree (text); g_string_free(ftext, TRUE); /* Trim the text after the last line for ease of counting lines/characters */ /* Also prevents drawing whole lines outside the boundaries if NoClip was specified */ /* In case of pre-existing clipping, use smaller of clip rectangle or our specified height */ if (FrameHeight > 0) { cairo_clip_extents (graphics->ct, &clipx1, &clipy1, &clipx2, &clipy2); if (clipy2 > 0 && !(fmt->formatFlags & StringFormatFlagsNoClip)) clipy2 = min (clipy2, FrameHeight + FrameY); else clipy2 = FrameHeight + FrameY; iter = pango_layout_get_iter (layout); do { if (iter == NULL) break; pango_layout_iter_get_line_yrange (iter, &y0, &y1); //g_warning("yrange: %d %d clipy2: %f", y0 / PANGO_SCALE, y1 / PANGO_SCALE, clipy2); /* StringFormatFlagsLineLimit */ if (((fmt->formatFlags & StringFormatFlagsLineLimit) && y1 / PANGO_SCALE > clipy2) || (y0 / PANGO_SCALE > clipy2)) { PangoLayoutLine *line = pango_layout_iter_get_line_readonly (iter); pango_layout_set_text (layout, pango_layout_get_text (layout), line->start_index); break; } } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); } pango_layout_get_pixel_extents (layout, &ink, &logical); // g_warning ("\tlogical\t[x %d, y %d, w %d, h %d][x %d, y %d, w %d, h %d]", logical.x, logical.y, logical.width, logical.height, ink.x, ink.y, ink.width, ink.height); if ((fmt->formatFlags & StringFormatFlagsNoFitBlackBox) == 0) { /* By default don't allow overhang - ink space may be larger than logical space */ if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { box->X = min (ink.y, logical.y); box->Y = min (ink.x, logical.x); box->Height = max (ink.width, logical.width); box->Width = max (ink.height, logical.height); } else { box->X = min (ink.x, logical.x); box->Y = min (ink.y, logical.y); box->Height = max (ink.height, logical.height); box->Width = max (ink.width, logical.width); } } else { /* Allow overhang */ if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { box->X = logical.y; box->Y = logical.x; box->Height = logical.width; box->Width = logical.height; } else { box->X = logical.x; box->Y = logical.y; box->Height = logical.height; box->Width = logical.width; } } // g_warning ("\tbox\t[x %g, y %g, w %g, h %g]", box->X, box->Y, box->Width, box->Height); /* vertical alignment*/ if (fmt->formatFlags & StringFormatFlagsDirectionVertical) { switch (fmt->lineAlignment) { case StringAlignmentNear: break; case StringAlignmentCenter: box->X += (rc->Width - box->Width) / 2; break; case StringAlignmentFar: box->X += (rc->Width - box->Width); break; } } else { switch (fmt->lineAlignment) { case StringAlignmentNear: break; case StringAlignmentCenter: box->Y += (rc->Height - box->Height) / 2; break; case StringAlignmentFar: box->Y += (rc->Height - box->Height); break; } } // g_warning ("va-box\t[x %g, y %g, w %g, h %g]", box->X, box->Y, box->Width, box->Height); pango_cairo_update_layout (graphics->ct, layout); return layout; }
static PangoLayout* create_layout(HippoCanvasText *text, int allocation_width) { HippoCanvasBox *box = HIPPO_CANVAS_BOX(text); PangoLayout *layout; HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(text)); g_return_val_if_fail(box->context != NULL, NULL); layout = hippo_canvas_context_create_layout(box->context); if (box->font_desc) { PangoFontDescription *merged = pango_font_description_copy(hippo_canvas_style_get_font(style)); pango_font_description_merge(merged, box->font_desc, TRUE); pango_layout_set_font_description(layout, merged); pango_font_description_free(merged); } else { pango_layout_set_font_description(layout, hippo_canvas_style_get_font(style)); } { PangoAttrList *attrs; HippoTextDecoration decoration = hippo_canvas_style_get_text_decoration(style); if (text->attributes) attrs = pango_attr_list_copy(text->attributes); else attrs = pango_attr_list_new(); if (ABS(1.0 - text->font_scale) > .000001) { PangoAttribute *attr = pango_attr_scale_new(text->font_scale); attr->start_index = 0; attr->end_index = G_MAXUINT; pango_attr_list_insert(attrs, attr); } if ((decoration & HIPPO_TEXT_DECORATION_UNDERLINE) != 0) { PangoAttribute *attr = pango_attr_underline_new(TRUE); attr->start_index = 0; attr->end_index = G_MAXUINT; pango_attr_list_insert(attrs, attr); } if ((decoration & HIPPO_TEXT_DECORATION_LINE_THROUGH) != 0) { PangoAttribute *attr = pango_attr_strikethrough_new(TRUE); attr->start_index = 0; attr->end_index = G_MAXUINT; pango_attr_list_insert(attrs, attr); } pango_layout_set_attributes(layout, attrs); pango_attr_list_unref(attrs); } if (text->text != NULL) { pango_layout_set_text(layout, text->text, -1); } if (allocation_width >= 0) { int layout_width, layout_height; pango_layout_get_size(layout, &layout_width, &layout_height); layout_width /= PANGO_SCALE; layout_height /= PANGO_SCALE; /* Force layout smaller if required, but we don't want to make * the layout _wider_ because it breaks alignment, so only do * this if required. */ if (layout_width > allocation_width) { pango_layout_set_width(layout, allocation_width * PANGO_SCALE); /* If we set ellipsize, then it overrides wrapping. If we get * too-small allocation for HIPPO_CANVAS_SIZE_FULL_WIDTH, then * we want to ellipsize instead of wrapping. */ if (text->size_mode == HIPPO_CANVAS_SIZE_WRAP_WORD) { pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE); } else { pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); } /* For now if we say ellipsize end, we always just want one line. * Maybe this should be an orthogonal property? */ if (text->size_mode == HIPPO_CANVAS_SIZE_ELLIPSIZE_END) { pango_layout_set_single_paragraph_mode(layout, TRUE); /* Pango's line separator character in this case is ugly, so we * fix it. Not a very efficient approach, but oh well. */ if (text->text != NULL) { char *new_text = remove_newlines(text->text); /* avoid making the layout recompute everything * if we didn't have newlines anyhow */ if (strcmp(text->text, new_text) != 0) { pango_layout_set_text(layout, new_text, -1); } g_free(new_text); } } } } return layout; }
static PangoAttrList* hildon_font_selection_dialog_create_attrlist (HildonFontSelectionDialog *fontsel, guint start_index, guint len) { PangoAttrList *list; PangoAttribute *attr; gint size, position; gboolean family_set, size_set, color_set, bold, bold_set, italic, italic_set, underline, underline_set, strikethrough, strikethrough_set, position_set; GdkColor *color = NULL; gchar *family = NULL; gdouble font_scaling = 1.0; list = pango_attr_list_new (); g_object_get (G_OBJECT (fontsel), "family", &family, "family-set", &family_set, "size", &size, "size-set", &size_set, "color", &color, "color-set", &color_set, "bold", &bold, "bold-set", &bold_set, "italic", &italic, "italic-set", &italic_set, "underline", &underline, "underline-set", &underline_set, "strikethrough", &strikethrough, "strikethrough-set", &strikethrough_set, "position", &position, "position-set", &position_set, "font-scaling", &font_scaling, NULL); /* family */ if (family_set) { attr = pango_attr_family_new (family); add_preview_text_attr (list, attr, start_index, len); } g_free (family); /* size */ if (size_set) { attr = pango_attr_size_new (size * PANGO_SCALE); add_preview_text_attr (list, attr, start_index, len); } /*color*/ if (color_set) { attr = pango_attr_foreground_new (color->red, color->green, color->blue); add_preview_text_attr (list, attr, start_index, len); } if (color != NULL) gdk_color_free (color); /*weight*/ if (bold_set) { if (bold) attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); else attr = pango_attr_weight_new (PANGO_WEIGHT_NORMAL); add_preview_text_attr(list, attr, start_index, len); } /* style */ if (italic_set) { if (italic) attr = pango_attr_style_new (PANGO_STYLE_ITALIC); else attr = pango_attr_style_new (PANGO_STYLE_NORMAL); add_preview_text_attr(list, attr, start_index, len); } /* underline */ if (underline_set) { if (underline) attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); else attr = pango_attr_underline_new (PANGO_UNDERLINE_NONE); add_preview_text_attr(list, attr, start_index, len); } /* strikethrough */ if (strikethrough_set) { if (strikethrough) attr = pango_attr_strikethrough_new (TRUE); else attr = pango_attr_strikethrough_new (FALSE); add_preview_text_attr(list, attr, start_index, len); } /* position */ if (position_set) { switch (position) { case 1: /*super*/ attr = pango_attr_rise_new (SUPERSCRIPT_RISE); break; case -1: /*sub*/ attr = pango_attr_rise_new (SUBSCRIPT_LOW); break; default: /*normal*/ attr = pango_attr_rise_new (0); break; } add_preview_text_attr (list, attr, start_index, len); } /* font scaling for preview */ if (font_scaling) { attr = pango_attr_scale_new(font_scaling); add_preview_text_attr(list, attr, 0, len + start_index); } return list; }
static gboolean span_parse_func (MarkupData *md, OpenTag *tag, const gchar **names, const gchar **values, GMarkupParseContext *context, GError **error) { int line_number, char_number; int i; const char *family = NULL; const char *size = NULL; const char *style = NULL; const char *weight = NULL; const char *variant = NULL; const char *stretch = NULL; const char *desc = NULL; const char *foreground = NULL; const char *background = NULL; const char *underline = NULL; const char *underline_color = NULL; const char *strikethrough = NULL; const char *strikethrough_color = NULL; const char *rise = NULL; const char *letter_spacing = NULL; const char *lang = NULL; const char *fallback = NULL; const char *gravity = NULL; const char *gravity_hint = NULL; g_markup_parse_context_get_position (context, &line_number, &char_number); #define CHECK_DUPLICATE(var) G_STMT_START{ \ if ((var) != NULL) { \ g_set_error (error, G_MARKUP_ERROR, \ G_MARKUP_ERROR_INVALID_CONTENT, \ _("Attribute '%s' occurs twice on <span> tag " \ "on line %d char %d, may only occur once"), \ names[i], line_number, char_number); \ return FALSE; \ }}G_STMT_END #define CHECK_ATTRIBUTE2(var, name) \ if (attr_strcmp (names[i], (name)) == 0) { \ CHECK_DUPLICATE (var); \ (var) = values[i]; \ found = TRUE; \ break; \ } #define CHECK_ATTRIBUTE(var) CHECK_ATTRIBUTE2 (var, G_STRINGIFY (var)) i = 0; while (names[i]) { gboolean found = FALSE; switch (names[i][0]) { case 'f': CHECK_ATTRIBUTE (fallback); CHECK_ATTRIBUTE2(desc, "font"); CHECK_ATTRIBUTE2(desc, "font_desc"); CHECK_ATTRIBUTE2(family, "face"); CHECK_ATTRIBUTE2(family, "font_family"); CHECK_ATTRIBUTE2(size, "font_size"); CHECK_ATTRIBUTE2(stretch, "font_stretch"); CHECK_ATTRIBUTE2(style, "font_style"); CHECK_ATTRIBUTE2(variant, "font_variant"); CHECK_ATTRIBUTE2(weight, "font_weight"); CHECK_ATTRIBUTE (foreground); CHECK_ATTRIBUTE2 (foreground, "fgcolor"); break; case 's': CHECK_ATTRIBUTE (size); CHECK_ATTRIBUTE (stretch); CHECK_ATTRIBUTE (strikethrough); CHECK_ATTRIBUTE (strikethrough_color); CHECK_ATTRIBUTE (style); break; case 'g': CHECK_ATTRIBUTE (gravity); CHECK_ATTRIBUTE (gravity_hint); break; case 'l': CHECK_ATTRIBUTE (lang); CHECK_ATTRIBUTE (letter_spacing); break; case 'u': CHECK_ATTRIBUTE (underline); CHECK_ATTRIBUTE (underline_color); break; default: CHECK_ATTRIBUTE (background); CHECK_ATTRIBUTE2 (background, "bgcolor"); CHECK_ATTRIBUTE2(foreground, "color"); CHECK_ATTRIBUTE (rise); CHECK_ATTRIBUTE (variant); CHECK_ATTRIBUTE (weight); break; } if (!found) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, _("Attribute '%s' is not allowed on the <span> tag " "on line %d char %d"), names[i], line_number, char_number); return FALSE; } ++i; } /* Parse desc first, then modify it with other font-related attributes. */ if (G_UNLIKELY (desc)) { PangoFontDescription *parsed; parsed = pango_font_description_from_string (desc); if (parsed) { add_attribute (tag, pango_attr_font_desc_new (parsed)); if (tag) open_tag_set_absolute_font_size (tag, pango_font_description_get_size (parsed)); pango_font_description_free (parsed); } } if (G_UNLIKELY (family)) { add_attribute (tag, pango_attr_family_new (family)); } if (G_UNLIKELY (size)) { if (g_ascii_isdigit (*size)) { const char *end; gint n; /* cap size from the top at an arbitrary 2048 */ #define MAX_SIZE (2048 * PANGO_SCALE) if ((end = size, !pango_scan_int (&end, &n)) || *end != '\0' || n < 0 || n > MAX_SIZE) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("Value of 'size' attribute on <span> tag on line %d " "could not be parsed; should be an integer less than %d, or a " "string such as 'small', not '%s'"), line_number, MAX_SIZE+1, size); goto error; } add_attribute (tag, pango_attr_size_new (n)); if (tag) open_tag_set_absolute_font_size (tag, n); } else if (strcmp (size, "smaller") == 0) { if (tag) { tag->scale_level_delta -= 1; tag->scale_level -= 1; } } else if (strcmp (size, "larger") == 0) { if (tag) { tag->scale_level_delta += 1; tag->scale_level += 1; } } else if (parse_absolute_size (tag, size)) ; /* nothing */ else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("Value of 'size' attribute on <span> tag on line %d " "could not be parsed; should be an integer, or a " "string such as 'small', not '%s'"), line_number, size); goto error; } } if (G_UNLIKELY (style)) { PangoStyle pango_style; if (pango_parse_style (style, &pango_style, FALSE)) add_attribute (tag, pango_attr_style_new (pango_style)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'style' attribute " "on <span> tag, line %d; valid values are " "'normal', 'oblique', 'italic'"), style, line_number); goto error; } } if (G_UNLIKELY (weight)) { PangoWeight pango_weight; if (pango_parse_weight (weight, &pango_weight, FALSE)) add_attribute (tag, pango_attr_weight_new (pango_weight)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'weight' " "attribute on <span> tag, line %d; valid " "values are for example 'light', 'ultrabold' or a number"), weight, line_number); goto error; } } if (G_UNLIKELY (variant)) { PangoVariant pango_variant; if (pango_parse_variant (variant, &pango_variant, FALSE)) add_attribute (tag, pango_attr_variant_new (pango_variant)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'variant' " "attribute on <span> tag, line %d; valid values are " "'normal', 'smallcaps'"), variant, line_number); goto error; } } if (G_UNLIKELY (stretch)) { PangoStretch pango_stretch; if (pango_parse_stretch (stretch, &pango_stretch, FALSE)) add_attribute (tag, pango_attr_stretch_new (pango_stretch)); else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("'%s' is not a valid value for the 'stretch' " "attribute on <span> tag, line %d; valid " "values are for example 'condensed', " "'ultraexpanded', 'normal'"), stretch, line_number); goto error; } } if (G_UNLIKELY (foreground)) { PangoColor color; if (!span_parse_color ("foreground", foreground, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_foreground_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (background)) { PangoColor color; if (!span_parse_color ("background", background, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_background_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (underline)) { PangoUnderline ul = PANGO_UNDERLINE_NONE; if (!span_parse_enum ("underline", underline, PANGO_TYPE_UNDERLINE, &ul, line_number, error)) goto error; add_attribute (tag, pango_attr_underline_new (ul)); } if (G_UNLIKELY (underline_color)) { PangoColor color; if (!span_parse_color ("underline_color", underline_color, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_underline_color_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (gravity)) { PangoGravity gr = PANGO_GRAVITY_SOUTH; if (!span_parse_enum ("gravity", gravity, PANGO_TYPE_GRAVITY, &gr, line_number, error)) goto error; add_attribute (tag, pango_attr_gravity_new (gr)); } if (G_UNLIKELY (gravity_hint)) { PangoGravityHint hint = PANGO_GRAVITY_HINT_NATURAL; if (!span_parse_enum ("gravity_hint", gravity_hint, PANGO_TYPE_GRAVITY_HINT, &hint, line_number, error)) goto error; add_attribute (tag, pango_attr_gravity_hint_new (hint)); } if (G_UNLIKELY (strikethrough)) { gboolean b = FALSE; if (!span_parse_boolean ("strikethrough", strikethrough, &b, line_number, error)) goto error; add_attribute (tag, pango_attr_strikethrough_new (b)); } if (G_UNLIKELY (strikethrough_color)) { PangoColor color; if (!span_parse_color ("strikethrough_color", strikethrough_color, &color, line_number, error)) goto error; add_attribute (tag, pango_attr_strikethrough_color_new (color.red, color.green, color.blue)); } if (G_UNLIKELY (fallback)) { gboolean b = FALSE; if (!span_parse_boolean ("fallback", fallback, &b, line_number, error)) goto error; add_attribute (tag, pango_attr_fallback_new (b)); } if (G_UNLIKELY (rise)) { gint n = 0; if (!span_parse_int ("rise", rise, &n, line_number, error)) goto error; add_attribute (tag, pango_attr_rise_new (n)); } if (G_UNLIKELY (letter_spacing)) { gint n = 0; if (!span_parse_int ("letter_spacing", letter_spacing, &n, line_number, error)) goto error; add_attribute (tag, pango_attr_letter_spacing_new (n)); } if (G_UNLIKELY (lang)) { add_attribute (tag, pango_attr_language_new (pango_language_from_string (lang))); } return TRUE; error: return FALSE; }
/** * gimp_label_set_attributes: * @label: a #GtkLabel * @...: a list of PangoAttrType and value pairs terminated by -1. * * Sets Pango attributes on a #GtkLabel in a more convenient way than * gtk_label_set_attributes(). * * This function is useful if you want to change the font attributes * of a #GtkLabel. This is an alternative to using PangoMarkup which * is slow to parse and akward to handle in an i18n-friendly way. * * The attributes are set on the complete label, from start to end. If * you need to set attributes on part of the label, you will have to * use the PangoAttributes API directly. * * Since: 2.2 **/ void gimp_label_set_attributes (GtkLabel *label, ...) { PangoAttribute *attr = NULL; PangoAttrList *attrs; va_list args; g_return_if_fail (GTK_IS_LABEL (label)); attrs = pango_attr_list_new (); va_start (args, label); do { PangoAttrType attr_type = va_arg (args, PangoAttrType); if (attr_type == -1) attr_type = PANGO_ATTR_INVALID; switch (attr_type) { case PANGO_ATTR_LANGUAGE: attr = pango_attr_language_new (va_arg (args, PangoLanguage *)); break; case PANGO_ATTR_FAMILY: attr = pango_attr_family_new (va_arg (args, const gchar *)); break; case PANGO_ATTR_STYLE: attr = pango_attr_style_new (va_arg (args, PangoStyle)); break; case PANGO_ATTR_WEIGHT: attr = pango_attr_weight_new (va_arg (args, PangoWeight)); break; case PANGO_ATTR_VARIANT: attr = pango_attr_variant_new (va_arg (args, PangoVariant)); break; case PANGO_ATTR_STRETCH: attr = pango_attr_stretch_new (va_arg (args, PangoStretch)); break; case PANGO_ATTR_SIZE: attr = pango_attr_size_new (va_arg (args, gint)); break; case PANGO_ATTR_FONT_DESC: attr = pango_attr_font_desc_new (va_arg (args, const PangoFontDescription *)); break; case PANGO_ATTR_FOREGROUND: { const PangoColor *color = va_arg (args, const PangoColor *); attr = pango_attr_foreground_new (color->red, color->green, color->blue); } break; case PANGO_ATTR_BACKGROUND: { const PangoColor *color = va_arg (args, const PangoColor *); attr = pango_attr_background_new (color->red, color->green, color->blue); } break; case PANGO_ATTR_UNDERLINE: attr = pango_attr_underline_new (va_arg (args, PangoUnderline)); break; case PANGO_ATTR_STRIKETHROUGH: attr = pango_attr_strikethrough_new (va_arg (args, gboolean)); break; case PANGO_ATTR_RISE: attr = pango_attr_rise_new (va_arg (args, gint)); break; case PANGO_ATTR_SCALE: attr = pango_attr_scale_new (va_arg (args, gdouble)); break; default: g_warning ("%s: invalid PangoAttribute type %d", G_STRFUNC, attr_type); case PANGO_ATTR_INVALID: attr = NULL; break; } if (attr) { attr->start_index = 0; attr->end_index = -1; pango_attr_list_insert (attrs, attr); } } while (attr); va_end (args); gtk_label_set_attributes (label, attrs); pango_attr_list_unref (attrs); }
/* This function is used by gtk_text_cell_accessible_get_offset_at_point() * and gtk_text_cell_accessible_get_character_extents(). There is no * cached PangoLayout so we must create a temporary one using this function. */ static PangoLayout * create_pango_layout (GtkTextCellAccessible *text) { GdkRGBA *foreground_rgba; PangoAttrList *attr_list, *attributes; PangoLayout *layout; PangoUnderline uline, underline; PangoFontMask mask; PangoFontDescription *font_desc; gboolean foreground_set, strikethrough_set, strikethrough; gboolean scale_set, underline_set, rise_set; gchar *renderer_text; gdouble scale; gint rise; GtkRendererCellAccessible *gail_renderer; GtkCellRendererText *gtk_renderer; gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text); gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer); g_object_get (gtk_renderer, "text", &renderer_text, "attributes", &attributes, "foreground-set", &foreground_set, "foreground-rgba", &foreground_rgba, "strikethrough-set", &strikethrough_set, "strikethrough", &strikethrough, "font-desc", &font_desc, "scale-set", &scale_set, "scale", &scale, "underline-set", &underline_set, "underline", &underline, "rise-set", &rise_set, "rise", &rise, NULL); layout = gtk_widget_create_pango_layout (get_widget (text), renderer_text); if (attributes) attr_list = pango_attr_list_copy (attributes); else attr_list = pango_attr_list_new (); if (foreground_set) { add_attr (attr_list, pango_attr_foreground_new (foreground_rgba->red * 65535, foreground_rgba->green * 65535, foreground_rgba->blue * 65535)); } if (strikethrough_set) add_attr (attr_list, pango_attr_strikethrough_new (strikethrough)); mask = pango_font_description_get_set_fields (font_desc); if (mask & PANGO_FONT_MASK_FAMILY) add_attr (attr_list, pango_attr_family_new (pango_font_description_get_family (font_desc))); if (mask & PANGO_FONT_MASK_STYLE) add_attr (attr_list, pango_attr_style_new (pango_font_description_get_style (font_desc))); if (mask & PANGO_FONT_MASK_VARIANT) add_attr (attr_list, pango_attr_variant_new (pango_font_description_get_variant (font_desc))); if (mask & PANGO_FONT_MASK_WEIGHT) add_attr (attr_list, pango_attr_weight_new (pango_font_description_get_weight (font_desc))); if (mask & PANGO_FONT_MASK_STRETCH) add_attr (attr_list, pango_attr_stretch_new (pango_font_description_get_stretch (font_desc))); if (mask & PANGO_FONT_MASK_SIZE) add_attr (attr_list, pango_attr_size_new (pango_font_description_get_size (font_desc))); if (scale_set && scale != 1.0) add_attr (attr_list, pango_attr_scale_new (scale)); if (underline_set) uline = underline; else uline = PANGO_UNDERLINE_NONE; if (uline != PANGO_UNDERLINE_NONE) add_attr (attr_list, pango_attr_underline_new (underline)); if (rise_set) add_attr (attr_list, pango_attr_rise_new (rise)); pango_layout_set_attributes (layout, attr_list); pango_layout_set_width (layout, -1); pango_attr_list_unref (attr_list); pango_font_description_free (font_desc); pango_attr_list_unref (attributes); g_free (renderer_text); gdk_rgba_free (foreground_rgba); return layout; }
static IgtkFont* gtkFindFont(const char *standardfont) { PangoFontMetrics* metrics; PangoFontDescription* fontdesc; int i, is_underline = 0, is_strikeout = 0, count = iupArrayCount(gtk_fonts); IgtkFont* fonts = (IgtkFont*)iupArrayGetData(gtk_fonts); /* Check if the standardfont already exists in cache */ for (i = 0; i < count; i++) { if (iupStrEqualNoCase(standardfont, fonts[i].standardfont)) return &fonts[i]; } /* not found, create a new one */ { int size = 0, is_pango = 0; int is_bold = 0, is_italic = 0; char typeface[1024]; const char* mapped_name; /* parse the old Windows format first */ if (!iupFontParseWin(standardfont, typeface, &size, &is_bold, &is_italic, &is_underline, &is_strikeout)) { if (!iupFontParseX(standardfont, typeface, &size, &is_bold, &is_italic, &is_underline, &is_strikeout)) { if (!iupFontParsePango(standardfont, typeface, &size, &is_bold, &is_italic, &is_underline, &is_strikeout)) return NULL; else is_pango = 1; } } mapped_name = iupFontGetPangoName(typeface); if (mapped_name) strcpy(typeface, mapped_name); if (is_pango && !is_underline && !is_strikeout && size>0) fontdesc = pango_font_description_from_string(standardfont); else { char new_standardfont[200]; if (size<0) { double res = ((double)gdk_screen_get_width(gdk_screen_get_default()) / (double)gdk_screen_get_width_mm(gdk_screen_get_default())); /* pixels/mm */ /* 1 point = 1/72 inch 1 inch = 25.4 mm */ /* pixel = ((point/72)*25.4)*pixel/mm */ size = (int)((-size/res)*2.83464567 + 0.5); /* from pixels to points */ } sprintf(new_standardfont, "%s, %s%s%d", typeface, is_bold?"Bold ":"", is_italic?"Italic ":"", size); fontdesc = pango_font_description_from_string(new_standardfont); } } if (!fontdesc) return NULL; /* create room in the array */ fonts = (IgtkFont*)iupArrayInc(gtk_fonts); strcpy(fonts[i].standardfont, standardfont); fonts[i].fontdesc = fontdesc; fonts[i].strikethrough = pango_attr_strikethrough_new(is_strikeout? TRUE: FALSE); fonts[i].underline = pango_attr_underline_new(is_underline? PANGO_UNDERLINE_SINGLE: PANGO_UNDERLINE_NONE); fonts[i].layout = pango_layout_new(gtk_fonts_context); metrics = pango_context_get_metrics(gtk_fonts_context, fontdesc, pango_context_get_language(gtk_fonts_context)); fonts[i].charheight = pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics); fonts[i].charheight = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charheight); fonts[i].charwidth = pango_font_metrics_get_approximate_char_width(metrics); fonts[i].charwidth = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charwidth); pango_font_metrics_unref(metrics); gtkFontUpdate(&(fonts[i])); return &fonts[i]; }