Graphviz 16.0.0~dev.20260810.2334
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
18#include "gvplugin_gdiplus.h"
19
20using namespace Gdiplus;
21
22static int CALLBACK fetch_first_font(const LOGFONTA *logFont,
23 const TEXTMETRICA *, DWORD, LPARAM lParam)
24{
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{
32 /* convert incoming UTF8 string to wide chars */
33 /* NOTE: conversion is 1 or more UTF8 chars to 1 wide char */
34 int len = strlen(string);
35 text.resize(len);
36 text.resize(MultiByteToWideChar(CP_UTF8, 0, string, len, &text[0], len));
37
38 /* search for a font with this name. if we can't find it, use the generic serif instead */
39 /* NOTE: GDI font search is more comprehensive than GDI+ and will look for variants e.g. Arial Bold */
40 DeviceContext reference;
41 LOGFONTA font_to_find;
42 font_to_find.lfCharSet = ANSI_CHARSET;
43 size_t font_len = strlen(fontname);
44 if (font_len > sizeof(font_to_find.lfFaceName) - 1) {
45 font_len = sizeof(font_to_find.lfFaceName) - 1;
46 }
47 memcpy(font_to_find.lfFaceName, fontname, font_len);
48 font_to_find.lfFaceName[sizeof(font_to_find.lfFaceName) - 1] = '\0';
49 font_to_find.lfPitchAndFamily = 0;
50 LOGFONTA found_font;
51 if (EnumFontFamiliesExA(reference.hdc,
52 &font_to_find,
54 (LPARAM)&found_font,
55 0) == 0) {
56 found_font.lfHeight = (LONG)-fontsize;
57 found_font.lfWidth = 0;
58 font = std::make_unique<Font>(reference.hdc, &found_font);
59 }
60 else
61 font = std::make_unique<Font>(FontFamily::GenericSerif(), fontsize);
62}
63
65{
66 if (layout)
67 delete reinterpret_cast<Layout*>(layout);
68};
69
70bool gdiplus_textlayout(textspan_t *span, char **)
71{
72 /* ensure GDI+ is started up: since we get called outside of a job, we can't rely on GDI+ startup then */
73 UseGdiplus();
74
75 Layout* layout = new Layout(span->font->name, span->font->size, span->str);
76
77 /* measure the text */
78 /* NOTE: use TextRenderingHintAntiAlias + GetGenericTypographic to get a layout without extra space at beginning and end */
79 RectF boundingBox;
80 DeviceContext deviceContext;
81 Graphics measureGraphics(deviceContext.hdc);
82 measureGraphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
83 measureGraphics.MeasureString(
84 &layout->text[0],
85 layout->text.size(),
86 layout->font.get(),
87 PointF(0.0f, 0.0f),
89 &boundingBox);
90
91 FontFamily fontFamily;
92 layout->font->GetFamily(&fontFamily);
93 int style = layout->font->GetStyle();
94
95 span->layout = layout;
97 span->size.x = boundingBox.Width;
98 span->size.y = layout->font->GetHeight(&measureGraphics);
99 span->yoffset_layout = fontFamily.GetCellAscent(style) * span->font->size / fontFamily.GetEmHeight(style); /* convert design units to pixels */
100 span->yoffset_centerline = 0;
101 return true;
102};
103
107
109 {0, "textlayout", 8, &gdiplus_textlayout_engine, nullptr},
110 {0, nullptr, 0, nullptr, nullptr}
111};
static double len(glCompPoint p)
Definition glutils.c:138
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