mirror of https://github.com/neutrinolabs/xrdp
Merge pull request #2341 from matt335672/scaled_login_screen
Scaled login screen support
This commit is contained in:
commit
7354eb6060
|
@ -11,7 +11,6 @@ EXTRA_DIST = \
|
|||
astyle_config.as \
|
||||
bootstrap \
|
||||
coding_style.md \
|
||||
fontdump \
|
||||
m4 \
|
||||
vrplayer
|
||||
|
||||
|
@ -57,6 +56,7 @@ SUBDIRS = \
|
|||
$(RFXCODECDIR) \
|
||||
sesman \
|
||||
xrdp \
|
||||
fontutils \
|
||||
keygen \
|
||||
docs \
|
||||
instfiles \
|
||||
|
|
|
@ -124,7 +124,7 @@ pulseaudio modules. The build instructions can be found at wiki.
|
|||
xrdp
|
||||
├── common ······ common code
|
||||
├── docs ········ documentation
|
||||
├── fontdump ···· font dump for Windows
|
||||
├── fontutils ··· font handling utilities
|
||||
├── genkeymap ··· keymap generator
|
||||
├── instfiles ··· installable data file
|
||||
├── keygen ······ xrdp RSA key pair generator
|
||||
|
|
|
@ -91,8 +91,10 @@
|
|||
b = (c) & 0xff; \
|
||||
}
|
||||
/* font macros */
|
||||
#define FONT_DATASIZE(f) \
|
||||
((((f)->height * (((f)->width + 7) / 8)) + 3) & ~3);
|
||||
#define FONT_DATASIZE_FROM_GEOMETRY(width,height) \
|
||||
((((height) * (((width) + 7) / 8)) + 3) & ~3)
|
||||
#define FONT_DATASIZE(f) FONT_DATASIZE_FROM_GEOMETRY((f->width), (f->height))
|
||||
|
||||
/* use crc for bitmap cache lookups */
|
||||
#define USE_CRC
|
||||
|
||||
|
|
|
@ -343,6 +343,13 @@ g_memcpy(void *d_ptr, const void *s_ptr, int size)
|
|||
memcpy(d_ptr, s_ptr, size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
g_memmove(void *d_ptr, const void *s_ptr, int size)
|
||||
{
|
||||
memmove(d_ptr, s_ptr, size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
g_getchar(void)
|
||||
|
|
|
@ -62,6 +62,7 @@ void g_write(const char *format, ...) printflike(1, 2);
|
|||
void g_hexdump(const char *p, int len);
|
||||
void g_memset(void *ptr, int val, int size);
|
||||
void g_memcpy(void *d_ptr, const void *s_ptr, int size);
|
||||
void g_memmove(void *d_ptr, const void *s_ptr, int size);
|
||||
int g_getchar(void);
|
||||
int g_tcp_set_no_delay(int sck);
|
||||
int g_tcp_set_keepalive(int sck);
|
||||
|
|
46
configure.ac
46
configure.ac
|
@ -190,6 +190,8 @@ AM_CONDITIONAL(XRDP_RDPSNDAUDIN, [test x$enable_rdpsndaudin = xyes])
|
|||
|
||||
AC_ARG_WITH(imlib2, AC_HELP_STRING([--with-imlib2=ARG], [imlib2 library to use for non-BMP backgrounds (ARG=yes/no/<abs-path>)]),,)
|
||||
|
||||
AC_ARG_WITH(freetype2, AC_HELP_STRING([--with-freetype2=ARG], [freetype2 library to use for rendering fonts (ARG=yes/no/<abs-path>)]),,)
|
||||
|
||||
# Obsolete options
|
||||
AC_ARG_ENABLE(xrdpdebug, AS_HELP_STRING([--enable-xrdpdebug],
|
||||
[This option is no longer supported - use --enable-devel-all]))
|
||||
|
@ -278,6 +280,41 @@ if test x$use_imlib2 = xyes; then
|
|||
AC_DEFINE([USE_IMLIB2],1, [Compile with imlib2 support])
|
||||
fi
|
||||
|
||||
# Find freetype2
|
||||
case "$with_freetype2" in
|
||||
'' | no) AC_MSG_NOTICE([freetype2 will not be supported])
|
||||
use_freetype2=no
|
||||
;;
|
||||
yes)
|
||||
PKG_CHECK_MODULES([FREETYPE2], [freetype2 >= 2.8],
|
||||
[use_freetype2=yes],
|
||||
[AC_MSG_ERROR([please install libfreetype6-dev or freetype-devel])])
|
||||
;;
|
||||
/*) AC_MSG_CHECKING([for freetype2 in $with_freetype2])
|
||||
if test -d $with_freetype2/lib; then
|
||||
FREETYPE2_LIBS="-L$with_freetype2/lib -llibfreetype"
|
||||
elif test -d $with_freetype2/lib64; then
|
||||
FREETYPE2_LIBS="-L$with_freetype2/lib64 -llibfreetype"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Can't find libfreetype in $with_freetype2])
|
||||
fi
|
||||
|
||||
if test -f $with_freetype2/include/freetype2/ft2build.h; then
|
||||
FREETYPE2_CFLAGS="-I $with_freetype2/include/freetype2"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Can't find $with_freetype2/include/freetype2/ft2build.h])
|
||||
fi
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_SUBST([FREETYPE2_LIBS])
|
||||
AC_SUBST([FREETYPE2_CFLAGS])
|
||||
use_freetype2=yes
|
||||
;;
|
||||
*) AC_MSG_ERROR([--with-freetype2 needs yes/no or absolute path])
|
||||
esac
|
||||
AM_CONDITIONAL([USE_FREETYPE2], [test "x$use_freetype2" = xyes])
|
||||
|
||||
# Check only one auth mechanism is specified, and give it a name
|
||||
auth_cnt=0
|
||||
auth_mech="Builtin"
|
||||
|
@ -494,6 +531,7 @@ AC_CONFIG_FILES([
|
|||
common/Makefile
|
||||
docs/Makefile
|
||||
docs/man/Makefile
|
||||
fontutils/Makefile
|
||||
genkeymap/Makefile
|
||||
instfiles/default/Makefile
|
||||
instfiles/init.d/Makefile
|
||||
|
@ -551,11 +589,9 @@ echo " vsock $enable_vsock"
|
|||
echo " auth mechanism $auth_mech"
|
||||
echo " rdpsndaudin $enable_rdpsndaudin"
|
||||
echo
|
||||
if test x$use_imlib2 = xyes; then
|
||||
echo " with imlib2 yes"
|
||||
else
|
||||
echo " with imlib2 no"
|
||||
fi
|
||||
echo " with imlib2 $use_imlib2"
|
||||
echo " with freetype2 $use_freetype2"
|
||||
|
||||
echo
|
||||
echo " development logging $devel_logging"
|
||||
echo " development streamcheck $devel_streamcheck"
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
if USE_FREETYPE2
|
||||
MKFV1_MAN = xrdp-mkfv1.8
|
||||
else
|
||||
MKFV1_MAN =
|
||||
endif
|
||||
|
||||
man_MANS = \
|
||||
xrdp-dis.1 \
|
||||
sesman.ini.5 \
|
||||
|
@ -8,7 +14,9 @@ man_MANS = \
|
|||
xrdp-keygen.8 \
|
||||
xrdp-sesadmin.8 \
|
||||
xrdp-sesman.8 \
|
||||
xrdp-sesrun.8
|
||||
xrdp-sesrun.8 \
|
||||
xrdp-dumpfv1.8 \
|
||||
$(MKFV1_MAN)
|
||||
|
||||
EXTRA_DIST = $(man_MANS:=.in)
|
||||
|
||||
|
@ -21,6 +29,7 @@ SUBST_VARS = sed \
|
|||
-e 's|@socketdir[@]|$(socketdir)|g' \
|
||||
-e 's|@sesmanruntimedir[@]|$(sesmanruntimedir)|g' \
|
||||
-e 's|@xrdpconfdir[@]|$(sysconfdir)/xrdp|g' \
|
||||
-e 's|@xrdpdatadir[@]|$(datadir)/xrdp|g' \
|
||||
-e 's|@xrdphomeurl[@]|http://www.xrdp.org/|g'
|
||||
|
||||
subst_verbose = $(subst_verbose_@AM_V@)
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
.TH "xrdp-dumpfv1" "8" "@PACKAGE_VERSION@" "xrdp team"
|
||||
.SH NAME
|
||||
xrdp\-dumpfv1 \- Display content of .fv1 font files
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBxrdp-dumpfv1\fR [ options ] fv1_file
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBxrdp\-dumpfv1\fP can be used to display the contents of an fv1 file.
|
||||
|
||||
.SH OPTIONS
|
||||
A summary of options is included below.
|
||||
|
||||
One of \fB\-i\fR, \fB\-t\fR, or \fB\-c\fR must be specified.
|
||||
.TP
|
||||
\fB\-i\fR
|
||||
Displays general information about the fv1 file.
|
||||
|
||||
.TP
|
||||
\fB\-t\fR
|
||||
Displays a CSV table of all the glyphs in the font. This table can be
|
||||
imported into a spreadsheet program for further manipulation.
|
||||
|
||||
.TP
|
||||
\fB\-c\fR <character>
|
||||
Displays detailed information about a particular glyph in the font,
|
||||
including a representation of the bitmap for the glyph.
|
||||
|
||||
Specify the character using one of the following strings:
|
||||
|
||||
\fBU+<hex>\fR - Unicode character, e.g. \fBU+25\fR for a percentage symbol (%).
|
||||
|
||||
\fB@<char>\fR - Unicode character, e.g. \fB@%\fR for a percentage symbol.
|
||||
|
||||
\fBnumber\fR - Unicode value as an integer, e.g. \fB37\fR for a
|
||||
percentage symbol
|
||||
|
||||
Note that the row numbers shown in the font data are relative to the
|
||||
natural font baseline. If comparing two fonts, be aware that when the
|
||||
glyph is drawn, the row number may be affected by the global descender
|
||||
value for the font (displayed with \fB\-i\fR).
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.TP
|
||||
\fBxrdp\-dumpfv1 -i @xrdpdatadir@/sans-10.fv1\fR
|
||||
Displays global information about the sans 10 font file distributed with xrdp.
|
||||
|
||||
.TP
|
||||
\fBxrdp\-dumpfv1 -c @'*' @xrdpdatadir@/sans-10.fv1\fR
|
||||
Displays information about the asterisk symbol in the sans 10 font file distributed with xrdp.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR xrdp\-mkfv1(8).
|
||||
|
||||
More info on \fBxrdp\fR can be found on the
|
||||
.UR @xrdphomeurl@
|
||||
xrdp homepage
|
||||
.UE
|
|
@ -0,0 +1,81 @@
|
|||
.TH "xrdp-mkfv1" "8" "@PACKAGE_VERSION@" "xrdp team"
|
||||
.SH NAME
|
||||
xrdp\-mkfv1 \- Create .fv1 font files from other font files
|
||||
|
||||
.SH SYNOPSIS
|
||||
\fBxrdp-mkfv1\fR [ options ] font_file fv1_file
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBxrdp\-mkfv1\fP can be used to convert a font file such as a TrueType
|
||||
font to a fv1 file.
|
||||
|
||||
.SH OPTIONS
|
||||
A summary of options is included below.
|
||||
|
||||
.TP
|
||||
\fB\-n\fR <font_name>
|
||||
Give the font a name, which is stored in the font header.
|
||||
|
||||
The default is to use the font family name from the source font.
|
||||
|
||||
.TP
|
||||
\fB\-p\fR <number>
|
||||
Set the point size of the font. A fixed DPI value of 96 is used for
|
||||
converting this value into a pixel size.
|
||||
|
||||
The default value for this option is '10'.
|
||||
|
||||
.TP
|
||||
\fB\-m\fR <glyph>
|
||||
Set the limit on the glyphs stored in the font file. The argument is the last
|
||||
glyph stored in the font file.
|
||||
|
||||
Specify the glyph using one of the following strings:
|
||||
|
||||
\fBU+<hex>\fR - Unicode character, e.g. \fBU+25\fR for a percentage symbol (%).
|
||||
|
||||
\fB@<char>\fR - Unicode character, e.g. \fB@%\fR for a percentage symbol.
|
||||
|
||||
\fBnumber\fR - Unicode value as an integer, e.g. \fB37\fR for a
|
||||
percentage symbol
|
||||
|
||||
The default value for this option is 'U+4DFF'.
|
||||
|
||||
.TP
|
||||
\fB\-C\fR
|
||||
When used with the "DejaVu Sans" font at a point-size of 10, a small
|
||||
number of glyphs are assigned a different x-offset than they have
|
||||
when the original Windows font generation program is used.
|
||||
|
||||
This switch can be used to preserve the original x-offsets for glyphs in
|
||||
the range U+0020 - U+00FF when a 10 point DajaVu Sans font is generated.
|
||||
|
||||
Use one of the following arguments to this option:-
|
||||
|
||||
\fBauto\fR - Automatic mode. Offsets are preserved if a "DajaVu Sans" 10-point font is converted.
|
||||
|
||||
\fBon / true / yes\fR - Preserve offsets if automatic font detection does not work.
|
||||
|
||||
\fBoff / false / no\fR - Do not tamper with the offsets generated by the program.
|
||||
|
||||
The default value of this switch is \fRauto\fR.
|
||||
|
||||
To see the effects of this switch, set the \fBMKFV1_LOG_LEVEL\fR environment
|
||||
variable to \fBinfo\fR before running the program.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.TP
|
||||
\fBxrdp-mkfv1 -p18 /path/to/DejaVuSans.ttf ./sans-18.fv1\fR
|
||||
Generate an 18-point Deja Sans font.
|
||||
|
||||
.TP
|
||||
\fBxrdp-mkfv1 -C off -p10 /path/to/DejaVuSans.ttf ./sans-10.fv1\fR
|
||||
Generate a 10-point DajaVu Sans font using natural offsets.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR xrdp\-dumpfv1(8).
|
||||
|
||||
More info on \fBxrdp\fR can be found on the
|
||||
.UR @xrdphomeurl@
|
||||
xrdp homepage
|
||||
.UE
|
|
@ -125,12 +125,12 @@ separator as the password supplied by the user and treats it as autologon. If no
|
|||
defaults to \fBfalse\fP.
|
||||
|
||||
.TP
|
||||
\domain_user_separator\fP=\separator\fP
|
||||
\fBdomain_user_separator\fP=\fBseparator\fP
|
||||
If specified the domain name supplied by the client is appended to the username separated
|
||||
by \fBseparator\fP.
|
||||
|
||||
.TP
|
||||
\enable_token_login\fP=\fI[true|false]\fP
|
||||
\fBenable_token_login\fP=\fI[true|false]\fP
|
||||
If set to \fB1\fP, \fBtrue\fP or \fByes\fP, \fBxrdp\fP requires clients to include username and
|
||||
password initial connection phase. In other words, xrdp doesn't allow clients to show login
|
||||
screen if set to true. If not specified, defaults to \fBfalse\fP.
|
||||
|
@ -212,6 +212,18 @@ These options override the colors used internally by \fBxrdp\fP(8) to draw the l
|
|||
Colors are defined using a hexadecimal (hex) notation for the combination of Red, Green, and Blue color values (RGB).
|
||||
The lowest value that can be given to one of the light sources is 0 (hex 00).
|
||||
The highest value is 255 (hex FF).
|
||||
.TP
|
||||
\fBfv1_select\fP=\fI130:sans-18.fv1,0:sans-10.fv1\fP
|
||||
Selects a default fv1 font.
|
||||
This parameter is a comma-separated list of DPI:name pairs. The list
|
||||
is scanned from left-to-right. The font used is the first font whose DPI
|
||||
value is less-than-or-equal to the vertical DPI of the monitor used for
|
||||
the login screen.
|
||||
.TP
|
||||
\fBdefault_dpi\fP=\fI96\fP
|
||||
Default DPI used for a monitor if the client does not send physical
|
||||
size information.
|
||||
|
||||
|
||||
.SH "LOGGING"
|
||||
The following parameters can be used in the \fB[Logging]\fR section:
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
EXTRA_DIST = windows
|
||||
|
||||
# Some programs need freetype2 to build
|
||||
if USE_FREETYPE2
|
||||
MKFV1 = xrdp-mkfv1
|
||||
else
|
||||
MKFV1 =
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/common \
|
||||
$(FREETYPE2_CFLAGS)
|
||||
|
||||
bin_PROGRAMS = \
|
||||
$(MKFV1) \
|
||||
xrdp-dumpfv1
|
||||
|
||||
xrdp_mkfv1_SOURCES = \
|
||||
mkfv1.c \
|
||||
fv1.c \
|
||||
fv1.h
|
||||
|
||||
xrdp_mkfv1_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(FREETYPE2_LIBS)
|
||||
|
||||
xrdp_dumpfv1_SOURCES = \
|
||||
dumpfv1.c \
|
||||
fv1.c \
|
||||
fv1.h
|
||||
|
||||
xrdp_dumpfv1_LDADD = \
|
||||
$(top_builddir)/common/libcommon.la
|
|
@ -0,0 +1,87 @@
|
|||
The fv1 font format has the following characteristics:-
|
||||
|
||||
1) Bitmap fonts (i.e. pixels are on or off)
|
||||
2) 96 DPI is assumed
|
||||
3) Glyphs from U+0020 up to a pre-defined limit are stored in the file.
|
||||
At the time of writing this limit is U+4DFF. To change the limit
|
||||
requires a change to xrdp/xrdp_types.h and (potentially)
|
||||
fontutils/mkfv1.c
|
||||
4) Font format is header, plus a variable data area for each glyph.
|
||||
|
||||
The intention (over time) is to build support for the freetype2 library
|
||||
directly into xrdp. This will allow for modern font features like
|
||||
anti-aliasing and kerning to be supported.
|
||||
|
||||
General Info
|
||||
------------
|
||||
All numeric values are 2 octets, and stored in twos-complement
|
||||
little-endian format.
|
||||
|
||||
Dimensions are all measured in pixels.
|
||||
|
||||
Font header
|
||||
-----------
|
||||
|
||||
signature 4 octets File signature - "FNT1"
|
||||
font~name 32 octets Null-terminated if less that 32 octets long
|
||||
point_size 2 octets Assumes 96 DPI.
|
||||
style 2 octets Unused. Set to 1.
|
||||
body_height 2 octets Line spacing for font.
|
||||
min_descender 2 octets The common lowest descender value in the font
|
||||
glyphs (A few glyphs may be lower than
|
||||
this). Used to calculate where the font baseline
|
||||
is in relation to the text box for the font.
|
||||
<padding> 4 octets Set to zero.
|
||||
|
||||
Older fonts, generated for xrdp v.0.9x and earlier, have zero values
|
||||
for the body_height and min_descender. For these fonts, the body height is
|
||||
calculated as (-baseline + 1) for the first glyph, and the glyphs are
|
||||
all offset so that a min_descender of 0 works OK.
|
||||
|
||||
Glyph data
|
||||
----------
|
||||
The header is followed by a number of glyphs representing U+0020 upwards. The
|
||||
glyphs have a variable size. The format of each glyph is as follows:-
|
||||
|
||||
width 2 octets Width of character data
|
||||
height 2 octets Height of character data
|
||||
baseline 2 octets Offset from font baseline to 1st row of glyph data
|
||||
offset 2 octets Space before glyph is drawn (can be -ve)
|
||||
inc_by 2 octets Total width of glyph + spacing. The width of
|
||||
a string is obtained by adding up all the inc_by
|
||||
fields for all the glyphs
|
||||
data <variable> Bitmap data.
|
||||
|
||||
Bitmap data is laid out in rows from top to bottom. Within each row the
|
||||
most significant bit of each octet is on the left. Row data is padded
|
||||
to the nearest octet (e.g. a 14 bit width would be padded by 2 bits to
|
||||
16 bits (2 octets). The total data is padded out with between 0 and 3
|
||||
octets to end on a 4-octet boundary.
|
||||
|
||||
Example glyph:-
|
||||
|
||||
Glyph : U+0067
|
||||
Width : 12
|
||||
Height : 18
|
||||
Baseline : -13
|
||||
Offset : 1
|
||||
Inc By : 15
|
||||
Data :
|
||||
-13: ...XXXXX..XX 1F 30
|
||||
-12: ..XXXXXXXXXX 3F F0
|
||||
-11: .XXX....XXXX 70 F0
|
||||
-10: XXX......XXX E0 70
|
||||
-9: XX........XX C0 30
|
||||
-8: XX........XX C0 30
|
||||
-7: XX........XX C0 30
|
||||
-6: XX........XX C0 30
|
||||
-5: XX........XX C0 30
|
||||
-4: XXX......XXX E0 70
|
||||
-3: .XXX....XXXX 70 F0
|
||||
-2: ..XXXXXXXXXX 3F F0
|
||||
-1: ...XXXXX..XX 1F 30
|
||||
+0: ..........XX 00 30
|
||||
+1: .........XXX 00 70
|
||||
+2: ..X.....XXX. 20 E0
|
||||
+3: ..XXXXXXXX.. 3F C0
|
||||
+4: ...XXXXXX... 1F 80
|
|
@ -0,0 +1,413 @@
|
|||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2022
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* fonts
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "os_calls.h"
|
||||
#include "parse.h"
|
||||
#include "string_calls.h"
|
||||
#include "fv1.h"
|
||||
|
||||
/**
|
||||
* What the program is doing
|
||||
*/
|
||||
enum program_mode
|
||||
{
|
||||
PM_UNSPECIFIED = 0,
|
||||
PM_INFO,
|
||||
PM_GLYPH_INFO_TABLE,
|
||||
PM_SHOW_CHAR
|
||||
};
|
||||
|
||||
/**
|
||||
* Parsed program arguments
|
||||
*/
|
||||
struct program_args
|
||||
{
|
||||
const char *font_file;
|
||||
enum program_mode mode;
|
||||
int ucode; /* Unicode character to display in 'c' mode */
|
||||
};
|
||||
|
||||
/**************************************************************************//**
|
||||
* Parses the program args
|
||||
*
|
||||
* @param argc Passed to main
|
||||
* @param @argv Passed to main
|
||||
* @param pa program_pargs structure for resulting values
|
||||
* @return !=0 for success
|
||||
*/
|
||||
static int
|
||||
parse_program_args(int argc, char *argv[], struct program_args *pa)
|
||||
{
|
||||
int params_ok = 1;
|
||||
int opt;
|
||||
|
||||
pa->font_file = NULL;
|
||||
pa->mode = PM_UNSPECIFIED;
|
||||
pa->ucode = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "c:it")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'i':
|
||||
if (pa->mode == PM_UNSPECIFIED)
|
||||
{
|
||||
pa->mode = PM_INFO;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't have two modes set");
|
||||
params_ok = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (pa->mode == PM_UNSPECIFIED)
|
||||
{
|
||||
pa->mode = PM_GLYPH_INFO_TABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't have two modes set");
|
||||
params_ok = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
if (pa->mode == PM_UNSPECIFIED)
|
||||
{
|
||||
pa->mode = PM_SHOW_CHAR;
|
||||
if (toupper(optarg[0]) == 'U' && optarg[1] == '+')
|
||||
{
|
||||
char *hex = g_strdup(optarg);
|
||||
hex[0] = '0';
|
||||
hex[1] = 'x';
|
||||
pa->ucode = g_atoix(hex);
|
||||
g_free(hex);
|
||||
}
|
||||
else if (optarg[0] == '@')
|
||||
{
|
||||
pa->ucode = optarg[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
pa->ucode = g_atoix(optarg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't have two modes set");
|
||||
params_ok = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "Unrecognised switch '%c'", (char)opt);
|
||||
params_ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc <= optind)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "No font file specified");
|
||||
params_ok = 0;
|
||||
}
|
||||
else if ((argc - optind) > 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unexpected arguments after font file");
|
||||
params_ok = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pa->font_file = argv[optind];
|
||||
}
|
||||
|
||||
return params_ok;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Displays information about a font file
|
||||
*
|
||||
* @param fv1 loaded font file
|
||||
*/
|
||||
static void
|
||||
display_font_file_info(const struct fv1_file *fv1)
|
||||
{
|
||||
g_printf("Font name : %s\n", fv1->font_name);
|
||||
g_printf("Point size (%d DPI) : %d\n", FV1_DEVICE_DPI, fv1->point_size);
|
||||
g_printf("Style : %d\n", fv1->style);
|
||||
if (fv1->body_height == 0 && fv1->glyphs->count > 0)
|
||||
{
|
||||
const struct fv1_glyph *g =
|
||||
(const struct fv1_glyph *)fv1->glyphs->items[0];
|
||||
g_printf("Body height : %d (from 1st glyph)\n", -g->baseline + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printf("Body height : %d\n", fv1->body_height);
|
||||
}
|
||||
g_printf("Descender : %d\n", fv1->min_descender);
|
||||
|
||||
if (fv1->glyphs->count == 0)
|
||||
{
|
||||
g_printf("\nFile contains no glyphs\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printf("Min glyph index : U+%04X\n", FV1_MIN_CHAR);
|
||||
g_printf("Max glyph index : U+%04X\n", FV1_GLYPH_END(fv1) - 1);
|
||||
|
||||
/* Work out the statistics */
|
||||
unsigned short max_width = 0;
|
||||
int max_width_ucode = 0;
|
||||
unsigned short max_height = 0;
|
||||
int max_height_ucode = 0;
|
||||
short min_baseline = 0;
|
||||
int min_baseline_ucode = 0;
|
||||
short min_offset = 0;
|
||||
int min_offset_ucode = 0;
|
||||
short max_offset = 0;
|
||||
int max_offset_ucode = 0;
|
||||
unsigned short max_inc_by = 0;
|
||||
int max_inc_by_ucode = 0;
|
||||
|
||||
/* Derived quantities */
|
||||
short min_y_descender = SHRT_MAX;
|
||||
int min_y_descender_ucode = 0;
|
||||
int max_datasize = -1;
|
||||
int max_datasize_ucode = 0;
|
||||
|
||||
/* Loop and output macros */
|
||||
#define SET_MIN(ucode,field,val) \
|
||||
if ((field) < (val)) \
|
||||
{ \
|
||||
val = (field); \
|
||||
val##_ucode = (ucode); \
|
||||
}
|
||||
|
||||
#define SET_MAX(ucode,field,val) \
|
||||
if ((field) > (val)) \
|
||||
{ \
|
||||
val = (field); \
|
||||
val##_ucode = (ucode); \
|
||||
}
|
||||
|
||||
#define OUTPUT_INFO(string, val) \
|
||||
if (val##_ucode > 0) \
|
||||
{ \
|
||||
g_printf(string, val, val##_ucode); \
|
||||
}
|
||||
int u;
|
||||
for (u = FV1_MIN_CHAR ; u < FV1_GLYPH_END(fv1); ++u)
|
||||
{
|
||||
const struct fv1_glyph *g = FV1_GET_GLYPH(fv1, u);
|
||||
if (g != NULL)
|
||||
{
|
||||
short y_descender = - (g->baseline + g->height);
|
||||
int datasize = FONT_DATASIZE(g);
|
||||
|
||||
SET_MAX(u, g->width, max_width);
|
||||
SET_MAX(u, g->height, max_height);
|
||||
SET_MIN(u, g->baseline, min_baseline);
|
||||
SET_MIN(u, g->offset, min_offset);
|
||||
SET_MAX(u, g->offset, max_offset);
|
||||
SET_MAX(u, g->inc_by, max_inc_by);
|
||||
SET_MIN(u, y_descender, min_y_descender);
|
||||
SET_MAX(u, datasize, max_datasize);
|
||||
}
|
||||
}
|
||||
|
||||
OUTPUT_INFO("Max glyph width : %d (U+%04X)\n", max_width);
|
||||
OUTPUT_INFO("Max glyph height : %d (U+%04X)\n", max_height);
|
||||
OUTPUT_INFO("Min glyph y-baseline : %d (U+%04X)\n", min_baseline);
|
||||
OUTPUT_INFO("Min glyph y-descender : %d (U+%04X)\n", min_y_descender);
|
||||
OUTPUT_INFO("Min glyph x-offset : %d (U+%04X)\n", min_offset);
|
||||
OUTPUT_INFO("Max glyph x-offset : %d (U+%04X)\n", max_offset);
|
||||
OUTPUT_INFO("Max glyph x-inc_by : %d (U+%04X)\n", max_inc_by);
|
||||
OUTPUT_INFO("Max glyph datasize : %d (U+%04X)\n", max_datasize);
|
||||
|
||||
#undef SET_MIN
|
||||
#undef SET_MAX
|
||||
#undef OUTPUT_INFO
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Display info in a table about all the glyphs
|
||||
* @param fv1 font file
|
||||
*/
|
||||
static void
|
||||
display_glyph_info_table(const struct fv1_file *fv1)
|
||||
{
|
||||
int u;
|
||||
g_printf("character,width,height,baseline,offset,inc_by,datasize\n");
|
||||
|
||||
for (u = FV1_MIN_CHAR; u < FV1_GLYPH_END(fv1); ++u)
|
||||
{
|
||||
const struct fv1_glyph *g = FV1_GET_GLYPH(fv1, u);
|
||||
if (g != NULL)
|
||||
{
|
||||
int datasize = FONT_DATASIZE(g);
|
||||
g_printf("%d,%hu,%hu,%hd,%hd,%hu,%d\n",
|
||||
u, g->width, g->height, g->baseline,
|
||||
g->offset, g->inc_by, datasize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Converts a font data row to a printable string
|
||||
*
|
||||
* @param rowdata Pointer to the first byte of the row data
|
||||
* @param width Number of pixels in the row
|
||||
* @param out Output buffer. Must be sized by the caller to be at
|
||||
* least width+1 bytes
|
||||
*/
|
||||
static void
|
||||
row_to_str(const unsigned char *rowdata, int width, char *out)
|
||||
{
|
||||
int x;
|
||||
int mask = 1 << 7;
|
||||
for (x = 0 ; x < width ; ++x)
|
||||
{
|
||||
out[x] = ((*rowdata & mask) != 0) ? 'X' : '.';
|
||||
mask >>= 1;
|
||||
if (mask == 0)
|
||||
{
|
||||
mask = 1 << 7;
|
||||
++rowdata;
|
||||
}
|
||||
}
|
||||
out[width] = '\0';
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Display info about a specific glyph
|
||||
* @param ucode Unicode character value
|
||||
* @param g Glyph
|
||||
*/
|
||||
static void
|
||||
display_glyph_info(int ucode, const struct fv1_glyph *g)
|
||||
{
|
||||
|
||||
char *row_buffer = (char *)g_malloc(g->width + 1, 0);
|
||||
if (row_buffer == NULL)
|
||||
{
|
||||
g_printf("<No memory>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_printf("Glyph : U+%04X\n", ucode);
|
||||
g_printf(" Width : %d\n", g->width);
|
||||
g_printf(" Height : %d\n", g->height);
|
||||
g_printf(" Baseline : %d\n", g->baseline);
|
||||
g_printf(" Offset : %d\n", g->offset);
|
||||
g_printf(" Inc By : %d\n", g->inc_by);
|
||||
|
||||
g_printf(" Data :\n");
|
||||
int y;
|
||||
const unsigned char *dataptr = g->data;
|
||||
|
||||
for (y = 0 ; y < g->height; ++y)
|
||||
{
|
||||
row_to_str(dataptr, g->width, row_buffer);
|
||||
g_printf(" %+3d: %s\n", y + g->baseline, row_buffer);
|
||||
dataptr += (g->width + 7) / 8;
|
||||
}
|
||||
g_free(row_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Main
|
||||
*
|
||||
* @param argc Argument count
|
||||
* @param argv Arguments
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct fv1_file *fv1 = NULL;
|
||||
struct log_config *logging;
|
||||
struct program_args pa;
|
||||
int rv = 1;
|
||||
|
||||
logging = log_config_init_for_console(LOG_LEVEL_WARNING,
|
||||
g_getenv("DUMPFV1_LOG_LEVEL"));
|
||||
log_start_from_param(logging);
|
||||
log_config_free(logging);
|
||||
|
||||
if (parse_program_args(argc, argv, &pa) &&
|
||||
(fv1 = fv1_file_load(pa.font_file)) != NULL)
|
||||
{
|
||||
switch (pa.mode)
|
||||
{
|
||||
case PM_INFO:
|
||||
display_font_file_info(fv1);
|
||||
rv = 0;
|
||||
break;
|
||||
|
||||
case PM_GLYPH_INFO_TABLE:
|
||||
display_glyph_info_table(fv1);
|
||||
rv = 0;
|
||||
break;
|
||||
|
||||
case PM_SHOW_CHAR:
|
||||
if (pa.ucode < FV1_MIN_CHAR)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Value for -c must be at least U+%04X",
|
||||
FV1_MIN_CHAR);
|
||||
}
|
||||
else if (pa.ucode >= FV1_GLYPH_END(fv1))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Value for -c must be less than U+%04X",
|
||||
FV1_GLYPH_END(fv1));
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct fv1_glyph *g =
|
||||
(const struct fv1_glyph *)
|
||||
list_get_item(fv1->glyphs, pa.ucode - FV1_MIN_CHAR);
|
||||
display_glyph_info(pa.ucode, g);
|
||||
rv = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "Specify one of '-i' or '-c'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fv1_file_free(fv1);
|
||||
log_end();
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2022
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file fontutils/fv1.c
|
||||
* @brief Definitions relating to fv1 font files
|
||||
*/
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "os_calls.h"
|
||||
#include "parse.h"
|
||||
#include "string_calls.h"
|
||||
#include "fv1.h"
|
||||
|
||||
const static char FV1_SIGNATURE[] = {'F', 'N', 'T', '1'};
|
||||
|
||||
/*****************************************************************************/
|
||||
struct fv1_glyph *
|
||||
fv1_alloc_glyph(int ucode,
|
||||
unsigned short width,
|
||||
unsigned short height)
|
||||
{
|
||||
int datasize = FONT_DATASIZE_FROM_GEOMETRY(width, height);
|
||||
struct fv1_glyph *glyph = NULL;
|
||||
char ucode_str[16] = {'\0'};
|
||||
if (ucode < 0)
|
||||
{
|
||||
g_snprintf(ucode_str, sizeof(ucode_str), "Glyph");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(ucode_str, sizeof(ucode_str), "Glyph:U+%04X", ucode);
|
||||
}
|
||||
|
||||
if (datasize < 0 || datasize > FV1_MAX_GLYPH_DATASIZE)
|
||||
{
|
||||
|
||||
/* shouldn't happen */
|
||||
LOG(LOG_LEVEL_ERROR, "%s - datasize %d out of bounds",
|
||||
ucode_str, datasize);
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph = (struct fv1_glyph *)
|
||||
g_malloc( offsetof(struct fv1_glyph, data) + datasize, 1);
|
||||
|
||||
if (glyph == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s - out of memory", ucode_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph->width = width;
|
||||
glyph->height = height;
|
||||
}
|
||||
}
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct fv1_file *
|
||||
fv1_file_create(void)
|
||||
{
|
||||
struct fv1_file *fv1 = (struct fv1_file *)g_new0(struct fv1_file, 1);
|
||||
if (fv1 == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "fv1_file_create - out of memory");
|
||||
}
|
||||
else
|
||||
{
|
||||
fv1->style = 1; /* Unused at present - compatibility value */
|
||||
fv1->glyphs = list_create();
|
||||
fv1->glyphs->auto_free = 1;
|
||||
}
|
||||
return fv1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
add_glyphs_from_stream(struct fv1_file *fv1, struct stream *s)
|
||||
{
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
int datasize;
|
||||
|
||||
struct fv1_glyph *glyph;
|
||||
|
||||
while (s_check_rem(s, 4))
|
||||
{
|
||||
in_sint16_le(s, width);
|
||||
in_sint16_le(s, height);
|
||||
|
||||
datasize = FONT_DATASIZE_FROM_GEOMETRY(width, height);
|
||||
|
||||
if (datasize < 0 || datasize > FV1_MAX_GLYPH_DATASIZE)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Font:%s Glyph:%d - datasize %d out of bounds",
|
||||
fv1->font_name, FV1_GLYPH_END(fv1), datasize);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 6 + 6 + datasize))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Font:%s Glyph:%d - not enough data for glyph",
|
||||
fv1->font_name, FV1_GLYPH_END(fv1));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((glyph = fv1_alloc_glyph(FV1_GLYPH_END(fv1), width, height)) == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
in_sint16_le(s, glyph->baseline);
|
||||
in_sint16_le(s, glyph->offset);
|
||||
in_sint16_le(s, glyph->inc_by);
|
||||
in_uint8s(s, 6);
|
||||
|
||||
in_uint8a(s, glyph->data, datasize);
|
||||
|
||||
list_add_item(fv1->glyphs, (tintptr)glyph);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct fv1_file *
|
||||
fv1_file_load(const char *filename)
|
||||
{
|
||||
struct fv1_file *fv1 = NULL;
|
||||
|
||||
if (!g_file_exist(filename))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't find font file %s", filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
int file_size = g_file_get_size(filename);
|
||||
if (file_size < FV1_MIN_FILE_SIZE || file_size > FV1_MAX_FILE_SIZE)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Font file %s has bad size %d",
|
||||
filename, file_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stream *s;
|
||||
int fd;
|
||||
make_stream(s);
|
||||
init_stream(s, file_size + 1024);
|
||||
fd = g_file_open(filename);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't open font file %s", filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
int b = g_file_read(fd, s->data, file_size + 1024);
|
||||
g_file_close(fd);
|
||||
|
||||
if (b < FV1_MIN_FILE_SIZE)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Font file %s is too small",
|
||||
filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
char sig[sizeof(FV1_SIGNATURE)];
|
||||
s->end = s->data + b;
|
||||
in_uint8a(s, sig, sizeof(FV1_SIGNATURE));
|
||||
if (g_memcmp(sig, FV1_SIGNATURE, sizeof(sig)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Font file %s has wrong signature",
|
||||
filename);
|
||||
}
|
||||
else if ((fv1 = fv1_file_create()) != NULL)
|
||||
{
|
||||
in_uint8a(s, fv1->font_name, FV1_MAX_FONT_NAME_SIZE);
|
||||
fv1->font_name[FV1_MAX_FONT_NAME_SIZE] = '\0';
|
||||
in_uint16_le(s, fv1->point_size);
|
||||
in_uint16_le(s, fv1->style);
|
||||
in_uint16_le(s, fv1->body_height);
|
||||
in_uint16_le(s, fv1->min_descender);
|
||||
in_uint8s(s, 4);
|
||||
|
||||
add_glyphs_from_stream(fv1, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
}
|
||||
}
|
||||
|
||||
return fv1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
fv1_file_free(struct fv1_file *fv1)
|
||||
{
|
||||
if (fv1 != NULL)
|
||||
{
|
||||
list_delete(fv1->glyphs);
|
||||
g_free(fv1);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
write_stream(int fd, struct stream *s)
|
||||
{
|
||||
const char *p = s->data;
|
||||
int rv = 1;
|
||||
|
||||
while (p < s->end)
|
||||
{
|
||||
int len = g_file_write(fd, p, s->end - p);
|
||||
if (len <= 0)
|
||||
{
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
fv1_file_save(const struct fv1_file *fv1, const char *filename)
|
||||
{
|
||||
int fd;
|
||||
struct fv1_glyph *blank_glyph; /* Needed for bad characters */
|
||||
|
||||
fd = g_file_open_ex(filename, 0, 1, 1, 1);
|
||||
int rv = 1;
|
||||
if (fd < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to open %s for writing [%s]", filename,
|
||||
g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
struct stream *s;
|
||||
make_stream(s);
|
||||
init_stream(s, 1024);
|
||||
|
||||
/* Write the header */
|
||||
out_uint8a(s, FV1_SIGNATURE, sizeof(FV1_SIGNATURE));
|
||||
int len = g_strlen(fv1->font_name);
|
||||
if (len > FV1_MAX_FONT_NAME_SIZE)
|
||||
{
|
||||
len = FV1_MAX_FONT_NAME_SIZE;
|
||||
}
|
||||
out_uint8a(s, fv1->font_name, len);
|
||||
while (len++ < FV1_MAX_FONT_NAME_SIZE)
|
||||
{
|
||||
out_uint8(s, '\0');
|
||||
}
|
||||
out_uint16_le(s, fv1->point_size);
|
||||
out_uint16_le(s, fv1->style);
|
||||
out_uint16_le(s, fv1->body_height);
|
||||
out_uint16_le(s, fv1->min_descender);
|
||||
out_uint8a(s, "\0\0\0\0", 4);
|
||||
s_mark_end(s);
|
||||
if (!write_stream(fd, s))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to write file header [%s]",
|
||||
g_get_strerror());
|
||||
}
|
||||
else if ((blank_glyph = fv1_alloc_glyph(-1, 0, 0)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to allocate blank glyph");
|
||||
}
|
||||
else
|
||||
{
|
||||
int u;
|
||||
|
||||
for (u = FV1_MIN_CHAR; u < FV1_GLYPH_END(fv1); ++u)
|
||||
{
|
||||
const struct fv1_glyph *g = FV1_GET_GLYPH(fv1, u);
|
||||
int datasize;
|
||||
if (g == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Glyph %d is not set", u);
|
||||
g = blank_glyph;
|
||||
}
|
||||
else
|
||||
{
|
||||
datasize = FONT_DATASIZE(g);
|
||||
if (datasize > FV1_MAX_GLYPH_DATASIZE)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"glyph %d datasize %d exceeds max of %d"
|
||||
" - glyph will be blank",
|
||||
u, datasize, FV1_MAX_GLYPH_DATASIZE);
|
||||
g = blank_glyph;
|
||||
}
|
||||
}
|
||||
init_stream(s, 16 + FONT_DATASIZE(g));
|
||||
out_uint16_le(s, g->width);
|
||||
out_uint16_le(s, g->height);
|
||||
out_uint16_le(s, g->baseline);
|
||||
out_uint16_le(s, g->offset);
|
||||
out_uint16_le(s, g->inc_by);
|
||||
out_uint8a(s, "\0\0\0\0\0\0", 6);
|
||||
out_uint8a(s, g->data, FONT_DATASIZE(g));
|
||||
s_mark_end(s);
|
||||
|
||||
if (!write_stream(fd, s))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Unable to write glyph %d [%s]",
|
||||
u, g_get_strerror());
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free(blank_glyph);
|
||||
|
||||
rv = (u == FV1_GLYPH_END(fv1)) ? 0 : 1;
|
||||
}
|
||||
free_stream(s);
|
||||
g_file_close(fd);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2022
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file fontutils/fv1.h
|
||||
* @brief Definitions relating to fv1 font files
|
||||
*/
|
||||
#if !defined(FV1_H)
|
||||
#define FV1_H
|
||||
|
||||
struct list;
|
||||
|
||||
#define FV1_DEVICE_DPI 96
|
||||
|
||||
#define FV1_MIN_CHAR 0x20 /* First character value in file */
|
||||
|
||||
#define FV1_MIN_FILE_SIZE 48
|
||||
#define FV1_MAX_FILE_SIZE (10 * 1024 * 1024)
|
||||
#define FV1_MAX_FONT_NAME_SIZE 32
|
||||
|
||||
#define FV1_MAX_GLYPH_DATASIZE 512
|
||||
|
||||
struct fv1_glyph
|
||||
{
|
||||
unsigned short width; /* Width of glyph */
|
||||
unsigned short height; /* Height of glyph */
|
||||
short baseline; /* Offset from cursor pos to 1st row of glyph */
|
||||
short offset; /* Space before glyph (can be -ve) */
|
||||
unsigned short inc_by; /* Total width of glyph + spacing */
|
||||
/* Standard C++ does not yet support C99 flexible array members */
|
||||
#ifdef __cplusplus
|
||||
unsigned char data[1];
|
||||
#else
|
||||
unsigned char data[];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fv1_file
|
||||
{
|
||||
char font_name[FV1_MAX_FONT_NAME_SIZE + 1];
|
||||
short point_size; /* Input point size (for reference) */
|
||||
short style;
|
||||
short body_height; /* Body height (pixels) */
|
||||
short min_descender; /* Min descender of the glyphs in the font */
|
||||
struct list *glyphs; /* Glyphs are struct fv1_glyph * */
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a glyph pointer for a unicode character
|
||||
*/
|
||||
#define FV1_GET_GLYPH(fv1,ucode) \
|
||||
(((ucode) < FV1_MIN_CHAR) \
|
||||
? NULL \
|
||||
: (struct fv1_glyph *)list_get_item(fv1->glyphs, (ucode) - FV1_MIN_CHAR))
|
||||
|
||||
/**
|
||||
* First glyph not in file
|
||||
*/
|
||||
#define FV1_GLYPH_END(fv1) (fv1->glyphs->count + FV1_MIN_CHAR)
|
||||
|
||||
struct fv1_file *
|
||||
fv1_file_load(const char *filename);
|
||||
|
||||
void
|
||||
fv1_file_free(struct fv1_file *);
|
||||
|
||||
struct fv1_file *
|
||||
fv1_file_create(void);
|
||||
|
||||
struct fv1_glyph *
|
||||
fv1_alloc_glyph(int ucode, /* Unicode character for error reporting if known */
|
||||
unsigned short width,
|
||||
unsigned short height);
|
||||
|
||||
enum fv1_realloc_mode
|
||||
{
|
||||
FV1_AT_TOP,
|
||||
FV1_AT_BOTTOM
|
||||
};
|
||||
|
||||
int
|
||||
fv1_file_save(const struct fv1_file *fv1, const char *filename);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,587 @@
|
|||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2012
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
/* See the FT2 documentation - this builds an error table */
|
||||
#undef FTERRORS_H_
|
||||
#define FT_ERRORDEF( e, v, s ) { e, s },
|
||||
#define FT_ERROR_START_LIST {
|
||||
#define FT_ERROR_END_LIST { 0, NULL } };
|
||||
|
||||
static const struct
|
||||
{
|
||||
int err_code;
|
||||
const char *err_msg;
|
||||
} ft_errors[] =
|
||||
#include <freetype/fterrors.h>
|
||||
|
||||
#if 0
|
||||
/* These lines fix problems with astyle formatting following the ft_errors
|
||||
* definition */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#include "arch.h"
|
||||
#include "defines.h"
|
||||
#include "log.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#include "fv1.h"
|
||||
|
||||
#define DEFAULT_POINT_SIZE 10
|
||||
#define DEFAULT_MAX_CHAR 0x4dff
|
||||
|
||||
/**
|
||||
* sans10 compatibility choices
|
||||
*/
|
||||
enum sans10_compat
|
||||
{
|
||||
S10_OFF = 0,
|
||||
S10_ON,
|
||||
S10_AUTO
|
||||
};
|
||||
|
||||
/**
|
||||
* Parsed program arguments
|
||||
*/
|
||||
struct program_args
|
||||
{
|
||||
const char *input_file;
|
||||
const char *output_file;
|
||||
char font_name[FV1_MAX_FONT_NAME_SIZE + 1];
|
||||
unsigned short point_size;
|
||||
/** Last character value in file */
|
||||
unsigned int max_ucode;
|
||||
/** Are we generating san10 in compatibility mode? */
|
||||
enum sans10_compat sans10_compatibility;
|
||||
};
|
||||
|
||||
struct x_dimensions
|
||||
{
|
||||
unsigned short width;
|
||||
short offset;
|
||||
unsigned short inc_by;
|
||||
};
|
||||
|
||||
/**
|
||||
* Table of some character settings in the original sans-10.fv1 font
|
||||
*/
|
||||
static const struct x_dimensions
|
||||
original_sans10_data[] =
|
||||
{
|
||||
/* 0x20 - 0x3f */
|
||||
{1, 0, 4}, {1, 2, 5}, {3, 1, 5}, {9, 1, 11},
|
||||
{7, 1, 8}, {11, 0, 12}, {9, 1, 11}, {1, 1, 3},
|
||||
{3, 1, 5}, {3, 1, 5}, {7, 0, 7}, {9, 1, 11},
|
||||
{2, 1, 4}, {3, 1, 5}, {1, 2, 4}, {4, 0, 4},
|
||||
{6, 1, 8}, {5, 2, 8}, {6, 1, 8}, {6, 1, 8},
|
||||
{6, 1, 8}, {6, 1, 8}, {6, 1, 8}, {6, 1, 8},
|
||||
{6, 1, 8}, {6, 1, 8}, {1, 2, 4}, {2, 1, 4},
|
||||
{8, 1, 11}, {8, 1, 11}, {8, 1, 11}, {5, 1, 7},
|
||||
/* 0x40 - 0x5f */
|
||||
{11, 1, 13}, {9, 0, 9}, {7, 1, 9}, {7, 1, 9},
|
||||
{8, 1, 10}, {6, 1, 8}, {5, 1, 7}, {8, 1, 10},
|
||||
{8, 1, 10}, {1, 1, 3}, {3, -1, 3}, {7, 1, 8},
|
||||
{6, 1, 7}, {9, 1, 11}, {8, 1, 10}, {8, 1, 10},
|
||||
{6, 1, 8}, {8, 1, 10}, {7, 1, 8}, {7, 1, 9},
|
||||
{7, 0, 7}, {8, 1, 10}, {9, 0, 9}, {11, 0, 11},
|
||||
{8, 0, 8}, {7, 0, 7}, {8, 1, 10}, {3, 1, 5},
|
||||
{4, 0, 4}, {3, 1, 5}, {8, 1, 11}, {7, 0, 7},
|
||||
/* 0x60 - 0x7f */
|
||||
{3, 1, 7}, {6, 1, 8}, {6, 1, 8}, {5, 1, 7},
|
||||
{6, 1, 8}, {6, 1, 8}, {4, 0, 4}, {6, 1, 8},
|
||||
{6, 1, 8}, {1, 1, 3}, {2, 0, 3}, {6, 1, 7},
|
||||
{1, 1, 3}, {11, 1, 13}, {6, 1, 8}, {6, 1, 8},
|
||||
{6, 1, 8}, {6, 1, 8}, {4, 1, 5}, {5, 1, 7},
|
||||
{4, 0, 5}, {6, 1, 8}, {7, 0, 7}, {9, 0, 9},
|
||||
{7, 0, 7}, {7, 0, 7}, {5, 1, 7}, {5, 2, 8},
|
||||
{1, 2, 4}, {5, 2, 8}, {8, 1, 11}, {7, 1, 8},
|
||||
/* 0x80 - 0x9f */
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
{7, 1, 8}, {7, 1, 8}, {7, 1, 8}, {7, 1, 8},
|
||||
/* 0xa0 - 0xbf */
|
||||
{1, 0, 4}, {1, 2, 5}, {6, 1, 8}, {7, 0, 8},
|
||||
{7, 0, 8}, {7, 1, 8}, {1, 2, 4}, {5, 1, 7},
|
||||
{3, 2, 7}, {9, 2, 13}, {5, 1, 6}, {6, 1, 8},
|
||||
{8, 1, 11}, {3, 1, 5}, {9, 2, 13}, {4, 1, 7},
|
||||
{4, 1, 7}, {9, 1, 11}, {4, 1, 5}, {4, 1, 5},
|
||||
{3, 2, 7}, {7, 1, 8}, {6, 1, 8}, {1, 1, 4},
|
||||
{3, 2, 7}, {3, 1, 5}, {5, 1, 6}, {6, 1, 8},
|
||||
{12, 1, 13}, {11, 1, 13}, {12, 1, 13}, {5, 1, 7},
|
||||
/* 0xc0 - 0xdf */
|
||||
{9, 0, 9}, {9, 0, 9}, {9, 0, 9}, {9, 0, 9},
|
||||
{9, 0, 9}, {9, 0, 9}, {12, 0, 13}, {7, 1, 9},
|
||||
{6, 1, 8}, {6, 1, 8}, {6, 1, 8}, {6, 1, 8},
|
||||
{2, 0, 3}, {2, 1, 3}, {5, -1, 3}, {3, 0, 3},
|
||||
{9, 0, 10}, {8, 1, 10}, {8, 1, 10}, {8, 1, 10},
|
||||
{8, 1, 10}, {8, 1, 10}, {8, 1, 10}, {7, 2, 11},
|
||||
{8, 1, 10}, {8, 1, 10}, {8, 1, 10}, {8, 1, 10},
|
||||
{8, 1, 10}, {7, 0, 7}, {6, 1, 8}, {6, 1, 8},
|
||||
/* 0xe0 - 0xff */
|
||||
{6, 1, 8}, {6, 1, 8}, {6, 1, 8}, {6, 1, 8},
|
||||
{6, 1, 8}, {6, 1, 8}, {11, 1, 13}, {5, 1, 7},
|
||||
{6, 1, 8}, {6, 1, 8}, {6, 1, 8}, {6, 1, 8},
|
||||
{3, 0, 3}, {3, 1, 3}, {5, -1, 3}, {3, 0, 3},
|
||||
{6, 1, 8}, {6, 1, 8}, {6, 1, 8}, {6, 1, 8},
|
||||
{6, 1, 8}, {6, 1, 8}, {6, 1, 8}, {8, 1, 11},
|
||||
{6, 1, 8}, {6, 1, 8}, {6, 1, 8}, {6, 1, 8},
|
||||
{6, 1, 8}, {7, 0, 7}, {6, 1, 8}, {7, 0, 7}
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* Parses a unicode character value
|
||||
*
|
||||
* @param str String containing value
|
||||
* @return Resulting character value
|
||||
*/
|
||||
static unsigned int
|
||||
parse_ucode_name(const char *str)
|
||||
{
|
||||
unsigned int rv;
|
||||
if (toupper(str[0]) == 'U' && str[1] == '+')
|
||||
{
|
||||
char *hex = g_strdup(str);
|
||||
hex[0] = '0';
|
||||
hex[1] = 'x';
|
||||
rv = g_atoix(hex);
|
||||
g_free(hex);
|
||||
}
|
||||
else if (str[0] == '@')
|
||||
{
|
||||
rv = str[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = g_atoix(str);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Parses the program args
|
||||
*
|
||||
* @param argc Passed to main
|
||||
* @param @argv Passed to main
|
||||
* @param pa program_pargs structure for resulting values
|
||||
* @return !=0 for success
|
||||
*/
|
||||
static int
|
||||
parse_program_args(int argc, char *argv[], struct program_args *pa)
|
||||
{
|
||||
int params_ok = 1;
|
||||
int opt;
|
||||
|
||||
pa->input_file = NULL;
|
||||
pa->output_file = NULL;
|
||||
pa->font_name[0] = '\0';
|
||||
pa->point_size = DEFAULT_POINT_SIZE;
|
||||
pa->max_ucode = DEFAULT_MAX_CHAR;
|
||||
pa->sans10_compatibility = S10_AUTO;
|
||||
|
||||
while ((opt = getopt(argc, argv, "n:p:m:C:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'n':
|
||||
g_snprintf(pa->font_name, FV1_MAX_FONT_NAME_SIZE + 1, "%s",
|
||||
optarg);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
pa->point_size = g_atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
pa->max_ucode = parse_ucode_name(optarg);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
if (toupper(optarg[0]) == 'A')
|
||||
{
|
||||
pa->sans10_compatibility = S10_AUTO;
|
||||
}
|
||||
else if (g_text2bool(optarg))
|
||||
{
|
||||
pa->sans10_compatibility = S10_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
pa->sans10_compatibility = S10_OFF;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "Unrecognised switch '%c'", (char)opt);
|
||||
params_ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pa->max_ucode < FV1_MIN_CHAR)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "-m argument must be at least %d",
|
||||
FV1_MIN_CHAR);
|
||||
params_ok = 0;
|
||||
}
|
||||
|
||||
switch (argc - optind)
|
||||
{
|
||||
case 0:
|
||||
LOG(LOG_LEVEL_ERROR, "No input file specified");
|
||||
params_ok = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
LOG(LOG_LEVEL_ERROR, "No output file specified");
|
||||
params_ok = 0;
|
||||
break;
|
||||
case 2:
|
||||
pa->input_file = argv[optind];
|
||||
pa->output_file = argv[optind + 1];
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "Unexpected arguments after output file");
|
||||
params_ok = 0;
|
||||
}
|
||||
|
||||
return params_ok;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Checks whether the specified glyph row is blank
|
||||
* @param g Glyph
|
||||
* @param row Row number between 0 and g->height - 1
|
||||
* @result Boolean
|
||||
*/
|
||||
static int
|
||||
is_blank_glyph_row(const struct fv1_glyph *g, unsigned int row)
|
||||
{
|
||||
if (g->width == 0 || row >= g->height)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
const unsigned int glyph_row_size = ((g->width + 7) / 8);
|
||||
const unsigned char *dataptr = g->data + (row * glyph_row_size);
|
||||
const unsigned int masks[] =
|
||||
{ 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
|
||||
|
||||
/* Check for set pixels in all the leading bytes */
|
||||
unsigned int x;
|
||||
for (x = g->width ; x > 8 ; x -= 8)
|
||||
{
|
||||
if (*dataptr++ != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use a single test to check the pixels in the last byte */
|
||||
return ((*dataptr & masks[x - 1]) == 0);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Returns a string for a freetype2 error
|
||||
* @param error Freetype2 error code
|
||||
* @param buff Pointer to buffer for error string
|
||||
* @param bufflen Length of above
|
||||
*/
|
||||
static void
|
||||
get_ft_error(FT_Error error, char *buff, unsigned int bufflen)
|
||||
{
|
||||
const char *errstr = NULL;
|
||||
unsigned int i;
|
||||
for (i = 0 ; i < (sizeof(ft_errors) / sizeof(ft_errors[0])); ++i)
|
||||
{
|
||||
if (ft_errors[i].err_code == error)
|
||||
{
|
||||
errstr = ft_errors[i].err_msg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errstr != NULL)
|
||||
{
|
||||
g_snprintf(buff, bufflen, "[%s]", errstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(buff, bufflen,
|
||||
"[errorcode %d (no description)]", (int)error);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Implement sans10 compatibility for a glyph
|
||||
*
|
||||
* The original Windows font generator made a few different choices for the
|
||||
* character x offset than freetype2 does. These are particularly noticeable
|
||||
* with a small font.
|
||||
*
|
||||
* This routine checks the glyph, and implements the original offset size
|
||||
* for popular English characters, which are all that the user will probably
|
||||
* be displaying with xrdp v0.9.x
|
||||
*
|
||||
* @param g Glyph to check
|
||||
*/
|
||||
static void
|
||||
implement_sans10_compatibility(struct fv1_glyph *g, unsigned int ucode)
|
||||
{
|
||||
const unsigned int max_index =
|
||||
sizeof(original_sans10_data) / sizeof(original_sans10_data[0]);
|
||||
|
||||
if (ucode < FV1_MIN_CHAR || ucode >= max_index + FV1_MIN_CHAR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const struct x_dimensions *d =
|
||||
&original_sans10_data[ucode - FV1_MIN_CHAR];
|
||||
|
||||
if (g->offset != d->offset)
|
||||
{
|
||||
if (g->width != d->width)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Can't set compatibility offset for U+%04X: width %d != %d",
|
||||
ucode, g->width, d->width);
|
||||
}
|
||||
else if (g->inc_by != d->inc_by)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Can't set compatibility offset for U+%04X: inc_by %d != %d",
|
||||
ucode, g->inc_by, d->inc_by);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Changing compatibility offset for U+%04X: from %d to %d",
|
||||
ucode, g->offset, d->offset);
|
||||
}
|
||||
|
||||
g->offset = d->offset;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Converts a freetype 2 bitmap to a fv1 glyph
|
||||
* @param ft_glyph Freetype2 glyph. Must be a monochrome bitmap
|
||||
* @param ucode Unicode character for error reporting
|
||||
* @param pa Program args
|
||||
* @return fv1 glyph, or NULL for error
|
||||
*/
|
||||
static struct fv1_glyph *
|
||||
convert_mono_glyph(FT_GlyphSlot ft_glyph, unsigned int ucode,
|
||||
const struct program_args *pa)
|
||||
{
|
||||
short width = ft_glyph->bitmap.width;
|
||||
short height = ft_glyph->bitmap.rows;
|
||||
struct fv1_glyph *g;
|
||||
|
||||
/* Number of bytes in a glyph row */
|
||||
const unsigned int glyph_row_size = ((width + 7) / 8);
|
||||
|
||||
if ((g = fv1_alloc_glyph(ucode, width, height)) != NULL)
|
||||
{
|
||||
g->baseline = -(ft_glyph->metrics.horiBearingY / 64);
|
||||
g->offset = ft_glyph->metrics.horiBearingX / 64;
|
||||
g->inc_by = ft_glyph->metrics.horiAdvance / 64;
|
||||
|
||||
if (FONT_DATASIZE(g) > 0)
|
||||
{
|
||||
const unsigned char *srcptr = ft_glyph->bitmap.buffer;
|
||||
unsigned char *dstptr = g->data;
|
||||
unsigned int y;
|
||||
|
||||
for (y = 0; y < g->height; ++y)
|
||||
{
|
||||
g_memcpy(dstptr, srcptr, glyph_row_size);
|
||||
dstptr += glyph_row_size;
|
||||
srcptr += ft_glyph->bitmap.pitch;
|
||||
}
|
||||
|
||||
/* Optimise the glyph by removing any blank lines at the bottom
|
||||
* and top */
|
||||
if (g->width > 0)
|
||||
{
|
||||
while (g->height > 0 &&
|
||||
is_blank_glyph_row(g, g->height - 1))
|
||||
{
|
||||
--g->height;
|
||||
}
|
||||
|
||||
y = 0;
|
||||
while (y < g->height && is_blank_glyph_row(g, y))
|
||||
{
|
||||
++y;
|
||||
}
|
||||
|
||||
if (y > 0)
|
||||
{
|
||||
g->baseline += y;
|
||||
g->height -= y;
|
||||
g_memmove(g->data, g->data + (y * glyph_row_size),
|
||||
g->height * glyph_row_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pa->sans10_compatibility != S10_OFF)
|
||||
{
|
||||
implement_sans10_compatibility(g, ucode);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Main
|
||||
*
|
||||
* @param argc Argument count
|
||||
* @param argv Arguments
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FT_Library library = NULL; /* handle to library */
|
||||
FT_Face face = NULL; /* handle to face object */
|
||||
FT_Error error;
|
||||
struct fv1_glyph *g;
|
||||
struct program_args pa;
|
||||
struct log_config *logging;
|
||||
int rv = 1;
|
||||
|
||||
logging = log_config_init_for_console(LOG_LEVEL_WARNING,
|
||||
g_getenv("MKFV1_LOG_LEVEL"));
|
||||
log_start_from_param(logging);
|
||||
log_config_free(logging);
|
||||
|
||||
struct fv1_file *fv1 = fv1_file_create();
|
||||
|
||||
if (fv1 == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Memory allocation failure");
|
||||
}
|
||||
else if (parse_program_args(argc, argv, &pa))
|
||||
{
|
||||
char errstr[128];
|
||||
|
||||
if ((error = FT_Init_FreeType(&library)) != 0)
|
||||
{
|
||||
get_ft_error(error, errstr, sizeof(errstr));
|
||||
LOG(LOG_LEVEL_ERROR, "Error initializing freetype library %s",
|
||||
errstr);
|
||||
}
|
||||
else if ((error = FT_New_Face(library, pa.input_file, 0, &face)) != 0)
|
||||
{
|
||||
get_ft_error(error, errstr, sizeof(errstr));
|
||||
LOG(LOG_LEVEL_ERROR, "Error loading font file %s %s",
|
||||
pa.input_file, errstr);
|
||||
}
|
||||
else if ((error = FT_Set_Char_Size(face, 0,
|
||||
pa.point_size * 64,
|
||||
FV1_DEVICE_DPI, 0)) != 0)
|
||||
{
|
||||
get_ft_error(error, errstr, sizeof(errstr));
|
||||
LOG(LOG_LEVEL_ERROR, "Error setting point size to %u %s",
|
||||
pa.point_size, errstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *fname =
|
||||
(pa.font_name[0] != '\0') ? pa.font_name :
|
||||
(face->family_name != NULL) ? face->family_name :
|
||||
/* Default */ "";
|
||||
|
||||
g_snprintf(fv1->font_name, FV1_MAX_FONT_NAME_SIZE + 1, "%s", fname);
|
||||
fv1->point_size = pa.point_size;
|
||||
fv1->body_height = face->size->metrics.height / 64;
|
||||
fv1->min_descender = face->size->metrics.descender / 64;
|
||||
|
||||
if (pa.sans10_compatibility == S10_AUTO)
|
||||
{
|
||||
if (g_strcmp(fv1->font_name, "DejaVu Sans") == 0 &&
|
||||
fv1->point_size == 10)
|
||||
{
|
||||
pa.sans10_compatibility = S10_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
pa.sans10_compatibility = S10_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int u;
|
||||
for (u = FV1_MIN_CHAR; u <= pa.max_ucode; ++u)
|
||||
{
|
||||
/* retrieve glyph index from character code */
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(face, u);
|
||||
|
||||
/* load glyph image into the slot (erase previous one) */
|
||||
error = FT_Load_Glyph(face, glyph_index,
|
||||
FT_LOAD_RENDER | FT_LOAD_TARGET_MONO);
|
||||
if (error)
|
||||
{
|
||||
get_ft_error(error, errstr, sizeof(errstr));
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Unable to get bitmap for U+%04X %s", u, errstr);
|
||||
g = NULL;
|
||||
}
|
||||
else if (face->glyph->format != FT_GLYPH_FORMAT_BITMAP ||
|
||||
face->glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Internal error; U+%04X was not loaded as a bitmap",
|
||||
u);
|
||||
g = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
g = convert_mono_glyph(face->glyph, u, &pa);
|
||||
}
|
||||
list_add_item(fv1->glyphs, (tintptr)g);
|
||||
}
|
||||
|
||||
rv = fv1_file_save(fv1, pa.output_file);
|
||||
}
|
||||
}
|
||||
|
||||
FT_Done_FreeType(library);
|
||||
fv1_file_free(fv1);
|
||||
log_end();
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -99,5 +99,6 @@ dist_xrdppkgdata_DATA = \
|
|||
xrdp256.bmp \
|
||||
xrdp_logo.bmp \
|
||||
sans-10.fv1 \
|
||||
sans-18.fv1 \
|
||||
cursor0.cur \
|
||||
cursor1.cur
|
||||
|
|
BIN
xrdp/sans-10.fv1
BIN
xrdp/sans-10.fv1
Binary file not shown.
Binary file not shown.
16
xrdp/xrdp.h
16
xrdp/xrdp.h
|
@ -301,8 +301,8 @@ xrdp_painter_draw_bitmap(struct xrdp_painter *self,
|
|||
int x, int y, int cx, int cy);
|
||||
int
|
||||
xrdp_painter_text_width(struct xrdp_painter *self, const char *text);
|
||||
int
|
||||
xrdp_painter_text_height(struct xrdp_painter *self, const char *text);
|
||||
unsigned int
|
||||
xrdp_painter_font_body_height(const struct xrdp_painter *self);
|
||||
int
|
||||
xrdp_painter_draw_text(struct xrdp_painter *self,
|
||||
struct xrdp_bitmap *bitmap,
|
||||
|
@ -343,7 +343,7 @@ xrdp_painter_line(struct xrdp_painter *self,
|
|||
|
||||
/* xrdp_font.c */
|
||||
struct xrdp_font *
|
||||
xrdp_font_create(struct xrdp_wm *wm);
|
||||
xrdp_font_create(struct xrdp_wm *wm, unsigned int dpi);
|
||||
void
|
||||
xrdp_font_delete(struct xrdp_font *self);
|
||||
int
|
||||
|
@ -387,10 +387,20 @@ int
|
|||
get_keymaps(int keylayout, struct xrdp_keymap *keymap);
|
||||
|
||||
/* xrdp_login_wnd.c */
|
||||
/**
|
||||
* Gets the DPI of the login (primary) monitor
|
||||
*
|
||||
* @param self xrdp_wm instance
|
||||
* @return DPI of primary monitor, or 0 if unavailable.
|
||||
*/
|
||||
unsigned int
|
||||
xrdp_login_wnd_get_monitor_dpi(struct xrdp_wm *self);
|
||||
int
|
||||
xrdp_login_wnd_create(struct xrdp_wm *self);
|
||||
int
|
||||
load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp);
|
||||
void
|
||||
xrdp_login_wnd_scale_config_values(struct xrdp_wm *self);
|
||||
|
||||
/* xrdp_bitmap_compress.c */
|
||||
int
|
||||
|
|
|
@ -106,6 +106,17 @@ grey=dedede
|
|||
#green=00ff00
|
||||
#background=626c72
|
||||
|
||||
;
|
||||
; Select a default fv1 font
|
||||
;
|
||||
; This parameter is a comma-separated list of DPI:name pairs.
|
||||
; The list is scanned from left-to-right. The font used is the first
|
||||
; font whose DPI value is less-than-or-equal to the vertical DPI of
|
||||
; the monitor used for the login screen.
|
||||
#fv1_select=130:sans-18.fv1,0:sans-10.fv1
|
||||
; Default DPI used for a monitor when that information is unknown
|
||||
#default_dpi=96
|
||||
|
||||
;
|
||||
; configure login screen
|
||||
;
|
||||
|
@ -118,6 +129,10 @@ ls_top_window_bg_color=009cb5
|
|||
|
||||
; width and height of login screen
|
||||
;
|
||||
; When the sans-10.fv1 font is selected, these values are in pixels.
|
||||
; For other fonts, these values (and other size values) will be scaled
|
||||
; appropriately to preserve the proportions of the login screen.
|
||||
;
|
||||
; The default height allows for about 5 fields to be comfortably displayed
|
||||
; above the buttons at the bottom. To display more fields, make <ls_height>
|
||||
; larger, and also increase <ls_btn_ok_y_pos> and <ls_btn_cancel_y_pos>
|
||||
|
@ -147,15 +162,15 @@ ls_bg_color=dedede
|
|||
; For transform values, see 'ls_background_transform'. The logo width and
|
||||
; logo height are ignored for a transform of 'none'.
|
||||
ls_logo_filename=
|
||||
#ls_logo_transform=none
|
||||
#ls_logo_width=240
|
||||
#ls_logo_height=140
|
||||
ls_logo_transform=scale
|
||||
ls_logo_width=240
|
||||
ls_logo_height=140
|
||||
ls_logo_x_pos=55
|
||||
ls_logo_y_pos=50
|
||||
|
||||
; for positioning labels such as username, password etc
|
||||
ls_label_x_pos=30
|
||||
ls_label_width=65
|
||||
ls_label_width=68
|
||||
|
||||
; for positioning text and combo boxes next to above labels
|
||||
ls_input_x_pos=110
|
||||
|
|
|
@ -111,6 +111,7 @@ int
|
|||
xrdp_bitmap_set_focus(struct xrdp_bitmap *self, int focused)
|
||||
{
|
||||
struct xrdp_painter *painter = (struct xrdp_painter *)NULL;
|
||||
unsigned int font_height;
|
||||
|
||||
if (self == 0)
|
||||
{
|
||||
|
@ -125,19 +126,22 @@ xrdp_bitmap_set_focus(struct xrdp_bitmap *self, int focused)
|
|||
painter = xrdp_painter_create(self->wm, self->wm->session);
|
||||
xrdp_painter_font_needed(painter);
|
||||
xrdp_painter_begin_update(painter);
|
||||
font_height = xrdp_painter_font_body_height(painter);
|
||||
|
||||
if (focused)
|
||||
{
|
||||
/* active title bar */
|
||||
painter->fg_color = self->wm->blue;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3,
|
||||
self->width - 5, font_height + 5);
|
||||
painter->fg_color = self->wm->white;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* inactive title bar */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3,
|
||||
self->width - 5, font_height + 5);
|
||||
painter->fg_color = self->wm->black;
|
||||
}
|
||||
|
||||
|
@ -616,6 +620,7 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
|
|||
struct xrdp_rect r1;
|
||||
struct xrdp_rect r2;
|
||||
struct xrdp_painter *painter;
|
||||
unsigned int font_height;
|
||||
twchar wtext[256];
|
||||
char text[256];
|
||||
char *p;
|
||||
|
@ -632,6 +637,7 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
|
|||
|
||||
painter = xrdp_painter_create(self->wm, self->wm->session);
|
||||
xrdp_painter_font_needed(painter);
|
||||
font_height = xrdp_painter_font_body_height(painter);
|
||||
painter->rop = 0xcc; /* copy */
|
||||
|
||||
if (rect == 0)
|
||||
|
@ -684,14 +690,16 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
|
|||
{
|
||||
/* active title bar */
|
||||
painter->fg_color = self->wm->blue;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3,
|
||||
self->width - 5, font_height + 5);
|
||||
painter->fg_color = self->wm->white;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* inactive title bar */
|
||||
painter->fg_color = self->wm->dark_grey;
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3, self->width - 5, 18);
|
||||
xrdp_painter_fill_rect(painter, self, 3, 3,
|
||||
self->width - 5, font_height + 5);
|
||||
painter->fg_color = self->wm->black;
|
||||
}
|
||||
|
||||
|
@ -742,7 +750,7 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
|
|||
xrdp_bitmap_draw_button(self, painter, 0, 0,
|
||||
self->width, self->height, 0);
|
||||
w = xrdp_painter_text_width(painter, self->caption1);
|
||||
h = xrdp_painter_text_height(painter, self->caption1);
|
||||
h = xrdp_painter_font_body_height(painter);
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_draw_text(painter, self, self->width / 2 - w / 2,
|
||||
self->height / 2 - h / 2, self->caption1);
|
||||
|
@ -764,7 +772,7 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
|
|||
xrdp_bitmap_draw_button(self, painter, 0, 0,
|
||||
self->width, self->height, 1);
|
||||
w = xrdp_painter_text_width(painter, self->caption1);
|
||||
h = xrdp_painter_text_height(painter, self->caption1);
|
||||
h = xrdp_painter_font_body_height(painter);
|
||||
painter->fg_color = self->wm->black;
|
||||
xrdp_painter_draw_text(painter, self, (self->width / 2 - w / 2) + 1,
|
||||
(self->height / 2 - h / 2) + 1, self->caption1);
|
||||
|
@ -941,7 +949,7 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
|
|||
if (self->popped_from != 0)
|
||||
{
|
||||
/* change height if there are too many items in the list */
|
||||
i = xrdp_painter_text_height(painter, "W");
|
||||
i = xrdp_painter_font_body_height(painter);
|
||||
i = self->popped_from->string_list->count * i;
|
||||
|
||||
if (i > self->height)
|
||||
|
@ -961,7 +969,7 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
|
|||
for (i = 0; i < self->popped_from->string_list->count; i++)
|
||||
{
|
||||
p = (char *)list_get_item(self->popped_from->string_list, i);
|
||||
h = xrdp_painter_text_height(painter, p);
|
||||
h = xrdp_painter_font_body_height(painter);
|
||||
self->item_height = h;
|
||||
|
||||
if (i == self->item_index)
|
||||
|
|
212
xrdp/xrdp_font.c
212
xrdp/xrdp_font.c
|
@ -18,56 +18,127 @@
|
|||
* fonts
|
||||
*/
|
||||
|
||||
/*
|
||||
The fv1 files contain
|
||||
Font File Header (just one)
|
||||
FNT1 4 bytes
|
||||
Font Name 32 bytes
|
||||
Font Size 2 bytes
|
||||
Font Style 2 bytes
|
||||
Pad 8 bytes
|
||||
Font Data (repeats)
|
||||
Width 2 bytes
|
||||
Height 2 bytes
|
||||
Baseline 2 bytes
|
||||
Offset 2 bytes
|
||||
Incby 2 bytes
|
||||
Pad 6 bytes
|
||||
Glyph Data var, see FONT_DATASIZE macro
|
||||
*/
|
||||
/* fv1 files are described in fontutils/README_fv1.txt */
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "xrdp.h"
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
#if 0 /* not used */
|
||||
static char w_char[] =
|
||||
{
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x08, 0x20, 0x80,
|
||||
0x08, 0x50, 0x80,
|
||||
0x04, 0x51, 0x00,
|
||||
0x04, 0x51, 0x00,
|
||||
0x04, 0x51, 0x00,
|
||||
0x02, 0x8a, 0x00,
|
||||
0x02, 0x8a, 0x00,
|
||||
0x02, 0x8a, 0x00,
|
||||
0x01, 0x04, 0x00,
|
||||
0x01, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, // ........................
|
||||
0x00, 0x00, 0x00, // ........................
|
||||
0x00, 0x00, 0x00, // ........................
|
||||
0x08, 0x20, 0x80, // ....X.....X.....X.......
|
||||
0x08, 0x50, 0x80, // ....X....X.X....X.......
|
||||
0x04, 0x51, 0x00, // .....X...X.X...X........
|
||||
0x04, 0x51, 0x00, // .....X...X.X...X........
|
||||
0x04, 0x51, 0x00, // .....X...X.X...X........
|
||||
0x02, 0x8a, 0x00, // ......X.X...X.X.........
|
||||
0x02, 0x8a, 0x00, // ......X.X...X.X.........
|
||||
0x02, 0x8a, 0x00, // ......X.X...X.X.........
|
||||
0x01, 0x04, 0x00, // .......X.....X..........
|
||||
0x01, 0x04, 0x00, // .......X.....X..........
|
||||
0x00, 0x00, 0x00, // ........................
|
||||
0x00, 0x00, 0x00, // ........................
|
||||
0x00, 0x00, 0x00, // ........................
|
||||
};
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Parses the fv1_select configuration value to get the font to use,
|
||||
* based on the DPI of the primary monitor
|
||||
*
|
||||
* @param globals Configuration globals
|
||||
* @param dpi DPI of primary monitor. If not known, a suitable
|
||||
* default should be passed in here.
|
||||
* @param[out] font_name Name of font to use
|
||||
* @param[in] font_name_len Length of font name buffer
|
||||
*/
|
||||
static void
|
||||
get_font_name_from_dpi(const struct xrdp_cfg_globals *globals,
|
||||
unsigned int dpi,
|
||||
char *font_name, int font_name_len)
|
||||
{
|
||||
int bad_selector = 0;
|
||||
|
||||
font_name[0] = '\0';
|
||||
|
||||
const char *fv1_select = globals->fv1_select;
|
||||
if (fv1_select == NULL || fv1_select[0] == '\0')
|
||||
{
|
||||
fv1_select = DEFAULT_FV1_SELECT;
|
||||
}
|
||||
|
||||
const char *p = fv1_select;
|
||||
|
||||
while (p != NULL)
|
||||
{
|
||||
/* DPI value must be next in string */
|
||||
if (!isdigit(*p))
|
||||
{
|
||||
bad_selector = 1;
|
||||
break;
|
||||
}
|
||||
unsigned int field_dpi = g_atoi(p);
|
||||
if (field_dpi <= dpi)
|
||||
{
|
||||
/* Use this font */
|
||||
p = g_strchr(p, ':');
|
||||
if (p == NULL)
|
||||
{
|
||||
bad_selector = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++p;
|
||||
const char *q = g_strchr(p, ',');
|
||||
if (q == NULL)
|
||||
{
|
||||
q = p + g_strlen(p);
|
||||
}
|
||||
if (q - p > (font_name_len - 1))
|
||||
{
|
||||
q = p + font_name_len - 1;
|
||||
}
|
||||
g_memcpy(font_name, p, q - p);
|
||||
font_name[q - p] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = g_strchr(p, ',');
|
||||
if (p != NULL)
|
||||
{
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bad_selector)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Unable to parse fv1_select configuration");
|
||||
}
|
||||
|
||||
if (font_name[0] == '\0')
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Loading default font " DEFAULT_FONT_NAME);
|
||||
g_snprintf(font_name, font_name_len, DEFAULT_FONT_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_font *
|
||||
xrdp_font_create(struct xrdp_wm *wm)
|
||||
xrdp_font_create(struct xrdp_wm *wm, unsigned int dpi)
|
||||
{
|
||||
struct xrdp_font *self;
|
||||
struct stream *s;
|
||||
|
@ -78,16 +149,52 @@ xrdp_font_create(struct xrdp_wm *wm)
|
|||
int datasize;
|
||||
int file_size;
|
||||
struct xrdp_font_char *f;
|
||||
char file_path[256];
|
||||
|
||||
const char *file_path;
|
||||
char file_path_buff[256];
|
||||
int min_descender;
|
||||
char font_name[256];
|
||||
const struct xrdp_cfg_globals *globals = &wm->xrdp_config->cfg_globals;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_font_create");
|
||||
g_snprintf(file_path, 255, "%s/%s", XRDP_SHARE_PATH, DEFAULT_FONT_NAME);
|
||||
|
||||
if (dpi == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "No DPI value is available to find login font");
|
||||
dpi = globals->default_dpi;
|
||||
LOG(LOG_LEVEL_WARNING, "Using the default_dpi of %u", dpi);
|
||||
}
|
||||
get_font_name_from_dpi(globals, dpi, font_name, sizeof(font_name));
|
||||
|
||||
if (font_name[0] == '/')
|
||||
{
|
||||
/* User specified absolute path */
|
||||
file_path = font_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(file_path_buff, sizeof(file_path_buff),
|
||||
XRDP_SHARE_PATH "/%s",
|
||||
font_name);
|
||||
file_path = file_path_buff;
|
||||
}
|
||||
|
||||
if (!g_file_exist(file_path))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_font_create: error font file [%s] does not exist",
|
||||
file_path);
|
||||
return 0;
|
||||
/* Try to fall back to the default */
|
||||
const char *default_file_path = XRDP_SHARE_PATH "/" DEFAULT_FONT_NAME;
|
||||
if (g_file_exist(default_file_path))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"xrdp_font_create: font file [%s] does not exist - using [%s]",
|
||||
file_path, default_file_path);
|
||||
file_path = default_file_path;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_font_create: Can't load either [%s] or [%s]",
|
||||
file_path, default_file_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
file_size = g_file_get_size(file_path);
|
||||
|
@ -117,7 +224,9 @@ xrdp_font_create(struct xrdp_wm *wm)
|
|||
in_uint8a(s, self->name, 32);
|
||||
in_uint16_le(s, self->size);
|
||||
in_uint16_le(s, self->style);
|
||||
in_uint8s(s, 8);
|
||||
in_uint16_le(s, self->body_height);
|
||||
in_sint16_le(s, min_descender);
|
||||
in_uint8s(s, 4);
|
||||
index = 32;
|
||||
|
||||
while (s_check_rem(s, 16))
|
||||
|
@ -128,7 +237,8 @@ xrdp_font_create(struct xrdp_wm *wm)
|
|||
in_sint16_le(s, i);
|
||||
f->height = i;
|
||||
in_sint16_le(s, i);
|
||||
f->baseline = i;
|
||||
/* Move the glyph up so there are no descenders */
|
||||
f->baseline = i + min_descender;
|
||||
in_sint16_le(s, i);
|
||||
f->offset = i;
|
||||
in_sint16_le(s, i);
|
||||
|
@ -145,7 +255,15 @@ xrdp_font_create(struct xrdp_wm *wm)
|
|||
break;
|
||||
}
|
||||
|
||||
if (s_check_rem(s, datasize))
|
||||
if (datasize == 0)
|
||||
{
|
||||
/* Allocate a single blank pixel for the glyph, so
|
||||
* that it can be added to the glyph cache if required */
|
||||
f->width = 1;
|
||||
f->height = 1;
|
||||
f->data = (char *)g_malloc(1, 1);
|
||||
}
|
||||
else if (s_check_rem(s, datasize))
|
||||
{
|
||||
f->data = (char *)g_malloc(datasize, 0);
|
||||
in_uint8a(s, f->data, datasize);
|
||||
|
@ -154,9 +272,15 @@ xrdp_font_create(struct xrdp_wm *wm)
|
|||
{
|
||||
LOG(LOG_LEVEL_ERROR, "error in xrdp_font_create");
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (self->body_height == 0 && index > 32)
|
||||
{
|
||||
/* Older font made for xrdp v0.9.x. Synthesise this
|
||||
* value from the first glyph */
|
||||
self->body_height = -self->font_items[32].baseline + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,20 +72,32 @@ xrdp_wm_login_help_notify(struct xrdp_bitmap *wnd,
|
|||
|
||||
if (p != 0)
|
||||
{
|
||||
const int x = 10;
|
||||
int y = xrdp_painter_font_body_height(p) * 2;
|
||||
const int row_height = xrdp_painter_font_body_height(p);
|
||||
const int end_para_height = row_height * 3 / 2;
|
||||
|
||||
p->fg_color = wnd->wm->black;
|
||||
xrdp_painter_draw_text(p, wnd, 10, 30, "You must be authenticated \
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "You must be authenticated \
|
||||
before using this");
|
||||
xrdp_painter_draw_text(p, wnd, 10, 46, "session.");
|
||||
xrdp_painter_draw_text(p, wnd, 10, 78, "Enter a valid username in \
|
||||
y += row_height;
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "session.");
|
||||
y += end_para_height;
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "Enter a valid username in \
|
||||
the username edit box.");
|
||||
xrdp_painter_draw_text(p, wnd, 10, 94, "Enter the password in \
|
||||
y += end_para_height;
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "Enter the password in \
|
||||
the password edit box.");
|
||||
xrdp_painter_draw_text(p, wnd, 10, 110, "Both the username and \
|
||||
y += end_para_height;
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "Both the username and \
|
||||
password are case");
|
||||
xrdp_painter_draw_text(p, wnd, 10, 126, "sensitive.");
|
||||
xrdp_painter_draw_text(p, wnd, 10, 158, "Contact your system \
|
||||
y += row_height;
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "sensitive.");
|
||||
y += end_para_height;
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "Contact your system \
|
||||
administrator if you are");
|
||||
xrdp_painter_draw_text(p, wnd, 10, 174, "having problems \
|
||||
y += row_height;
|
||||
xrdp_painter_draw_text(p, wnd, x, y, "having problems \
|
||||
logging on.");
|
||||
}
|
||||
}
|
||||
|
@ -147,9 +159,23 @@ xrdp_wm_help_clicked(struct xrdp_bitmap *wnd)
|
|||
{
|
||||
struct xrdp_bitmap *help;
|
||||
struct xrdp_bitmap *but;
|
||||
const int width =
|
||||
wnd->wm->xrdp_config->cfg_globals.ls_scaled.help_wnd_width;
|
||||
const int height =
|
||||
wnd->wm->xrdp_config->cfg_globals.ls_scaled.help_wnd_height;
|
||||
const int ok_height =
|
||||
wnd->wm->xrdp_config->cfg_globals.ls_scaled.default_btn_height;
|
||||
const char *ok_string = "OK";
|
||||
|
||||
/* Get a width for the OK button */
|
||||
struct xrdp_painter *p = xrdp_painter_create(wnd->wm, wnd->wm->session);
|
||||
xrdp_painter_font_needed(p);
|
||||
const int ok_width = xrdp_painter_text_width(p, ok_string) +
|
||||
DEFAULT_BUTTON_MARGIN_W;
|
||||
xrdp_painter_delete(p);
|
||||
|
||||
/* create help screen */
|
||||
help = xrdp_bitmap_create(DEFAULT_WND_HELP_W, DEFAULT_WND_HELP_H, wnd->wm->screen->bpp,
|
||||
help = xrdp_bitmap_create(width, height, wnd->wm->screen->bpp,
|
||||
WND_TYPE_WND, wnd->wm);
|
||||
list_insert_item(wnd->wm->screen->child_list, 0, (long)help);
|
||||
help->parent = wnd->wm->screen;
|
||||
|
@ -161,16 +187,16 @@ xrdp_wm_help_clicked(struct xrdp_bitmap *wnd)
|
|||
help->notify = xrdp_wm_login_help_notify;
|
||||
set_string(&help->caption1, "Login help");
|
||||
/* ok button */
|
||||
but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, wnd->wm->screen->bpp,
|
||||
but = xrdp_bitmap_create(ok_width, ok_height, wnd->wm->screen->bpp,
|
||||
WND_TYPE_BUTTON, wnd->wm);
|
||||
list_insert_item(help->child_list, 0, (long)but);
|
||||
but->parent = help;
|
||||
but->owner = help;
|
||||
but->left = ((DEFAULT_WND_HELP_W / 2) - (DEFAULT_BUTTON_W / 2)); /* center */
|
||||
but->top = DEFAULT_WND_HELP_H - DEFAULT_BUTTON_H - 15;
|
||||
but->left = ((help->width / 2) - (ok_width / 2)); /* center */
|
||||
but->top = help->height - ok_height - 15;
|
||||
but->id = 1;
|
||||
but->tab_stop = 1;
|
||||
set_string(&but->caption1, "OK");
|
||||
set_string(&but->caption1, ok_string);
|
||||
/* draw it */
|
||||
help->focused_control = but;
|
||||
help->default_button = but;
|
||||
|
@ -387,32 +413,40 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
|
|||
}
|
||||
else if (g_strncmp(ASK, value, ASK_LEN) == 0)
|
||||
{
|
||||
const int combo_height =
|
||||
self->xrdp_config->cfg_globals.ls_scaled.combo_height;
|
||||
const int edit_height =
|
||||
self->xrdp_config->cfg_globals.ls_scaled.edit_height;
|
||||
/* label */
|
||||
b = xrdp_bitmap_create(globals->ls_label_width, DEFAULT_EDIT_H, self->screen->bpp,
|
||||
b = xrdp_bitmap_create(globals->ls_scaled.label_width,
|
||||
edit_height, self->screen->bpp,
|
||||
WND_TYPE_LABEL, self);
|
||||
list_insert_item(self->login_window->child_list, insert_index,
|
||||
(long)b);
|
||||
insert_index++;
|
||||
b->parent = self->login_window;
|
||||
b->owner = self->login_window;
|
||||
b->left = globals->ls_label_x_pos;
|
||||
b->left = globals->ls_scaled.label_x_pos;
|
||||
|
||||
b->top = globals->ls_input_y_pos + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count;
|
||||
b->top = globals->ls_scaled.input_y_pos + combo_height + 5 +
|
||||
(edit_height + 5) * count;
|
||||
b->id = 100 + 2 * count;
|
||||
name = (char *)list_get_item(mod->names, index);
|
||||
set_string(&b->caption1, name);
|
||||
|
||||
/* edit */
|
||||
b = xrdp_bitmap_create(globals->ls_input_width, DEFAULT_EDIT_H, self->screen->bpp,
|
||||
b = xrdp_bitmap_create(globals->ls_scaled.input_width,
|
||||
edit_height, self->screen->bpp,
|
||||
WND_TYPE_EDIT, self);
|
||||
list_insert_item(self->login_window->child_list, insert_index,
|
||||
(long)b);
|
||||
insert_index++;
|
||||
b->parent = self->login_window;
|
||||
b->owner = self->login_window;
|
||||
b->left = globals->ls_input_x_pos;
|
||||
b->left = globals->ls_scaled.input_x_pos;
|
||||
|
||||
b->top = globals->ls_input_y_pos + DEFAULT_COMBO_H + 5 + (DEFAULT_EDIT_H + 5) * count;
|
||||
b->top = globals->ls_scaled.input_y_pos + combo_height + 5 +
|
||||
(edit_height + 5) * count;
|
||||
|
||||
b->id = 100 + 2 * count + 1;
|
||||
b->pointer = 1;
|
||||
|
@ -634,6 +668,81 @@ xrdp_wm_login_fill_in_combo(struct xrdp_wm *self, struct xrdp_bitmap *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
unsigned int
|
||||
xrdp_login_wnd_get_monitor_dpi(struct xrdp_wm *self)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
const struct display_size_description *display_sizes =
|
||||
&self->client_info->display_sizes;
|
||||
unsigned int height_pixels = 0;
|
||||
unsigned int height_mm = 0;
|
||||
|
||||
unsigned int i;
|
||||
|
||||
/* Look at the monitor data first */
|
||||
for (i = 0; i < display_sizes->monitorCount; ++i)
|
||||
{
|
||||
const struct monitor_info *mi = &display_sizes->minfo_wm[i];
|
||||
{
|
||||
if (mi->is_primary)
|
||||
{
|
||||
height_pixels = mi->bottom - mi->top + 1;
|
||||
height_mm = mi->physical_height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No primary monitor, or values not defined - use the desktop size */
|
||||
if (height_mm == 0)
|
||||
{
|
||||
height_pixels = display_sizes->session_height;
|
||||
height_mm = self->client_info->session_physical_height;
|
||||
|
||||
if (height_mm == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"No information is available to determine login screen DPI");
|
||||
}
|
||||
else if (height_pixels < 768)
|
||||
{
|
||||
/* A bug was encountered with mstsc.exe version
|
||||
10.0.19041.1682 where the full physical monitor size was
|
||||
sent in TS_UD_CS_CORE when the desktop size was set to
|
||||
less than the screen size.
|
||||
To generate the bug, make a connection with a full-screen
|
||||
single window, cancel the login, and reconnect at
|
||||
(e.g.) 800x600.
|
||||
We can't detect that exact situation here, but if the
|
||||
session height is so small as to likely be in a window
|
||||
(rather than full screen), we should ignore the physical
|
||||
size */
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Ignoring unlikely physical session size %u "
|
||||
"for height of %u pixels", height_mm, height_pixels);
|
||||
height_mm = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (height_mm != 0)
|
||||
{
|
||||
/*
|
||||
* DPI = height_pixels / (height_mm / 25.4)
|
||||
* = (height_pixels * 25.4) / height_mm
|
||||
* = (height_pixels * 127) / (height_mm * 5)
|
||||
*/
|
||||
result = (height_pixels * 127 ) / (height_mm * 5);
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Login screen monitor height is %u pixels over %u mm (%u DPI)",
|
||||
height_pixels,
|
||||
height_mm,
|
||||
result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
xrdp_login_wnd_create(struct xrdp_wm *self)
|
||||
|
@ -657,6 +766,10 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
|||
int y;
|
||||
int cx;
|
||||
int cy;
|
||||
const int combo_height =
|
||||
self->xrdp_config->cfg_globals.ls_scaled.combo_height;
|
||||
const int edit_height =
|
||||
self->xrdp_config->cfg_globals.ls_scaled.edit_height;
|
||||
|
||||
globals = &self->xrdp_config->cfg_globals;
|
||||
|
||||
|
@ -665,8 +778,8 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
|||
primary_x_offset = primary_width / 2;
|
||||
primary_y_offset = primary_height / 2;
|
||||
|
||||
log_width = globals->ls_width;
|
||||
log_height = globals->ls_height;
|
||||
log_width = globals->ls_scaled.width;
|
||||
log_height = globals->ls_scaled.height;
|
||||
regular = 1;
|
||||
|
||||
if (self->screen->width < log_width)
|
||||
|
@ -811,58 +924,61 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
|
|||
xrdp_bitmap_load(but, globals->ls_logo_filename, self->palette,
|
||||
globals->ls_bg_color,
|
||||
globals->ls_logo_transform,
|
||||
globals->ls_logo_width,
|
||||
globals->ls_logo_height);
|
||||
globals->ls_scaled.logo_width,
|
||||
globals->ls_scaled.logo_height);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->left = globals->ls_logo_x_pos;
|
||||
but->top = globals->ls_logo_y_pos;
|
||||
but->left = globals->ls_scaled.logo_x_pos;
|
||||
but->top = globals->ls_scaled.logo_y_pos;
|
||||
list_add_item(self->login_window->child_list, (long)but);
|
||||
}
|
||||
|
||||
/* label */
|
||||
but = xrdp_bitmap_create(globals->ls_label_width, DEFAULT_EDIT_H, self->screen->bpp, WND_TYPE_LABEL, self);
|
||||
but = xrdp_bitmap_create(globals->ls_scaled.label_width, edit_height,
|
||||
self->screen->bpp, WND_TYPE_LABEL, self);
|
||||
list_add_item(self->login_window->child_list, (long)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->left = globals->ls_label_x_pos;
|
||||
but->top = globals->ls_input_y_pos;
|
||||
but->left = globals->ls_scaled.label_x_pos;
|
||||
but->top = globals->ls_scaled.input_y_pos;
|
||||
set_string(&but->caption1, "Session");
|
||||
|
||||
/* combo */
|
||||
combo = xrdp_bitmap_create(globals->ls_input_width, DEFAULT_COMBO_H,
|
||||
combo = xrdp_bitmap_create(globals->ls_scaled.input_width, combo_height,
|
||||
self->screen->bpp, WND_TYPE_COMBO, self);
|
||||
list_add_item(self->login_window->child_list, (long)combo);
|
||||
combo->parent = self->login_window;
|
||||
combo->owner = self->login_window;
|
||||
combo->left = globals->ls_input_x_pos;
|
||||
combo->top = globals->ls_input_y_pos;
|
||||
combo->left = globals->ls_scaled.input_x_pos;
|
||||
combo->top = globals->ls_scaled.input_y_pos;
|
||||
combo->id = 6;
|
||||
combo->tab_stop = 1;
|
||||
xrdp_wm_login_fill_in_combo(self, combo);
|
||||
|
||||
/* OK button */
|
||||
but = xrdp_bitmap_create(globals->ls_btn_ok_width, globals->ls_btn_ok_height,
|
||||
but = xrdp_bitmap_create(globals->ls_scaled.btn_ok_width,
|
||||
globals->ls_scaled.btn_ok_height,
|
||||
self->screen->bpp, WND_TYPE_BUTTON, self);
|
||||
list_add_item(self->login_window->child_list, (long)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->left = globals->ls_btn_ok_x_pos;
|
||||
but->top = globals->ls_btn_ok_y_pos;
|
||||
but->left = globals->ls_scaled.btn_ok_x_pos;
|
||||
but->top = globals->ls_scaled.btn_ok_y_pos;
|
||||
but->id = 3;
|
||||
set_string(&but->caption1, "OK");
|
||||
but->tab_stop = 1;
|
||||
self->login_window->default_button = but;
|
||||
|
||||
/* Cancel button */
|
||||
but = xrdp_bitmap_create(globals->ls_btn_cancel_width,
|
||||
globals->ls_btn_cancel_height, self->screen->bpp,
|
||||
but = xrdp_bitmap_create(globals->ls_scaled.btn_cancel_width,
|
||||
globals->ls_scaled.btn_cancel_height,
|
||||
self->screen->bpp,
|
||||
WND_TYPE_BUTTON, self);
|
||||
list_add_item(self->login_window->child_list, (long)but);
|
||||
but->parent = self->login_window;
|
||||
but->owner = self->login_window;
|
||||
but->left = globals->ls_btn_cancel_x_pos;
|
||||
but->top = globals->ls_btn_cancel_y_pos;
|
||||
but->left = globals->ls_scaled.btn_cancel_x_pos;
|
||||
but->top = globals->ls_scaled.btn_cancel_y_pos;
|
||||
but->id = 2;
|
||||
set_string(&but->caption1, "Cancel");
|
||||
but->tab_stop = 1;
|
||||
|
@ -948,27 +1064,39 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
|||
|
||||
/* set default values in case we can't get them from xrdp.ini file */
|
||||
globals->ini_version = 1;
|
||||
globals->default_dpi = 96;
|
||||
|
||||
globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi("009cb5"));
|
||||
globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi("dedede"));
|
||||
globals->ls_width = 350;
|
||||
globals->ls_height = 350;
|
||||
globals->ls_unscaled.width = 350;
|
||||
globals->ls_unscaled.height = 350;
|
||||
globals->ls_background_transform = XBLT_NONE;
|
||||
globals->ls_logo_transform = XBLT_NONE;
|
||||
globals->ls_logo_x_pos = 63;
|
||||
globals->ls_logo_y_pos = 50;
|
||||
globals->ls_label_x_pos = 30;
|
||||
globals->ls_label_width = 65;
|
||||
globals->ls_input_x_pos = 110;
|
||||
globals->ls_input_width = 210;
|
||||
globals->ls_input_y_pos = 150;
|
||||
globals->ls_btn_ok_x_pos = 150;
|
||||
globals->ls_btn_ok_y_pos = 300;
|
||||
globals->ls_btn_ok_width = 85;
|
||||
globals->ls_btn_ok_height = 30;
|
||||
globals->ls_btn_cancel_x_pos = 245;
|
||||
globals->ls_btn_cancel_y_pos = 300;
|
||||
globals->ls_btn_cancel_width = 85;
|
||||
globals->ls_btn_cancel_height = 30;
|
||||
globals->ls_unscaled.logo_x_pos = 63;
|
||||
globals->ls_unscaled.logo_y_pos = 50;
|
||||
globals->ls_unscaled.label_x_pos = 30;
|
||||
globals->ls_unscaled.label_width = 65;
|
||||
globals->ls_unscaled.input_x_pos = 110;
|
||||
globals->ls_unscaled.input_width = 210;
|
||||
globals->ls_unscaled.input_y_pos = 150;
|
||||
globals->ls_unscaled.btn_ok_x_pos = 150;
|
||||
globals->ls_unscaled.btn_ok_y_pos = 300;
|
||||
globals->ls_unscaled.btn_ok_width = 85;
|
||||
globals->ls_unscaled.btn_ok_height = 30;
|
||||
globals->ls_unscaled.btn_cancel_x_pos = 245;
|
||||
globals->ls_unscaled.btn_cancel_y_pos = 300;
|
||||
globals->ls_unscaled.btn_cancel_width = 85;
|
||||
globals->ls_unscaled.btn_cancel_height = 30;
|
||||
globals->ls_unscaled.default_btn_height =
|
||||
DEFAULT_FONT_PIXEL_SIZE + DEFAULT_BUTTON_MARGIN_H;
|
||||
globals->ls_unscaled.log_wnd_width = DEFAULT_WND_LOG_W;
|
||||
globals->ls_unscaled.log_wnd_height = DEFAULT_WND_LOG_H;
|
||||
globals->ls_unscaled.edit_height =
|
||||
DEFAULT_FONT_PIXEL_SIZE + DEFAULT_EDIT_MARGIN_H;
|
||||
globals->ls_unscaled.combo_height =
|
||||
DEFAULT_FONT_PIXEL_SIZE + DEFAULT_COMBO_MARGIN_H;
|
||||
globals->ls_unscaled.help_wnd_width = DEFAULT_WND_HELP_W;
|
||||
globals->ls_unscaled.help_wnd_height = DEFAULT_WND_HELP_H;
|
||||
|
||||
/* open xrdp.ini file */
|
||||
if ((fd = g_file_open(xrdp_ini)) < 0)
|
||||
|
@ -1165,6 +1293,16 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
|||
}
|
||||
|
||||
/* login screen values */
|
||||
else if (g_strcmp(n, "default_dpi") == 0)
|
||||
{
|
||||
globals->default_dpi = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strcmp(n, "fv1_select") == 0)
|
||||
{
|
||||
g_strncpy(globals->fv1_select, v, sizeof(globals->fv1_select) - 1);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_top_window_bg_color", 64) == 0)
|
||||
{
|
||||
globals->ls_top_window_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v));
|
||||
|
@ -1172,12 +1310,12 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
|||
|
||||
else if (g_strncmp(n, "ls_width", 64) == 0)
|
||||
{
|
||||
globals->ls_width = g_atoi(v);
|
||||
globals->ls_unscaled.width = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_height", 64) == 0)
|
||||
{
|
||||
globals->ls_height = g_atoi(v);
|
||||
globals->ls_unscaled.height = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_bg_color", 64) == 0)
|
||||
|
@ -1216,87 +1354,87 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
|||
|
||||
else if (g_strncmp(n, "ls_logo_width", 64) == 0)
|
||||
{
|
||||
globals->ls_logo_width = g_atoi(v);
|
||||
globals->ls_unscaled.logo_width = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_height", 64) == 0)
|
||||
{
|
||||
globals->ls_logo_height = g_atoi(v);
|
||||
globals->ls_unscaled.logo_height = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_x_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_logo_x_pos = g_atoi(v);
|
||||
globals->ls_unscaled.logo_x_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_logo_y_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_logo_y_pos = g_atoi(v);
|
||||
globals->ls_unscaled.logo_y_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_label_x_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_label_x_pos = g_atoi(v);
|
||||
globals->ls_unscaled.label_x_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_label_width", 64) == 0)
|
||||
{
|
||||
globals->ls_label_width = g_atoi(v);
|
||||
globals->ls_unscaled.label_width = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_input_x_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_input_x_pos = g_atoi(v);
|
||||
globals->ls_unscaled.input_x_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_input_width", 64) == 0)
|
||||
{
|
||||
globals->ls_input_width = g_atoi(v);
|
||||
globals->ls_unscaled.input_width = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_input_y_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_input_y_pos = g_atoi(v);
|
||||
globals->ls_unscaled.input_y_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_ok_x_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_ok_x_pos = g_atoi(v);
|
||||
globals->ls_unscaled.btn_ok_x_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_ok_y_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_ok_y_pos = g_atoi(v);
|
||||
globals->ls_unscaled.btn_ok_y_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_ok_width", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_ok_width = g_atoi(v);
|
||||
globals->ls_unscaled.btn_ok_width = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_ok_height", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_ok_height = g_atoi(v);
|
||||
globals->ls_unscaled.btn_ok_height = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_cancel_x_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_cancel_x_pos = g_atoi(v);
|
||||
globals->ls_unscaled.btn_cancel_x_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_cancel_y_pos", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_cancel_y_pos = g_atoi(v);
|
||||
globals->ls_unscaled.btn_cancel_y_pos = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_cancel_width", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_cancel_width = g_atoi(v);
|
||||
globals->ls_unscaled.btn_cancel_width = g_atoi(v);
|
||||
}
|
||||
|
||||
else if (g_strncmp(n, "ls_btn_cancel_height", 64) == 0)
|
||||
{
|
||||
globals->ls_btn_cancel_height = g_atoi(v);
|
||||
globals->ls_unscaled.btn_cancel_height = g_atoi(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1335,29 +1473,95 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
|||
LOG(LOG_LEVEL_DEBUG, "enable_token_login: %d", globals->enable_token_login);
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_top_window_bg_color: %x", globals->ls_top_window_bg_color);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_width: %d", globals->ls_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_height: %d", globals->ls_height);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_width (unscaled): %d", globals->ls_unscaled.width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_height (unscaled): %d", globals->ls_unscaled.height);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_bg_color: %x", globals->ls_bg_color);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_title: %s", globals->ls_title);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_logo_filename: %s", globals->ls_logo_filename);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_logo_x_pos: %d", globals->ls_logo_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_logo_y_pos: %d", globals->ls_logo_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_label_x_pos: %d", globals->ls_label_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_label_width: %d", globals->ls_label_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_input_x_pos: %d", globals->ls_input_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_input_width: %d", globals->ls_input_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_input_y_pos: %d", globals->ls_input_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_x_pos: %d", globals->ls_btn_ok_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_y_pos: %d", globals->ls_btn_ok_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_width: %d", globals->ls_btn_ok_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_height: %d", globals->ls_btn_ok_height);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_x_pos: %d", globals->ls_btn_cancel_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_y_pos: %d", globals->ls_btn_cancel_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_width: %d", globals->ls_btn_cancel_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_height: %d", globals->ls_btn_cancel_height);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_logo_x_pos : %d", globals->ls_unscaled.logo_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_logo_y_pos : %d", globals->ls_unscaled.logo_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_label_x_pos : %d", globals->ls_unscaled.label_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_label_width : %d", globals->ls_unscaled.label_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_input_x_pos : %d", globals->ls_unscaled.input_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_input_width : %d", globals->ls_unscaled.input_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_input_y_pos : %d", globals->ls_unscaled.input_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_x_pos : %d", globals->ls_unscaled.btn_ok_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_y_pos : %d", globals->ls_unscaled.btn_ok_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_width : %d", globals->ls_unscaled.btn_ok_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_ok_height : %d", globals->ls_unscaled.btn_ok_height);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_x_pos : %d", globals->ls_unscaled.btn_cancel_x_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_y_pos : %d", globals->ls_unscaled.btn_cancel_y_pos);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_width : %d", globals->ls_unscaled.btn_cancel_width);
|
||||
LOG(LOG_LEVEL_DEBUG, "ls_btn_cancel_height : %d", globals->ls_unscaled.btn_cancel_height);
|
||||
|
||||
list_delete(names);
|
||||
list_delete(values);
|
||||
g_file_close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale the configuration values
|
||||
*
|
||||
* After a font has been loaded, we can produce scaled versions of the
|
||||
* login screen layout parameters which will correspond to the size of the
|
||||
* font
|
||||
*/
|
||||
void
|
||||
xrdp_login_wnd_scale_config_values(struct xrdp_wm *self)
|
||||
{
|
||||
const struct xrdp_ls_dimensions *unscaled =
|
||||
&self->xrdp_config->cfg_globals.ls_unscaled;
|
||||
struct xrdp_ls_dimensions *scaled =
|
||||
&self->xrdp_config->cfg_globals.ls_scaled;
|
||||
|
||||
/* Clear the scaled values, so if we add one and forget to scale it,
|
||||
* it will be obvious */
|
||||
g_memset(scaled, '\0', sizeof(*scaled));
|
||||
|
||||
/* If we don't have a font, use zeros for everything */
|
||||
if (self->default_font == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't scale login values - no font available");
|
||||
}
|
||||
else
|
||||
{
|
||||
const int fheight = self->default_font->body_height;
|
||||
/* Define a Macro to scale to the nearest pixel value,
|
||||
* rounding up as appropriate */
|
||||
#define SCALE_AND_ROUND(x) \
|
||||
(((x) * fheight + (DEFAULT_FONT_PIXEL_SIZE / 2)) / \
|
||||
DEFAULT_FONT_PIXEL_SIZE)
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "Login screen scale factor %f",
|
||||
(float)fheight / DEFAULT_FONT_PIXEL_SIZE);
|
||||
|
||||
scaled->width = SCALE_AND_ROUND(unscaled->width);
|
||||
scaled->height = SCALE_AND_ROUND(unscaled->height);
|
||||
scaled->logo_width = SCALE_AND_ROUND(unscaled->logo_width);
|
||||
scaled->logo_height = SCALE_AND_ROUND(unscaled->logo_height);
|
||||
scaled->logo_x_pos = SCALE_AND_ROUND(unscaled->logo_x_pos);
|
||||
scaled->logo_y_pos = SCALE_AND_ROUND(unscaled->logo_y_pos);
|
||||
scaled->label_x_pos = SCALE_AND_ROUND(unscaled->label_x_pos);
|
||||
scaled->label_width = SCALE_AND_ROUND(unscaled->label_width);
|
||||
scaled->input_x_pos = SCALE_AND_ROUND(unscaled->input_x_pos);
|
||||
scaled->input_width = SCALE_AND_ROUND(unscaled->input_width);
|
||||
scaled->input_y_pos = SCALE_AND_ROUND(unscaled->input_y_pos);
|
||||
scaled->btn_ok_x_pos = SCALE_AND_ROUND(unscaled->btn_ok_x_pos);
|
||||
scaled->btn_ok_y_pos = SCALE_AND_ROUND(unscaled->btn_ok_y_pos);
|
||||
scaled->btn_ok_width = SCALE_AND_ROUND(unscaled->btn_ok_width);
|
||||
scaled->btn_ok_height = SCALE_AND_ROUND(unscaled->btn_ok_height);
|
||||
scaled->btn_cancel_x_pos = SCALE_AND_ROUND(unscaled->btn_cancel_x_pos);
|
||||
scaled->btn_cancel_y_pos = SCALE_AND_ROUND(unscaled->btn_cancel_y_pos);
|
||||
scaled->btn_cancel_width = SCALE_AND_ROUND(unscaled->btn_cancel_width);
|
||||
scaled->btn_cancel_height = SCALE_AND_ROUND(unscaled->btn_cancel_height);
|
||||
scaled->default_btn_height = fheight + DEFAULT_BUTTON_MARGIN_H;
|
||||
scaled->log_wnd_width = SCALE_AND_ROUND(unscaled->log_wnd_width);
|
||||
scaled->log_wnd_height = SCALE_AND_ROUND(unscaled->log_wnd_height);
|
||||
scaled->edit_height = fheight + DEFAULT_EDIT_MARGIN_H;
|
||||
scaled->combo_height = fheight + DEFAULT_COMBO_MARGIN_H;
|
||||
scaled->help_wnd_width = SCALE_AND_ROUND(unscaled->help_wnd_width);
|
||||
scaled->help_wnd_height = SCALE_AND_ROUND(unscaled->help_wnd_height);
|
||||
#undef SCALE_AND_ROUND
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(XRDP_PAINTER)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -464,41 +463,10 @@ xrdp_painter_text_width(struct xrdp_painter *self, const char *text)
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
xrdp_painter_text_height(struct xrdp_painter *self, const char *text)
|
||||
unsigned int
|
||||
xrdp_painter_font_body_height(const struct xrdp_painter *self)
|
||||
{
|
||||
int index;
|
||||
int rv;
|
||||
int len;
|
||||
struct xrdp_font_char *font_item;
|
||||
twchar *wstr;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_text_height:");
|
||||
xrdp_painter_font_needed(self);
|
||||
|
||||
if (self->font == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (text == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
len = g_mbstowcs(0, text, 0);
|
||||
wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0);
|
||||
g_mbstowcs(wstr, text, len + 1);
|
||||
|
||||
for (index = 0; index < len; index++)
|
||||
{
|
||||
font_item = self->font->font_items + wstr[index];
|
||||
rv = MAX(rv, font_item->height);
|
||||
}
|
||||
|
||||
g_free(wstr);
|
||||
return rv;
|
||||
return (self->font == NULL) ? 0 : self->font->body_height;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -830,7 +798,6 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
len = g_mbstowcs(0, text, 0);
|
||||
|
||||
if (len < 1)
|
||||
|
@ -873,7 +840,11 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
|||
font_item = font->font_items + wstr[index];
|
||||
k = font_item->incby;
|
||||
total_width += k;
|
||||
total_height = MAX(total_height, font_item->height);
|
||||
/* Use the nominal height of the font to work out the
|
||||
* actual height of this glyph */
|
||||
int glyph_height =
|
||||
font->body_height + font_item->baseline + font_item->height;
|
||||
total_height = MAX(total_height, glyph_height);
|
||||
}
|
||||
xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
|
||||
region = xrdp_region_create(self->wm);
|
||||
|
@ -912,12 +883,12 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
|||
pat.height = font_item->height;
|
||||
pat.data = font_item->data;
|
||||
x1 = x + font_item->offset;
|
||||
y1 = y + (font_item->height + font_item->baseline);
|
||||
y1 = y + (font->body_height + font_item->baseline);
|
||||
painter_fill_pattern(self->painter, &dst_pb, &pat,
|
||||
0, 0, x1, y1,
|
||||
font_item->width,
|
||||
font_item->height);
|
||||
xrdp_painter_add_dirty_rect(self, x, y,
|
||||
xrdp_painter_add_dirty_rect(self, x1, y1,
|
||||
font_item->width,
|
||||
font_item->height,
|
||||
&draw_rect);
|
||||
|
@ -954,7 +925,11 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
|||
data[index * 2 + 1] = k;
|
||||
k = font_item->incby;
|
||||
total_width += k;
|
||||
total_height = MAX(total_height, font_item->height);
|
||||
/* Use the nominal height of the font to work out the
|
||||
* actual height of this glyph */
|
||||
int glyph_height =
|
||||
font->body_height + font_item->baseline + font_item->height;
|
||||
total_height = MAX(total_height, glyph_height);
|
||||
}
|
||||
|
||||
xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
|
||||
|
@ -979,7 +954,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
|
|||
if (rect_intersect(&rect, &clip_rect, &draw_rect))
|
||||
{
|
||||
x1 = x;
|
||||
y1 = y + total_height;
|
||||
y1 = y + font->body_height;
|
||||
flags = 0x03; /* 0x03 0x73; TEXT2_IMPLICIT_X and something else */
|
||||
libxrdp_orders_text(self->session, f, flags, 0,
|
||||
self->fg_color, 0,
|
||||
|
|
|
@ -605,12 +605,13 @@ struct xrdp_bitmap
|
|||
|
||||
#define NUM_FONTS 0x4e00
|
||||
#define DEFAULT_FONT_NAME "sans-10.fv1"
|
||||
#define DEFAULT_FONT_PIXEL_SIZE 16
|
||||
#define DEFAULT_FV1_SELECT "130:sans-18.fv1,0:" DEFAULT_FONT_NAME
|
||||
|
||||
#define DEFAULT_ELEMENT_TOP 35
|
||||
#define DEFAULT_BUTTON_W 60
|
||||
#define DEFAULT_BUTTON_H 23
|
||||
#define DEFAULT_COMBO_H 21
|
||||
#define DEFAULT_EDIT_H 21
|
||||
#define DEFAULT_BUTTON_MARGIN_H 12
|
||||
#define DEFAULT_BUTTON_MARGIN_W 12
|
||||
#define DEFAULT_COMBO_MARGIN_H 6
|
||||
#define DEFAULT_EDIT_MARGIN_H 6
|
||||
#define DEFAULT_WND_LOGIN_W 425
|
||||
#define DEFAULT_WND_LOGIN_H 475
|
||||
#define DEFAULT_WND_HELP_W 340
|
||||
|
@ -626,6 +627,8 @@ struct xrdp_font
|
|||
struct xrdp_font_char font_items[NUM_FONTS];
|
||||
char name[32];
|
||||
int size;
|
||||
/** Body height in pixels */
|
||||
int body_height;
|
||||
int style;
|
||||
};
|
||||
|
||||
|
@ -655,9 +658,39 @@ struct xrdp_startup_params
|
|||
};
|
||||
|
||||
/*
|
||||
* For storing xrdp.ini configuration settings
|
||||
* For storing xrdp.ini (and other) configuration settings
|
||||
*/
|
||||
|
||||
struct xrdp_ls_dimensions
|
||||
{
|
||||
int width; /* window width */
|
||||
int height; /* window height */
|
||||
int logo_width; /* logo width (optional) */
|
||||
int logo_height; /* logo height (optional) */
|
||||
int logo_x_pos; /* logo x co-ordinate */
|
||||
int logo_y_pos; /* logo y co-ordinate */
|
||||
int label_x_pos; /* x pos of labels */
|
||||
int label_width; /* width of labels */
|
||||
int input_x_pos; /* x pos of text and combo boxes */
|
||||
int input_width; /* width of input and combo boxes */
|
||||
int input_y_pos; /* y pos for for first label and combo box */
|
||||
int btn_ok_x_pos; /* x pos for OK button */
|
||||
int btn_ok_y_pos; /* y pos for OK button */
|
||||
int btn_ok_width; /* width of OK button */
|
||||
int btn_ok_height; /* height of OK button */
|
||||
int btn_cancel_x_pos; /* x pos for Cancel button */
|
||||
int btn_cancel_y_pos; /* y pos for Cancel button */
|
||||
int btn_cancel_width; /* width of Cancel button */
|
||||
int btn_cancel_height; /* height of Cancel button */
|
||||
int default_btn_height; /* Default button height (e.g. OK on login box) */
|
||||
int log_wnd_width; /* Width of log window */
|
||||
int log_wnd_height; /* Height of log window */
|
||||
int edit_height; /* Height of an edit box */
|
||||
int combo_height; /* Height of a combo box */
|
||||
int help_wnd_width; /* Width of login help window */
|
||||
int help_wnd_height; /* Height of login help window */
|
||||
};
|
||||
|
||||
struct xrdp_cfg_globals
|
||||
{
|
||||
int ini_version; /* xrdp.ini file version number */
|
||||
|
@ -694,34 +727,21 @@ struct xrdp_cfg_globals
|
|||
int background;
|
||||
|
||||
/* login screen */
|
||||
unsigned int default_dpi; /* Default DPI to use if nothing from client */
|
||||
char fv1_select[256]; /* Selection string for fv1 font */
|
||||
int ls_top_window_bg_color; /* top level window background color */
|
||||
int ls_width; /* window width */
|
||||
int ls_height; /* window height */
|
||||
int ls_bg_color; /* background color */
|
||||
char ls_background_image[256]; /* background image file name */
|
||||
enum xrdp_bitmap_load_transform ls_background_transform;
|
||||
/* transform to apply to background image */
|
||||
enum xrdp_bitmap_load_transform ls_background_transform;
|
||||
char ls_logo_filename[256]; /* logo filename */
|
||||
enum xrdp_bitmap_load_transform ls_logo_transform;
|
||||
/* transform to apply to logo */
|
||||
int ls_logo_width; /* logo width (optional) */
|
||||
int ls_logo_height; /* logo height (optional) */
|
||||
int ls_logo_x_pos; /* logo x coordinate */
|
||||
int ls_logo_y_pos; /* logo y coordinate */
|
||||
int ls_label_x_pos; /* x pos of labels */
|
||||
int ls_label_width; /* width of labels */
|
||||
int ls_input_x_pos; /* x pos of text and combo boxes */
|
||||
int ls_input_width; /* width of input and combo boxes */
|
||||
int ls_input_y_pos; /* y pos for for first label and combo box */
|
||||
int ls_btn_ok_x_pos; /* x pos for OK button */
|
||||
int ls_btn_ok_y_pos; /* y pos for OK button */
|
||||
int ls_btn_ok_width; /* width of OK button */
|
||||
int ls_btn_ok_height; /* height of OK button */
|
||||
int ls_btn_cancel_x_pos; /* x pos for Cancel button */
|
||||
int ls_btn_cancel_y_pos; /* y pos for Cancel button */
|
||||
int ls_btn_cancel_width; /* width of Cancel button */
|
||||
int ls_btn_cancel_height; /* height of Cancel button */
|
||||
enum xrdp_bitmap_load_transform ls_logo_transform;
|
||||
char ls_title[256]; /* loginscreen window title */
|
||||
/* Login screen dimensions, unscaled (from config) */
|
||||
struct xrdp_ls_dimensions ls_unscaled;
|
||||
/* Login screen dimensions, scaled (after font is loaded) */
|
||||
struct xrdp_ls_dimensions ls_scaled;
|
||||
};
|
||||
|
||||
struct xrdp_cfg_logging
|
||||
|
|
|
@ -62,7 +62,6 @@ xrdp_wm_create(struct xrdp_process *owner,
|
|||
self->log = list_create();
|
||||
self->log->auto_free = 1;
|
||||
self->mm = xrdp_mm_create(self);
|
||||
self->default_font = xrdp_font_create(self);
|
||||
/* this will use built in keymap or load from file */
|
||||
get_keymaps(self->session->client_info->keylayout, &(self->keymap));
|
||||
xrdp_wm_set_login_state(self, WMLS_RESET);
|
||||
|
@ -570,12 +569,20 @@ xrdp_wm_init(struct xrdp_wm *self)
|
|||
char default_section_name[256];
|
||||
char section_name[256];
|
||||
char autorun_name[256];
|
||||
int dpi;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "in xrdp_wm_init: ");
|
||||
|
||||
load_xrdp_config(self->xrdp_config, self->session->xrdp_ini,
|
||||
self->screen->bpp);
|
||||
|
||||
/* Load the font */
|
||||
dpi = xrdp_login_wnd_get_monitor_dpi(self);
|
||||
self->default_font = xrdp_font_create(self, dpi);
|
||||
|
||||
/* Scale the login screen values */
|
||||
xrdp_login_wnd_scale_config_values(self);
|
||||
|
||||
/* global channels allow */
|
||||
names = list_create();
|
||||
names->auto_free = 1;
|
||||
|
@ -2047,12 +2054,14 @@ xrdp_wm_log_wnd_notify(struct xrdp_bitmap *wnd,
|
|||
|
||||
if (painter != 0)
|
||||
{
|
||||
unsigned int row_height = xrdp_painter_font_body_height(painter);
|
||||
painter->fg_color = wnd->wm->black;
|
||||
|
||||
for (index = 0; index < wnd->wm->log->count; index++)
|
||||
{
|
||||
text = (char *)list_get_item(wnd->wm->log, index);
|
||||
xrdp_painter_draw_text(painter, wnd, 10, 30 + index * 15, text);
|
||||
xrdp_painter_draw_text(painter, wnd, 10,
|
||||
(index + 2) * row_height, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2102,8 +2111,9 @@ xrdp_wm_show_log(struct xrdp_wm *self)
|
|||
|
||||
if (self->log_wnd == 0)
|
||||
{
|
||||
w = DEFAULT_WND_LOG_W;
|
||||
h = DEFAULT_WND_LOG_H;
|
||||
w = self->xrdp_config->cfg_globals.ls_scaled.log_wnd_width;
|
||||
h = self->xrdp_config->cfg_globals.ls_scaled.log_wnd_height;
|
||||
|
||||
xoffset = 10;
|
||||
yoffset = 10;
|
||||
|
||||
|
@ -2147,12 +2157,19 @@ xrdp_wm_show_log(struct xrdp_wm *self)
|
|||
self->log_wnd->top = primary_y_offset + yoffset;
|
||||
set_string(&(self->log_wnd->caption1), "Connection Log");
|
||||
/* ok button */
|
||||
but = xrdp_bitmap_create(DEFAULT_BUTTON_W, DEFAULT_BUTTON_H, self->screen->bpp, WND_TYPE_BUTTON, self);
|
||||
const char *ok_string = "OK";
|
||||
const int ok_height =
|
||||
self->xrdp_config->cfg_globals.ls_scaled.default_btn_height;
|
||||
const int ok_width = xrdp_painter_text_width(self->painter, ok_string) +
|
||||
DEFAULT_BUTTON_MARGIN_W;
|
||||
|
||||
but = xrdp_bitmap_create(ok_width, ok_height, self->screen->bpp,
|
||||
WND_TYPE_BUTTON, self);
|
||||
list_insert_item(self->log_wnd->child_list, 0, (long)but);
|
||||
but->parent = self->log_wnd;
|
||||
but->owner = self->log_wnd;
|
||||
but->left = (w - DEFAULT_BUTTON_W) - xoffset;
|
||||
but->top = (h - DEFAULT_BUTTON_H) - yoffset;
|
||||
but->left = (w - ok_width) - xoffset;
|
||||
but->top = (h - ok_height) - yoffset;
|
||||
but->id = 1;
|
||||
but->tab_stop = 1;
|
||||
set_string(&but->caption1, "OK");
|
||||
|
|
Loading…
Reference in New Issue