Graphviz 12.0.1~dev.20240716.0800
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 v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.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 strncpy(font_to_find.lfFaceName, fontname, sizeof(font_to_find.lfFaceName) - 1);
44 font_to_find.lfFaceName[sizeof(font_to_find.lfFaceName) - 1] = '\0';
45 font_to_find.lfPitchAndFamily = 0;
46 LOGFONTA found_font;
47 if (EnumFontFamiliesExA(reference.hdc,
48 &font_to_find,
50 (LPARAM)&found_font,
51 0) == 0) {
52 found_font.lfHeight = (LONG)-fontsize;
53 found_font.lfWidth = 0;
54 font = std::make_unique<Font>(reference.hdc, &found_font);
55 }
56 else
57 font = std::make_unique<Font>(FontFamily::GenericSerif(), fontsize);
58}
59
61{
62 if (layout)
63 delete reinterpret_cast<Layout*>(layout);
64};
65
66bool gdiplus_textlayout(textspan_t *span, char **)
67{
68 /* ensure GDI+ is started up: since we get called outside of a job, we can't rely on GDI+ startup then */
69 UseGdiplus();
70
71 Layout* layout = new Layout(span->font->name, span->font->size, span->str);
72
73 /* measure the text */
74 /* NOTE: use TextRenderingHintAntiAlias + GetGenericTypographic to get a layout without extra space at beginning and end */
75 RectF boundingBox;
76 DeviceContext deviceContext;
77 Graphics measureGraphics(deviceContext.hdc);
78 measureGraphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
79 measureGraphics.MeasureString(
80 &layout->text[0],
81 layout->text.size(),
82 layout->font.get(),
83 PointF(0.0f, 0.0f),
85 &boundingBox);
86
87 FontFamily fontFamily;
88 layout->font->GetFamily(&fontFamily);
89 int style = layout->font->GetStyle();
90
91 span->layout = layout;
93 span->size.x = boundingBox.Width;
94 span->size.y = layout->font->GetHeight(&measureGraphics);
95 span->yoffset_layout = fontFamily.GetCellAscent(style) * span->font->size / fontFamily.GetEmHeight(style); /* convert design units to pixels */
96 span->yoffset_centerline = 0;
97 return true;
98};
99
103
105 {0, "textlayout", 8, &gdiplus_textlayout_engine, nullptr},
106 {0, nullptr, 0, nullptr, nullptr}
107};
static double len(glCompPoint p)
Definition glutils.c:150
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)
Definition layout.c:809
#define CALLBACK
Definition polytess.c:18
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:54
double size
Definition textspan.h:57
double yoffset_layout
Definition textspan.h:69
char * str
Definition textspan.h:65
void * layout
Definition textspan.h:67
pointf size
Definition textspan.h:70
textfont_t * font
Definition textspan.h:66
double yoffset_centerline
Definition textspan.h:69
void(* free_layout)(void *layout)
Definition textspan.h:68