static void set_font(DiaRenderer *self, DiaFont *font, real height) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); /* pango/cairo wants the font size, not the (line-) height */ real size = dia_font_get_size (font) * (height / dia_font_get_height (font)); PangoFontDescription *pfd = pango_font_description_copy (dia_font_get_description (font)); DIAG_NOTE(g_message("set_font %f %s", height, dia_font_get_family(font))); #ifdef HAVE_PANGOCAIRO_H /* select font and size */ pango_font_description_set_absolute_size (pfd, (int)(size * PANGO_SCALE)); pango_layout_set_font_description (renderer->layout, pfd); pango_font_description_free (pfd); #else if (renderer->cr) { DiaFontStyle style = dia_font_get_style (font); const char *family_name = dia_font_get_family(font); cairo_select_font_face ( renderer->cr, family_name, DIA_FONT_STYLE_GET_SLANT(style) == DIA_FONT_NORMAL ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_SLANT_ITALIC, DIA_FONT_STYLE_GET_WEIGHT(style) < DIA_FONT_MEDIUM ? CAIRO_FONT_WEIGHT_NORMAL : CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (renderer->cr, size); DIAG_STATE(renderer->cr) }
G_CONST_RETURN char* dia_font_get_legacy_name(const DiaFont *font) { const char* matched_name = NULL; const char* family; DiaFontStyle style; int i; /* if we have loaded it from an old file, use the old name */ if (font->legacy_name) return font->legacy_name; family = dia_font_get_family (font); style = dia_font_get_style (font); for (i = 0; i < G_N_ELEMENTS(legacy_fonts); i++) { if (0 == g_ascii_strcasecmp (legacy_fonts[i].newname, family)) { /* match weight and slant */ DiaFontStyle st = legacy_fonts[i].style; if ((DIA_FONT_STYLE_GET_SLANT(style) | DIA_FONT_STYLE_GET_WEIGHT(style)) == (DIA_FONT_STYLE_GET_SLANT(st) | DIA_FONT_STYLE_GET_WEIGHT(st))) { return legacy_fonts[i].oldname; /* exact match */ } else if (0 == (DIA_FONT_STYLE_GET_SLANT(st) | DIA_FONT_STYLE_GET_WEIGHT(st))) { matched_name = legacy_fonts[i].oldname; /* 'unmodified' font, continue matching */ } } } return matched_name ? matched_name : "Courier"; }
static void draw_text_line(DiaRenderer *self, TextLine *text_line, Point *pos, Alignment alignment, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; char *style, *tmp; real saved_width; gchar d_buf[DTOSTR_BUF_SIZE]; DiaFont *font; node = xmlNewTextChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"text", (xmlChar *) text_line_get_string(text_line)); saved_width = renderer->linewidth; renderer->linewidth = 0.001; style = (char*)get_fill_style(renderer, colour); /* return value must not be freed */ renderer->linewidth = saved_width; tmp = g_strdup_printf("%s; font-size: %s", style, dia_svg_dtostr(d_buf, text_line_get_height(text_line))); style = tmp; /* This is going to break for non-LTR texts, as SVG thinks 'start' is * 'right' for those. */ switch (alignment) { case ALIGN_LEFT: tmp = g_strconcat(style, "; text-anchor:start", NULL); break; case ALIGN_CENTER: tmp = g_strconcat(style, "; text-anchor:middle", NULL); break; case ALIGN_RIGHT: tmp = g_strconcat(style, "; text-anchor:end", NULL); break; } g_free (style); style = tmp; font = text_line_get_font(text_line); tmp = g_strdup_printf("%s; font-family: %s; font-style: %s; " "font-weight: %s",style, dia_font_get_family(font), dia_font_get_slant_string(font), dia_font_get_weight_string(font)); g_free(style); style = tmp; /* have to do something about fonts here ... */ xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) style); g_free(style); dia_svg_dtostr(d_buf, pos->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, pos->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, text_line_get_width(text_line)); xmlSetProp(node, (const xmlChar*)"textLength", (xmlChar *) d_buf); }
DiaFont* dia_font_copy(const DiaFont* font) { if (!font) return NULL; return dia_font_new(dia_font_get_family(font), dia_font_get_style(font), dia_font_get_height(font)); }
/*! * \brief Add font data to an attribute node. * @param attr The attribute node. * @param font The value to set. * \ingroup DiagramXmlOut */ void data_add_font(AttributeNode attr, const DiaFont *font, DiaContext *ctx) { DataNode data_node; char buffer[20+1]; /* Enought for 64bit int + zero */ data_node = xmlNewChild(attr, NULL, (const xmlChar *)"font", NULL); xmlSetProp(data_node, (const xmlChar *)"family", (xmlChar *) dia_font_get_family(font)); g_snprintf(buffer, 20, "%d", dia_font_get_style(font)); xmlSetProp(data_node, (const xmlChar *)"style", (xmlChar *) buffer); /* Legacy support: don't crash older Dia on missing 'name' attribute */ xmlSetProp(data_node, (const xmlChar *)"name", (xmlChar *) dia_font_get_legacy_name(font)); }
static void dia_font_check_for_font(int font) { DiaFont *check; PangoFont *loaded; static real height = 1.0; check = dia_font_new_from_style(font, height); loaded = pango_context_load_font(dia_font_get_context(), check->pfd); if (!loaded) { message_error(_("Can't load font %s.\n"), dia_font_get_family(check)); } else { g_object_unref (loaded); } }
static void set_font(DiaRenderer *self, DiaFont *font, real height) { DrsRenderer *renderer = DRS_RENDERER (self); xmlNodePtr node; const PangoFontDescription *pfd = dia_font_get_description (font); char *desc = pango_font_description_to_string (pfd); node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"set-font", NULL); xmlSetProp(node, (const xmlChar *)"description", (xmlChar *)desc); xmlSetProp(node, (const xmlChar *)"family", (xmlChar *)dia_font_get_family (font)); xmlSetProp(node, (const xmlChar *)"weight", (xmlChar *)dia_font_get_weight_string (font)); xmlSetProp(node, (const xmlChar *)"slant", (xmlChar *)dia_font_get_slant_string (font)); _node_set_real (node, "size", dia_font_get_size (font)); _node_set_real (node, "height", height); g_free(desc); }
static void set_font(DiaRenderer *self, DiaFont *font, real height) { WpgRenderer *renderer = WPG_RENDERER (self); /* FIXME PANGO: this is a little broken. Use better matching. */ const char *family_name; DIAG_NOTE(g_message("set_font %f %s", height, font->name)); renderer->TextStyle.Height = SC(height); family_name = dia_font_get_family(font); if ((strstr(family_name, "courier")) || (strstr(family_name, "monospace"))) renderer->TextStyle.Font = 0x0DF0; else if ((strstr(family_name, "times")) || (strstr(family_name, "serif"))) renderer->TextStyle.Font = 0x1950; else renderer->TextStyle.Font = 0x1150; /* Helv */ }
static void set_font(DiaRenderer *self, DiaFont *font, real height) { WmfRenderer *renderer = WMF_RENDERER (self); W32::LPCTSTR sFace; W32::DWORD dwItalic = 0; W32::DWORD dwWeight = FW_DONTCARE; DiaFontStyle style = dia_font_get_style(font); real font_size = dia_font_get_size (font) * (height / dia_font_get_height (font)); DIAG_NOTE(renderer, "set_font %s %f\n", dia_font_get_family (font), height); if (renderer->hFont) { W32::DeleteObject(renderer->hFont); renderer->hFont = NULL; } if (renderer->pango_context) { g_object_unref (renderer->pango_context); renderer->pango_context = NULL; } if (renderer->use_pango) { #ifdef __PANGOWIN32_H__ /* with the pangowin32 backend there is a better way */ if (!renderer->pango_context) renderer->pango_context = pango_win32_get_context (); PangoFont* pf = pango_context_load_font (renderer->pango_context, dia_font_get_description (font)); if (pf) { W32::LOGFONT* lf = pango_win32_font_logfont (pf); /* .93 : sligthly smaller looks much better */ lf->lfHeight = -SC(height*.93); lf->lfHeight = -SC(font_size); renderer->hFont = (W32::HFONT)W32::CreateFontIndirect (lf); g_free (lf); g_object_unref (pf); } else { gchar *desc = pango_font_description_to_string (dia_font_get_description (font)); dia_context_add_message(renderer->ctx, _("Cannot render unknown font:\n%s"), desc); g_free (desc); } #else g_assert_not_reached(); #endif } else { sFace = dia_font_get_family (font); dwItalic = DIA_FONT_STYLE_GET_SLANT(style) != DIA_FONT_NORMAL; /* although there is a known algorithm avoid it for cleanness */ switch (DIA_FONT_STYLE_GET_WEIGHT(style)) { case DIA_FONT_ULTRALIGHT : dwWeight = FW_ULTRALIGHT; break; case DIA_FONT_LIGHT : dwWeight = FW_LIGHT; break; case DIA_FONT_MEDIUM : dwWeight = FW_MEDIUM; break; case DIA_FONT_DEMIBOLD : dwWeight = FW_DEMIBOLD; break; case DIA_FONT_BOLD : dwWeight = FW_BOLD; break; case DIA_FONT_ULTRABOLD : dwWeight = FW_ULTRABOLD; break; case DIA_FONT_HEAVY : dwWeight = FW_HEAVY; break; default : dwWeight = FW_NORMAL; break; } //Hack to get BYTE out of namespace W32 # ifndef BYTE # define BYTE unsigned char # endif renderer->hFont = (W32::HFONT)W32::CreateFont( - SC (font_size), // logical height of font 0, // logical average character width 0, // angle of escapement 0, // base-line orientation angle dwWeight, // font weight dwItalic, // italic attribute flag 0, // underline attribute flag 0, // strikeout attribute flag DEFAULT_CHARSET, // character set identifier OUT_TT_PRECIS, // output precision CLIP_DEFAULT_PRECIS, // clipping precision PROOF_QUALITY, // output quality DEFAULT_PITCH, // pitch and family sFace); // pointer to typeface name string } }
static void draw_text_line(DiaRenderer *self, TextLine *text_line, Point *pos, Alignment alignment, Color *colour) { DiaSvgRenderer *renderer = DIA_SVG_RENDERER (self); xmlNodePtr node; real saved_width; gchar d_buf[DTOSTR_BUF_SIZE]; DiaFont *font; GString *style; node = xmlNewTextChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"text", (xmlChar *) text_line_get_string(text_line)); saved_width = renderer->linewidth; renderer->linewidth = 0.001; /* return value must not be freed */ renderer->linewidth = saved_width; #if 0 /* would need a unit: https://bugzilla.mozilla.org/show_bug.cgi?id=707071#c4 */ style = g_strdup_printf("%s; font-size: %s", get_draw_style(renderer, colour, NULL), dia_svg_dtostr(d_buf, text_line_get_height(text_line))); #else /* get_draw_style: the return value of this function must not be saved * anywhere. And of course it must not be free'd */ style = g_string_new (get_draw_style(renderer, colour, NULL)); #endif /* This is going to break for non-LTR texts, as SVG thinks 'start' is * 'right' for those. */ switch (alignment) { case ALIGN_LEFT: g_string_append (style, "; text-anchor:start"); break; case ALIGN_CENTER: g_string_append (style, "; text-anchor:middle"); break; case ALIGN_RIGHT: g_string_append (style, "; text-anchor:end"); break; default: break; } font = text_line_get_font(text_line); g_string_append_printf (style, "font-family: %s; font-style: %s; font-weight: %s", dia_font_get_family(font), dia_font_get_slant_string(font), dia_font_get_weight_string(font)); xmlSetProp(node, (const xmlChar *)"style", (xmlChar *) style->str); g_string_free (style, TRUE); dia_svg_dtostr(d_buf, pos->x); xmlSetProp(node, (const xmlChar *)"x", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, pos->y); xmlSetProp(node, (const xmlChar *)"y", (xmlChar *) d_buf); /* font-size as single attribute can work like the other length w/o unit */ dia_svg_dtostr(d_buf, text_line_get_height(text_line)); xmlSetProp(node, (const xmlChar *)"font-size", (xmlChar *) d_buf); dia_svg_dtostr(d_buf, text_line_get_width(text_line)); xmlSetProp(node, (const xmlChar*)"textLength", (xmlChar *) d_buf); }
/*! * \brief Object update function called after property change * * Not in the object interface but very important anyway. * Used to recalculate the object data after a change * \protected \memberof Outline */ static void outline_update_data (Outline *outline) { DiaObject *obj = &outline->object; /* calculate the ink_rect from two points and the given rotation */ cairo_t *cr; cairo_surface_t *surface; cairo_text_extents_t extents; real x, y; DiaFontStyle style; if (outline->path) cairo_path_destroy (outline->path); outline->path = NULL; /* surface will not be used to render anything, it is just to create the cairo context */ surface = cairo_svg_surface_create_for_stream (write_nul, NULL, 100, 100); cr = cairo_create (surface); cairo_surface_destroy (surface); /* in fact: unref() */ style = dia_font_get_style (outline->font); /* not exact matching but almost the best we can do with the toy api */ cairo_select_font_face (cr, dia_font_get_family (outline->font), DIA_FONT_STYLE_GET_SLANT (style) == DIA_FONT_NORMAL ? CAIRO_FONT_SLANT_NORMAL : CAIRO_FONT_SLANT_ITALIC, DIA_FONT_STYLE_GET_WEIGHT (style) < DIA_FONT_MEDIUM ? CAIRO_FONT_WEIGHT_NORMAL : CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (cr, outline->font_height); cairo_text_extents (cr, outline->name, &extents); /* unfortunately this has no effect on the returned path? See below. */ cairo_rotate (cr, outline->rotation/(2*G_PI)); outline->mat.xx = cos(G_PI*outline->rotation/180); outline->mat.xy = sin(G_PI*outline->rotation/180); outline->mat.yx = -sin(G_PI*outline->rotation/180); outline->mat.yy = cos(G_PI*outline->rotation/180); /* fix point */ outline->ink_rect[0].x = x = obj->position.x; outline->ink_rect[0].y = y = obj->position.y; /* handle rotation */ outline->ink_rect[1].x = x + extents.width * outline->mat.xx; outline->ink_rect[1].y = y + extents.width * outline->mat.yx; outline->ink_rect[2].x = x + extents.width * outline->mat.xx + extents.height * outline->mat.xy; outline->ink_rect[2].y = y + extents.width * outline->mat.yx + extents.height * outline->mat.yy; outline->ink_rect[3].x = x + extents.height * outline->mat.xy; outline->ink_rect[3].y = y + extents.height * outline->mat.yy; /* x_advance? */ /* calculate bounding box */ { PolyBBExtras bbex = {0, 0, outline->line_width/2, 0, 0 }; polyline_bbox (&outline->ink_rect[0], 4, &bbex, TRUE, &obj->bounding_box); } outline_update_handles (outline), cairo_move_to (cr, -extents.x_bearing, -extents.y_bearing); #if 0 /* reset the matrix to not yet change the outline_draw method */ outline->mat.xx = 1.0; outline->mat.xy = 0.0; outline->mat.yx = 0.0; outline->mat.yy = 1.0; #endif cairo_text_path (cr, outline->name); /* reset the rotation to not have the path rotated back and forth: no effect */ cairo_rotate (cr, 0.0); outline->path = cairo_copy_path (cr); /* the cairo context is only used in this fuinction */ cairo_destroy (cr); }
static void node_set_text_style (xmlNodePtr node, DiaSvgRenderer *renderer, const DiaFont *font, real font_height, Alignment alignment, Color *colour) { char *style, *tmp; real saved_width; gchar d_buf[G_ASCII_DTOSTR_BUF_SIZE]; DiaSvgRendererClass *svg_renderer_class = DIA_SVG_RENDERER_GET_CLASS (renderer); /* SVG font-size is the (line-) height, from SVG Spec: * ... property refers to the size of the font from baseline to baseline when multiple lines of text are set ... so we should be able to use font_height directly instead of: */ real font_size = dia_font_get_size (font) * (font_height / dia_font_get_height (font)); /* ... but at least Inkscape and Firefox would produce the wrong font-size */ const gchar *family = dia_font_get_family(font); saved_width = renderer->linewidth; renderer->linewidth = 0.001; style = (char*)svg_renderer_class->get_fill_style(renderer, colour); /* return value must not be freed */ renderer->linewidth = saved_width; /* This is going to break for non-LTR texts, as SVG thinks 'start' is * 'right' for those. */ switch (alignment) { case ALIGN_LEFT: style = g_strconcat(style, ";text-anchor:start", NULL); break; case ALIGN_CENTER: style = g_strconcat(style, ";text-anchor:middle", NULL); break; case ALIGN_RIGHT: style = g_strconcat(style, ";text-anchor:end", NULL); break; } #if 0 /* would need a unit according to https://bugzilla.mozilla.org/show_bug.cgi?id=707071#c4 */ tmp = g_strdup_printf("%s;font-size:%s", style, dia_svg_dtostr(d_buf, font_size) ); g_free (style); style = tmp; #else /* font-size as attribute can work like the other length w/o unit */ dia_svg_dtostr(d_buf, font_size); xmlSetProp(node, (const xmlChar *)"font-size", (xmlChar *) d_buf); #endif if (font) { tmp = g_strdup_printf("%s;font-family:%s;font-style:%s;" "font-weight:%s",style, strcmp(family, "sans") == 0 ? "sans-serif" : family, dia_font_get_slant_string(font), dia_font_get_weight_string(font)); g_free(style); style = tmp; } /* have to do something about fonts here ... */ xmlSetProp(node, (xmlChar *)"style", (xmlChar *)style); g_free(style); }