/*
* Copyright ( C ) 2026 Behdad Esfahbod
*
* This is part of HarfBuzz , a text shaping library .
*
* Permission is hereby granted , without written agreement and without
* license or royalty fees , to use , copy , modify , and distribute this
* software and its documentation for any purpose , provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software .
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT , INDIRECT , SPECIAL , INCIDENTAL , OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION , EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE .
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES , INCLUDING ,
* BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE . THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN " AS IS " BASIS , AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE , SUPPORT , UPDATES , ENHANCEMENTS , OR MODIFICATIONS .
*
* Author ( s ) : Behdad Esfahbod
*/
#include "hb.hh"
#include "hb-gpu.h"
#include "hb-blob.hh"
/**
* SECTION : hb - gpu
* @ title : hb - gpu
* @ short_description : GPU text rendering
* @ include : hb - gpu . h
*
* This module provides GPU - side text rendering . Glyph data is
* encoded on the CPU into compact blobs that the GPU decodes and
* rasterizes directly in the fragment shader , with no intermediate
* bitmap atlas .
*
* Two renderers share the same atlas , vertex stage , and pipeline :
*
* - Draw , an antialiased monochrome coverage mask for outline
* glyphs .
* - Paint , a premultiplied - RGBA color accumulator for COLRv0 and
* COLRv1 glyphs . Paint also renders plain monochrome outlines
* ( as a single foreground - colored layer ) , at some cost over the
* Draw path .
*
* Applications typically pick one renderer per font , based on
* whether the font has a color paint table ( see
* hb_ot_color_has_paint ( ) ) . The Draw path is meaningfully faster
* than Paint on monochrome fonts , so using Paint unconditionally
* leaves performance on the table .
*
* See the [ live web demo ] ( https : //harfbuzz.github.io/hb-gpu-demo/).
*
* # Draw
*
* The draw renderer implements the
* [ Slug ] ( https : //github.com/EricLengyel/Slug) algorithm by Eric
* Lengyel . It produces an antialiased coverage mask in the
* fragment shader , suitable for compositing over any background
* or multiplying with any foreground color .
*
* # # Encoding
*
* Each glyph is encoded independently into an opaque blob of
* RGBA16I texels ( 8 bytes each ) . Typical encoding flow :
*
* | [ < ! - - language = " plain " - - >
* hb_gpu_draw_t * draw = hb_gpu_draw_create_or_fail ( ) ;
*
* hb_gpu_draw_glyph ( draw , font , gid ) ;
* hb_blob_t * blob = hb_gpu_draw_encode ( draw ) ;
*
* // Upload hb_blob_get_data(blob) to the atlas at some offset.
* unsigned atlas_offset = upload_to_atlas ( blob ) ;
*
* hb_gpu_draw_recycle_blob ( draw , blob ) ;
* // repeat for more glyphs...
*
* hb_gpu_draw_destroy ( draw ) ;
* ] |
*
* Create the encoder once and reuse it across glyphs .
* hb_gpu_draw_encode ( ) auto - clears the accumulated outlines on
* return , so the next call to hb_gpu_draw_glyph ( ) starts fresh ;
* user configuration ( font scale ) is preserved . Pass the
* encoded blob back via hb_gpu_draw_recycle_blob ( ) after upload
* to recycle the buffer across encodes .
*
* # # Atlas setup
*
* All encoded blobs are uploaded into a single GL_TEXTURE_BUFFER
* backed by a GL_RGBA16I format buffer . Each glyph occupies a
* contiguous range of texels at a known offset :
*
* | [ < ! - - language = " plain " - - >
* GLuint buf , tex ;
* glGenBuffers ( 1 , & buf ) ;
* glGenTextures ( 1 , & tex ) ;
*
* glBindBuffer ( GL_TEXTURE_BUFFER , buf ) ;
* glBufferData ( GL_TEXTURE_BUFFER , capacity * 8 , NULL , GL_STATIC_DRAW ) ;
*
* glBindTexture ( GL_TEXTURE_BUFFER , tex ) ;
* glTexBuffer ( GL_TEXTURE_BUFFER , GL_RGBA16I , buf ) ;
*
* // Upload a glyph blob at 'offset' texels:
* glBufferSubData ( GL_TEXTURE_BUFFER ,
* offset * 8 ,
* hb_blob_get_length ( blob ) ,
* hb_blob_get_data ( blob , NULL ) ) ;
* ] |
*
* # # Shader compilation
*
* The library provides GLSL source strings for shared helpers
* ( atlas access , vertex dilation ) and for the draw - renderer stage
* code . Prepend a # version directive , concatenate shared and
* draw sources in order , and append your own main ( ) :
*
* | [ < ! - - language = " plain " - - >
* const char * vert_sources [ ] = {
* " # version 330 \ n " ,
* hb_gpu_shader_source ( HB_GPU_SHADER_STAGE_VERTEX ,
* HB_GPU_SHADER_LANG_GLSL ) ,
* hb_gpu_draw_shader_source ( HB_GPU_SHADER_STAGE_VERTEX ,
* HB_GPU_SHADER_LANG_GLSL ) ,
* your_vertex_main
* } ;
* glShaderSource ( vert_shader , 4 , vert_sources , NULL ) ;
* // Same pattern for the fragment shader.
* ] |
*
* hb_gpu_draw_shader_source ( ) returns an empty string for the
* vertex stage , so the assembly order above is safe .
*
* # # Vertex shader
*
* The vertex library provides one function :
*
* | [ < ! - - language = " plain " - - >
* void hb_gpu_dilate ( inout vec2 position , inout vec2 texcoord ,
* vec2 normal , vec4 jac ,
* mat4 m , vec2 viewport ) ;
* ] |
*
* This expands each glyph quad by approximately half a pixel on
* screen to ensure proper antialiasing coverage at the edges .
* It must be called in the vertex shader before computing
* gl_Position .
*
* Per - vertex attributes for each glyph quad ( 2 triangles , 6
* vertices , 4 unique corners ) :
*
* - position ( vec2 ) : object - space vertex position , computed from
* the glyph ' s bounding box . For corner ( cx , cy ) where cx , cy
* are 0 or 1 :
* | [ < ! - - language = " plain " - - >
* pos . x = pen_x + scale * lerp ( extent_min_x , extent_max_x , cx )
* pos . y = pen_y - scale * lerp ( extent_min_y , extent_max_y , cy )
* ] |
* where scale = font_size / upem .
*
* - texcoord ( vec2 ) : em - space texture coordinates , equal to the
* raw extent values : ` ( ex , ey ) ` where ex / ey are the glyph ' s
* bounding box corners in font design units . The fragment shader
* samples the encoded blob in this coordinate space .
*
* - normal ( vec2 ) : outward normal at each corner .
* ` ( - 1 , + 1 ) ` for ( 0 , 0 ) , ` ( + 1 , + 1 ) ` for ( 1 , 0 ) ,
* ` ( - 1 , - 1 ) ` for ( 0 , 1 ) , ` ( + 1 , - 1 ) ` for ( 1 , 1 ) .
* Note : y is negated relative to cx , cy because the common
* em - to - object transform flips y .
*
* - jac ( vec4 ) : maps object - space displacements back to
* em - space after dilation , stored row - major as
* ( j00 , j01 , j10 , j11 ) . For the common case of uniform
* scaling with y - flip :
* | [ < ! - - language = " plain " - - >
* jac = vec4 ( emPerPos , 0 . 0 , 0 . 0 , - emPerPos )
* ] |
* where emPerPos = upem / font_size . For non - trivial
* transforms , see the hb_gpu_dilate source .
*
* - m ( mat4 ) : the model - view - projection matrix ( uniform ) .
*
* - viewport ( vec2 ) : the viewport size in pixels ( uniform ) .
*
* A typical vertex main :
*
* | [ < ! - - language = " plain " - - >
* uniform mat4 u_matViewProjection ;
* uniform vec2 u_viewport ;
*
* in vec2 a_position ;
* in vec2 a_texcoord ;
* in vec2 a_normal ;
* in float a_emPerPos ;
* in uint a_glyphLoc ;
*
* out vec2 v_texcoord ;
* flat out uint v_glyphLoc ;
*
* void main ( ) {
* vec2 pos = a_position ;
* vec2 tex = a_texcoord ;
* vec4 jac = vec4 ( a_emPerPos , 0 . 0 , 0 . 0 , - a_emPerPos ) ;
* hb_gpu_dilate ( pos , tex , a_normal , jac ,
* u_matViewProjection , u_viewport ) ;
* gl_Position = u_matViewProjection * vec4 ( pos , 0 . 0 , 1 . 0 ) ;
* v_texcoord = tex ;
* v_glyphLoc = a_glyphLoc ;
* }
* ] |
*
* # # Font scale
*
* The encoder works in font design units ( upem ) . For best
* results , do not set a scale on the # hb_font_t passed to
* hb_gpu_draw_glyph ( ) — leave it at the default ( upem ) .
* Scaling is applied later when computing vertex positions :
*
* | [ < ! - - language = " plain " - - >
* float scale = font_size / upem ;
* pos . x = pen_x + scale * extent_x ;
* pos . y = pen_y - scale * extent_y ;
* ] |
*
* If you do set a font scale ( e . g . for hinting ) , the encoded
* blob and extents will be in the scaled coordinate space ,
* and you must adjust emPerPos accordingly .
*
* # # Dilation
*
* Each glyph is rendered on a screen - aligned quad whose
* corners match the glyph ' s bounding box . Without dilation ,
* the antialiased edges at the quad boundary get clipped — the
* fragment shader needs at least half a pixel of padding
* around the glyph to produce smooth coverage gradients .
*
* hb_gpu_dilate computes a perspective - correct half - pixel
* expansion . It adjusts both the vertex position ( expanding
* the quad ) and the texcoord ( so the fragment shader samples
* the right location in em - space after expansion ) .
*
* The ` jac ` parameter maps object - space displacements back to
* em - space . For the common case of uniform scaling with
* y - flip ( ` pos . y = pen_y - scale * ey ` ) :
*
* | [ < ! - - language = " plain " - - >
* float emPerPos = upem / font_size ;
* jac = vec4 ( emPerPos , 0 . 0 , 0 . 0 , - emPerPos ) ;
* ] |
*
* For non - uniform scaling or shearing transforms , jac is the
* 2 x2 inverse of the em - to - object linear transform , stored
* row - major .
*
* # # # Static dilation alternative
*
* Applications that do not need perspective correctness ( e . g .
* strictly 2 D rendering at known sizes ) can skip hb_gpu_dilate
* and instead expand each quad vertex by a fixed amount along
* its normal , based on the minimum expected font size :
*
* | [ < ! - - language = " plain " - - >
* float min_ppem = 10 . 0 ; // smallest expected size in pixels
* float pad = 0 . 5 * upem / min_ppem ; // half-pixel in em units
* pos + = normal * pad * scale ;
* texcoord + = normal * pad ;
* ] |
*
* This over - dilates at larger sizes ( wasting fill rate on
* transparent pixels ) but is simpler to implement and avoids
* the need for the MVP matrix and viewport size in the vertex
* shader .
*
* # # Fragment shader
*
* The fragment library provides two functions :
*
* | [ < ! - - language = " plain " - - >
* float hb_gpu_draw ( vec2 renderCoord , uint glyphLoc ) ;
* ] |
*
* It requires the ` hb_gpu_atlas ` uniform to be bound to the
* texture containing the encoded glyph data . By default this
* is an ` isamplerBuffer ` ( GL_TEXTURE_BUFFER ) . For platforms
* without texture buffers ( e . g . WebGL2 ) , define
* ` HB_GPU_ATLAS_2D ` before including the shader source ; the
* atlas then becomes an ` isampler2D ` and a
* ` uniform int hb_gpu_atlas_width ` must also be set to the
* texture width .
*
* Parameters :
*
* - renderCoord : the interpolated em - space coordinate from
* the vertex shader ( v_texcoord ) .
*
* - glyphLoc : the texel offset of this glyph ' s encoded blob
* in the atlas buffer . Passed as a flat varying from the
* vertex shader .
*
* Returns the coverage in [ 0 , 1 ] : 1 . 0 inside the glyph , 0 . 0
* outside , with antialiased edges .
*
* A typical fragment main :
*
* | [ < ! - - language = " plain " - - >
* in vec2 v_texcoord ;
* flat in uint v_glyphLoc ;
* out vec4 fragColor ;
*
* void main ( ) {
* float coverage = hb_gpu_draw ( v_texcoord , v_glyphLoc ) ;
* fragColor = vec4 ( 0 . 0 , 0 . 0 , 0 . 0 , coverage ) ;
* }
* ] |
*
* The coverage value can be used with alpha blending
* ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) to composite
* over a background , or multiplied with any color .
*
* # # Stem darkening
*
* | [ < ! - - language = " plain " - - >
* float hb_gpu_stem_darken ( float coverage , float brightness , float ppem ) ;
* ] |
*
* Optional stem darkening adjusts coverage at small sizes so
* thin stems are not washed out by gamma correction .
*
* Parameters :
*
* - coverage : a coverage / alpha value in [ 0 , 1 ] . For
* hb_gpu_draw ( ) this is the returned coverage ; for
* hb_gpu_paint ( ) use the edge coverage out parameter .
*
* - brightness : brightness of the color that will end up on
* screen for this fragment , in [ 0 , 1 ] , computed as
* ` dot ( straight_color . rgb , vec3 ( 1 . 0 / 3 . 0 ) ) ` .
*
* - ppem : pixels per em at this fragment , computed as
* ` 1 . 0 / max ( fwidth ( v_texcoord ) . x , fwidth ( v_texcoord ) . y ) ` .
*
* Example — draw path :
*
* | [ < ! - - language = " plain " - - >
* float coverage = hb_gpu_draw ( v_texcoord , v_glyphLoc ) ;
* float brightness = dot ( u_foreground . rgb , vec3 ( 1 . 0 / 3 . 0 ) ) ;
* float ppem = 1 . 0 / max ( fwidth ( v_texcoord ) . x ,
* fwidth ( v_texcoord ) . y ) ;
* coverage = hb_gpu_stem_darken ( coverage , brightness , ppem ) ;
* ] |
*
* Example — paint path : hb_gpu_paint ( ) returns a separate
* edge coverage value that tracks the maximum antialiasing
* coverage across paint layers . Apply stem darkening and gamma to this
* edge coverage , then scale the premultiplied color to match .
* Interior fragments ( coverage = = 1 ) are left untouched .
*
* | [ < ! - - language = " plain " - - >
* float cov ;
* vec4 c = hb_gpu_paint ( v_texcoord , v_glyphLoc , u_foreground , cov ) ;
* if ( cov > 0 . 0 & & cov < 1 . 0 ) {
* float brightness = c . a > 0 . 0
* ? dot ( c . rgb , vec3 ( 1 . 0 / 3 . 0 ) ) / c . a : 0 . 0 ;
* float ppem = 1 . 0 / max ( fwidth ( v_texcoord ) . x ,
* fwidth ( v_texcoord ) . y ) ;
* float adj = hb_gpu_stem_darken ( cov , brightness , ppem ) ;
* c * = adj / cov ;
* }
* ] |
*
* # Paint
*
* The paint renderer walks the font ' s paint tree ( COLRv0 layers
* or COLRv1 paint subtree ) and records one layer op per solid or
* gradient fill , each with its own clip outline encoded as a Slug
* ( so the paint renderer reuses the draw renderer internally for
* clips ) . Palette colors and custom overrides are resolved and
* baked into the blob at encode time , so the shader does not need
* a separate palette uniform .
*
* Monochrome ( non - color ) glyphs are handled transparently :
* hb_gpu_paint_glyph ( ) synthesizes a single foreground - colored
* layer from the glyph ' s outline , so callers can use the paint
* renderer uniformly for any font . This costs more per fragment
* than the Draw path , but the rendered result is the same .
*
* # # Encoding
*
* | [ < ! - - language = " plain " - - >
* hb_gpu_paint_t * paint = hb_gpu_paint_create_or_fail ( ) ;
*
* // Optional: select a palette and install any custom-palette
* // overrides before hb_gpu_paint_glyph — their values are baked
* // into the encoded blob. (The foreground color is NOT set here:
* // it stays a shader uniform so dark-mode and color-change
* // toggles take effect without re-encoding.)
* hb_gpu_paint_set_palette ( paint , 0 ) ;
* hb_gpu_paint_set_custom_palette_color ( paint , 2 ,
* HB_COLOR ( 0 xff , 0 , 0 , 0 xff ) ) ;
*
* hb_gpu_paint_glyph ( paint , font , gid ) ;
* hb_glyph_extents_t ext ;
* hb_blob_t * blob = hb_gpu_paint_encode ( paint , & ext ) ;
*
* // Upload hb_blob_get_data(blob) to the same atlas used by draw.
* unsigned atlas_offset = upload_to_atlas ( blob ) ;
*
* hb_gpu_paint_recycle_blob ( paint , blob ) ;
* // repeat for more glyphs...
*
* hb_gpu_paint_destroy ( paint ) ;
* ] |
*
* As with the draw encoder , create the paint encoder once and
* reuse it . hb_gpu_paint_encode ( ) auto - clears on return ; user
* configuration ( palette , custom - palette overrides ) is preserved
* across encodes . Because colors are baked , changing any of that
* configuration afterwards requires re - encoding the affected
* glyphs . The encoded blob ' s texel format is the same RGBA16I
* as the draw renderer ' s , so both kinds of blobs can coexist in
* one atlas at different offsets .
*
* # # Shader composition
*
* Same pattern as the draw renderer but using
* hb_gpu_paint_shader_source ( ) for the paint - specific helpers .
* The vertex stage is identical — hb_gpu_paint_shader_source ( )
* returns an empty string for HB_GPU_SHADER_STAGE_VERTEX , so the
* fixed assembly order still works :
*
* | [ < ! - - language = " plain " - - >
* const char * frag_sources [ ] = {
* " # version 330 \ n " ,
* hb_gpu_shader_source ( HB_GPU_SHADER_STAGE_FRAGMENT ,
* HB_GPU_SHADER_LANG_GLSL ) ,
* hb_gpu_paint_shader_source ( HB_GPU_SHADER_STAGE_FRAGMENT ,
* HB_GPU_SHADER_LANG_GLSL ) ,
* your_fragment_main
* } ;
* glShaderSource ( frag_shader , 4 , frag_sources , NULL ) ;
* ] |
*
* The atlas setup , vertex attributes , dilation , and font scaling
* guidance from the Draw section all apply unchanged .
*
* # # Fragment shader
*
* The paint library provides one function :
*
* | [ < ! - - language = " plain " - - >
* vec4 hb_gpu_paint ( vec2 renderCoord , uint glyphLoc , vec4 foreground ,
* out float coverage ) ;
* ] |
*
* Parameters :
*
* - renderCoord : the interpolated em - space coordinate from the
* vertex shader ( v_texcoord ) , as for hb_gpu_draw ( ) .
*
* - glyphLoc : the texel offset of this glyph ' s encoded paint blob
* in the atlas , passed as a flat varying from the vertex shader .
*
* - foreground : the foreground color used to resolve palette
* entries that COLRv1 marks as " foreground color " . The encoder
* only records the is - foreground flag per layer / stop ; the actual
* color is substituted here at render time , so runtime
* foreground - color changes ( e . g . a dark - mode toggle ) take effect
* without re - encoding any glyphs .
*
* - coverage ( out ) : the maximum antialiasing coverage across all
* paint layers . Fractional values ( between 0 and 1 ) indicate
* antialiased edge pixels ; 0 means fully outside , 1 means fully
* inside . Stem darkening and gamma correction should be applied
* to this value rather than to the returned color , so that
* interior paint colors are unaffected . See the stem darkening
* notes in the Draw section .
*
* Returns premultiplied RGBA : fully transparent outside the glyph ,
* composited layers inside . Use ( GL_ONE , GL_ONE_MINUS_SRC_ALPHA )
* blending to composite over a background .
*
* A typical fragment main :
*
* | [ < ! - - language = " plain " - - >
* uniform vec4 u_foreground ;
* uniform float u_gamma ;
* uniform float u_stem_darkening ;
* in vec2 v_texcoord ;
* flat in uint v_glyphLoc ;
* out vec4 fragColor ;
*
* void main ( ) {
* float cov ;
* vec4 c = hb_gpu_paint ( v_texcoord , v_glyphLoc , u_foreground , cov ) ;
* if ( cov > 0 . 0 & & cov < 1 . 0 ) {
* float adj = cov ;
* if ( u_stem_darkening > 0 . 0 ) {
* float brightness = c . a > 0 . 0
* ? dot ( c . rgb , vec3 ( 1 . 0 / 3 . 0 ) ) / c . a : 0 . 0 ;
* adj = hb_gpu_stem_darken ( adj , brightness ,
* 1 . 0 / max ( fwidth ( v_texcoord ) . x , fwidth ( v_texcoord ) . y ) ) ;
* }
* if ( u_gamma ! = 1 . 0 )
* adj = pow ( adj , u_gamma ) ;
* c * = adj / cov ;
* }
* fragColor = c ;
* }
* ] |
**/
#include "hb-gpu-fragment-glsl.hh"
#include "hb-gpu-fragment-msl.hh"
#include "hb-gpu-fragment-wgsl.hh"
#include "hb-gpu-fragment-hlsl.hh"
#include "hb-gpu-vertex-glsl.hh"
#include "hb-gpu-vertex-msl.hh"
#include "hb-gpu-vertex-wgsl.hh"
#include "hb-gpu-vertex-hlsl.hh"
/**
* hb_gpu_shader_source :
* @ stage : pipeline stage ( vertex or fragment )
* @ lang : shader language variant
*
* Returns the shared helper shader source used by the hb - gpu
* renderers for the specified stage and language . The returned
* string is static and must not be freed .
*
* The shared source defines utilities such as the atlas sampler
* and the ` hb_gpu_fetch ( ) ` accessor for the fragment stage , and
* the ` hb_gpu_dilate ( ) ` helper for the vertex stage . Each
* renderer - specific source ( for example ,
* hb_gpu_draw_shader_source ( ) ) assumes these helpers are already
* in scope — callers should concatenate a ` # version ` directive ,
* then this shared source , then the renderer - specific source ,
* then their own ` main ( ) ` .
*
* Return value : ( transfer none ) :
* A shader source string , or ` NULL ` if @ stage or @ lang is
* unsupported .
*
* Since : 14 . 2 . 0
**/
const char *
hb_gpu_shader_source (hb_gpu_shader_stage_t stage,
hb_gpu_shader_lang_t lang)
{
switch (stage) {
case HB_GPU_SHADER_STAGE_FRAGMENT:
switch (lang) {
case HB_GPU_SHADER_LANG_GLSL: return hb_gpu_fragment_glsl;
case HB_GPU_SHADER_LANG_MSL: return hb_gpu_fragment_msl;
case HB_GPU_SHADER_LANG_WGSL: return hb_gpu_fragment_wgsl;
case HB_GPU_SHADER_LANG_HLSL: return hb_gpu_fragment_hlsl;
case HB_GPU_SHADER_LANG_INVALID:
default : return nullptr;
}
case HB_GPU_SHADER_STAGE_VERTEX:
switch (lang) {
case HB_GPU_SHADER_LANG_GLSL: return hb_gpu_vertex_glsl;
case HB_GPU_SHADER_LANG_MSL: return hb_gpu_vertex_msl;
case HB_GPU_SHADER_LANG_WGSL: return hb_gpu_vertex_wgsl;
case HB_GPU_SHADER_LANG_HLSL: return hb_gpu_vertex_hlsl;
case HB_GPU_SHADER_LANG_INVALID:
default : return nullptr;
}
default :
return nullptr;
}
}
Messung V0.5 in Prozent C=97 H=100 G=98
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.23Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland