Graphviz 16.1.0~dev.20260902.0144
Loading...
Searching...
No Matches
gvtextlayout_gdiplus.cpp
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <memory>
14#include <stdlib.h>
15#include <string.h>
16
17#include "gvplugin_gdiplus.h"
19
20using namespace Gdiplus;
21
22static int CALLBACK fetch_first_font(const LOGFONTA *logFont,
23 const TEXTMETRICA *, DWORD,
24 LPARAM lParam) {
25 /* save the first font we see in the font enumeration */
26 *((LOGFONTA *)lParam) = *logFont;
27 return 0;
28}
29
30Layout::Layout(char *fontname, double fontsize, char *string) {
31 /* convert incoming UTF8 string to wide chars */
32 /* NOTE: conversion is 1 or more UTF8 chars to 1 wide char */
33 int len = strlen(string);
34 text.resize(len);
35 text.resize(MultiByteToWideChar(CP_UTF8, 0, string, len, &text[0], len));
36
37 /* search for a font with this name. if we can't find it, use the generic
38 * serif instead */
39 /* NOTE: GDI font search is more comprehensive than GDI+ and will look for
40 * variants e.g. Arial Bold */
41 DeviceContext reference;
42 LOGFONTA font_to_find;
43 font_to_find.lfCharSet = ANSI_CHARSET;
44 size_t font_len = strlen(fontname);
45 if (font_len > sizeof(font_to_find.lfFaceName) - 1) {
46 font_len = sizeof(font_to_find.lfFaceName) - 1;
47 }
48 memcpy(font_to_find.lfFaceName, fontname, font_len);
49 font_to_find.lfFaceName[sizeof(font_to_find.lfFaceName) - 1] = '\0';
50 font_to_find.lfPitchAndFamily = 0;
51 LOGFONTA found_font;
52 if (EnumFontFamiliesExA(reference.hdc, &font_to_find, fetch_first_font,
53 (LPARAM)&found_font, 0) == 0) {
54 found_font.lfHeight = (LONG)-fontsize;
55 found_font.lfWidth = 0;
56 font = std::make_unique<Font>(reference.hdc, &found_font);
57 } else
58 font = std::make_unique<Font>(FontFamily::GenericSerif(),
59 static_cast<REAL>(fontsize));
60}
61
63 if (layout)
64 delete reinterpret_cast<Layout *>(layout);
65};
66
67bool gdiplus_textlayout(textspan_t *span, char **) {
68 /* ensure GDI+ is started up: since we get called outside of a job, we can't
69 * rely on GDI+ startup then */
70 UseGdiplus();
71
72 Layout *layout = new Layout(span->font->name, span->font->size, span->str);
73
74 /* measure the text */
75 /* NOTE: use TextRenderingHintAntiAlias + GetGenericTypographic to get a
76 * layout without extra space at beginning and end */
77 RectF boundingBox;
78 DeviceContext deviceContext;
79 Graphics measureGraphics(deviceContext.hdc);
80 measureGraphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
81 measureGraphics.MeasureString(&layout->text[0], layout->text.size(),
82 layout->font.get(), PointF(0.0f, 0.0f),
83 GetGenericTypographic(), &boundingBox);
84
85 FontFamily fontFamily;
86 layout->font->GetFamily(&fontFamily);
87 int style = layout->font->GetStyle();
88
89 span->layout = layout;
91 span->size.x = boundingBox.Width;
92 span->size.y = layout->font->GetHeight(&measureGraphics);
93 span->yoffset_layout =
94 fontFamily.GetCellAscent(style) * span->font->size /
95 fontFamily.GetEmHeight(style); /* convert design units to pixels */
96 span->yoffset_centerline = 0;
97 return true;
98};
99
101
103 {0, "textlayout", 8, &gdiplus_textlayout_engine, nullptr},
104 {0, nullptr, 0, nullptr, nullptr}};
static double len(glCompPoint p)
Definition glutils.c:138
#define REAL
Definition gmlparse.h:132
void UseGdiplus()
const Gdiplus::StringFormat * GetGenericTypographic()
static int CALLBACK fetch_first_font(const LOGFONTA *logFont, const TEXTMETRICA *, DWORD, LPARAM lParam)
static gvtextlayout_engine_t gdiplus_textlayout_engine
void gdiplus_free_layout(void *layout)
bool gdiplus_textlayout(textspan_t *span, char **)
gvplugin_installed_t gvtextlayout_gdiplus_types[]
static int layout(graph_t *g, layout_info *infop, size_t *counter)
Definition layout.c:800
#define CALLBACK
Definition polytess.c:20
std::vector< WCHAR > text
std::unique_ptr< Gdiplus::Font > font
Layout(char *fontname, double fontsize, char *string)
ingroup plugin_api
Definition gvplugin.h:35
double x
Definition geom.h:29
double y
Definition geom.h:29
char * name
Definition textspan.h:56
double size
Definition textspan.h:59
double yoffset_layout
Definition textspan.h:72
char * str
Definition textspan.h:68
void * layout
Definition textspan.h:70
pointf size
Definition textspan.h:73
textfont_t * font
Definition textspan.h:69
double yoffset_centerline
Definition textspan.h:72
void(* free_layout)(void *layout)
Definition textspan.h:71