Skip to main content

GetWidthFromCodepointSequence

Short summary

This function returns the width of a given unicode string.

A width of -1 means the string contains control characters, e.g. line feed or carriage return. If a string has for example a line break, the width cannot be calculated. A width 0 means the string is either empty or consists only of combining marks.

Attention: The actual width a character needs for displaying is always dependent on the used font, the fontsize and the rendering! The width this function returns is actually an estimation.

  • Return type: DINT

Parameters

NameTypeCommentKind
codepointsPOINTER TO UnicodeCodePointpointer to the codepoint sequenceinput
codepointCountUDINTnumber of codepoints in the sequenceinput
widthDINTwidth of the given stringoutput
visibleCharactersUDINTcount of visible charactersoutput

Code

Declaration

FUNCTION GetWidthFromCodepointSequence :DINT
VAR_INPUT
(* pointer to the codepoint sequence *)
codepoints :POINTER TO UnicodeCodePoint;
(* number of codepoints in the sequence *)
codepointCount :UDINT;
END_VAR
VAR_OUTPUT
(* width of the given string *)
width :DINT := 0;
(* count of visible characters *)
visibleCharacters :UDINT := 0;
END_VAR
VAR
index :UDINT;
currentCodepoint :UnicodeCodePoint;
characterWidth: DINT;
END_VAR

Implementation

GetWidthFromCodepointSequence := 0;

WHILE index < codepointCount DO
CASE codepoints[index] OF
16#200D: // zero width joiner, ignore next sign
index := index + 2;
16#FE0F: // Variant Selector 16, it can in some cases make the previous codepoint displayed as emoji, which will consume +1 additional width
IF (index>0) THEN
characterWidth := GetVS16Width(ADR(codepoints[index-1]));
width := width + characterWidth;
visibleCharacters := visibleCharacters + SEL(characterWidth > 0, 0, 1);
END_IF
index := index + 1;

ELSE
characterWidth := GetWidthFromCodepoint(ADR(codepoints[index]));
IF (characterWidth < 0) THEN
// control sign found, size cannot be calculated correctly (e.g. linefeed or carriage return)
width := -1;
RETURN;
END_IF
width := width + characterWidth;
visibleCharacters := visibleCharacters + SEL(characterWidth > 0, 0, 1);
index := index + 1;
END_CASE
END_WHILE
GetWidthFromCodepointSequence := width;