Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  xrdp_painter.c

  Sprache: C
 

/**
 * xrdp: A Remote Desktop Protocol server.
 *
 * Copyright (C) Jay Sorg 2004-2014
 *
 * 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.
 *
 * painter, gc
 */


#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif

#include <limits.h>

#include "xrdp.h"
#include "string_calls.h"

#if defined(XRDP_PAINTER)
#include <painter.h> /* libpainter */
#endif


#if defined(XRDP_PAINTER)

/*****************************************************************************/
static int
xrdp_painter_add_dirty_rect(struct xrdp_painter *self, int x, int y,
                            int cx, int cy, struct xrdp_rect *clip_rect)
{
    int x2;
    int y2;
    struct xrdp_rect rect;

    if (clip_rect != 0)
    {
        x2 = x + cx;
        y2 = y + cy;
        x = MAX(x, clip_rect->left);
        y = MAX(y, clip_rect->top);
        x2 = MIN(x2, clip_rect->right);
        y2 = MIN(y2, clip_rect->bottom);
        cx = x2 - x;
        cy = y2 - y;
    }
    if (cx < 1 || cy < 1)
    {
        return 0;
    }
    rect.left = x;
    rect.top = y;
    rect.right = x + cx;
    rect.bottom = y + cy;
    xrdp_region_add_rect(self->dirty_region, &rect);
    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_add_dirty_rect: x %d y %d cx %d cy %d",
              x, y, cx, cy);
    return 0;
}

/*****************************************************************************/
static int
xrdp_painter_send_dirty(struct xrdp_painter *self)
{
    int cx;
    int cy;
    int bpp;
    int Bpp;
    int index;
    int jndex;
    int error;
    char *ldata;
    char *src;
    char *dst;
    struct xrdp_rect rect;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_send_dirty:");

    bpp = self->wm->screen->bpp;
    Bpp = (bpp + 7) / 8;
    if (Bpp == 3)
    {
        Bpp = 4;
    }

    if (self->session->client_info->gfx)
    {
        xrdp_mm_efgx_add_dirty_region_to_planar_list(self->wm->mm,
                self->dirty_region);
    }
    else
    {
        jndex = 0;
        error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
        while (error == 0)
        {
            cx = rect.right - rect.left;
            cy = rect.bottom - rect.top;
            ldata = (char *)g_malloc(cx * cy * Bpp, 0);
            if (ldata == 0)
            {
                return 1;
            }
            src = self->wm->screen->data;
            src += self->wm->screen->line_size * rect.top;
            src += rect.left * Bpp;
            dst = ldata;
            for (index = 0; index < cy; index++)
            {
                g_memcpy(dst, src, cx * Bpp);
                src += self->wm->screen->line_size;
                dst += cx * Bpp;
            }
            LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_send_dirty:"
                      " x %d y %d cx %d cy %d",
                      rect.left, rect.top, cx, cy);
            libxrdp_send_bitmap(self->session, cx, cy, bpp,
                                ldata, rect.left, rect.top, cx, cy);
            g_free(ldata);

            jndex++;
            error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
        }
    }

    xrdp_region_delete(self->dirty_region);
    self->dirty_region = xrdp_region_create(self->wm);

    return 0;
}

#endif

/*****************************************************************************/
struct xrdp_painter *
xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session)
{
    struct xrdp_painter *self;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_create:");
    self = (struct xrdp_painter *)g_malloc(sizeof(struct xrdp_painter), 1);
    self->wm = wm;
    self->session = session;
    self->rop = 0xcc; /* copy will use 0xcc */
    self->clip_children = 1;

    if (self->session->client_info->no_orders_supported ||
            self->session->client_info->gfx)
    {
#if defined(XRDP_PAINTER)
        if (painter_create(&(self->painter)) != PT_ERROR_NONE)
        {
            self->painter = 0;
            LOG_DEVEL(LOG_LEVEL_WARNING, "xrdp_painter_create: painter_create failed");
        }
        else
        {
            LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_create: painter_create success");
        }
        self->dirty_region = xrdp_region_create(wm);
#endif
    }

    return self;
}

/*****************************************************************************/
void
xrdp_painter_delete(struct xrdp_painter *self)
{
    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_delete:");
    if (self == 0)
    {
        return;
    }

#if defined(XRDP_PAINTER)
    painter_delete(self->painter);
    xrdp_region_delete(self->dirty_region);
#endif

    g_free(self);
}

/*****************************************************************************/
int
wm_painter_set_target(struct xrdp_painter *self)
{
    int surface_index;
    int index;
    struct list *del_list;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "wm_painter_set_target:");

    if (self->painter != 0)
    {
        return 0;
    }

    if (self->wm->target_surface->type == WND_TYPE_SCREEN)
    {
        if (self->wm->current_surface_index != 0xffff)
        {
            libxrdp_orders_send_switch_os_surface(self->session, 0xffff);
            self->wm->current_surface_index = 0xffff;
        }
    }
    else if (self->wm->target_surface->type == WND_TYPE_OFFSCREEN)
    {
        surface_index = self->wm->target_surface->item_index;

        if (surface_index != self->wm->current_surface_index)
        {
            if (self->wm->target_surface->tab_stop == 0/* tab_stop is hack */
            {
                del_list = self->wm->cache->xrdp_os_del_list;
                index = list_index_of(del_list, surface_index);
                list_remove_item(del_list, index);
                libxrdp_orders_send_create_os_surface(self->session, surface_index,
                                                      self->wm->target_surface->width,
                                                      self->wm->target_surface->height,
                                                      del_list);
                self->wm->target_surface->tab_stop = 1;
                list_clear(del_list);
            }

            libxrdp_orders_send_switch_os_surface(self->session, surface_index);
            self->wm->current_surface_index = surface_index;
        }
    }
    else
    {
        LOG(LOG_LEVEL_WARNING, "xrdp_painter_begin_update: bad target_surface");
    }

    return 0;
}

/*****************************************************************************/
int
xrdp_painter_begin_update(struct xrdp_painter *self)
{
    int rv;
    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_begin_update:");
    if (self == 0)
    {
        return 0;
    }

    self->begin_end_level++;

    if (self->painter != 0)
    {
        return 0;
    }

    rv = libxrdp_orders_init(self->session);
    wm_painter_set_target(self);
    return rv;
}

/*****************************************************************************/
int
xrdp_painter_end_update(struct xrdp_painter *self)
{
    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_end_update:");
    if (self == 0)
    {
        return 0;
    }

    self->begin_end_level--;

    if (self->painter != 0)
    {
#if defined(XRDP_PAINTER)
        if (self->begin_end_level == 0)
        {
            xrdp_painter_send_dirty(self);
            return 0;
        }
#endif
    }

    libxrdp_orders_send(self->session);
    return 0;
}

/*****************************************************************************/
int
xrdp_painter_font_needed(struct xrdp_painter *self)
{
    if (self->font == 0)
    {
        self->font = self->wm->default_font;
    }

    return 0;
}

#if 0
/*****************************************************************************/
/* returns boolean, true if there is something to draw */
static int
xrdp_painter_clip_adj(struct xrdp_painter *self, int *x, int *y,
                      int *cx, int *cy)
{
    int dx;
    int dy;

    if (!self->use_clip)
    {
        return 1;
    }

    if (self->clip.left > *x)
    {
        dx = self->clip.left - *x;
    }
    else
    {
        dx = 0;
    }

    if (self->clip.top > *y)
    {
        dy = self->clip.top - *y;
    }
    else
    {
        dy = 0;
    }

    if (*x + *cx > self->clip.right)
    {
        *cx = *cx - ((*x + *cx) - self->clip.right);
    }

    if (*y + *cy > self->clip.bottom)
    {
        *cy = *cy - ((*y + *cy) - self->clip.bottom);
    }

    *cx = *cx - dx;
    *cy = *cy - dy;

    if (*cx <= 0)
    {
        return 0;
    }

    if (*cy <= 0)
    {
        return 0;
    }

    *x = *x + dx;
    *y = *y + dy;
    return 1;
}
#endif

/*****************************************************************************/
int
xrdp_painter_set_clip(struct xrdp_painter *self,
                      int x, int y, int cx, int cy)
{
    self->use_clip = &self->clip;
    self->clip.left = x;
    self->clip.top = y;
    self->clip.right = x + cx;
    self->clip.bottom = y + cy;
    return 0;
}

/*****************************************************************************/
int
xrdp_painter_clr_clip(struct xrdp_painter *self)
{
    self->use_clip = 0;
    return 0;
}

#if 0
/*****************************************************************************/
static int
xrdp_painter_rop(int rop, int src, int dst)
{
    switch (rop & 0x0f)
    {
        case 0x0:
            return 0;
        case 0x1:
            return ~(src | dst);
        case 0x2:
            return (~src) & dst;
        case 0x3:
            return ~src;
        case 0x4:
            return src & (~dst);
        case 0x5:
            return ~(dst);
        case 0x6:
            return src ^ dst;
        case 0x7:
            return ~(src & dst);
        case 0x8:
            return src & dst;
        case 0x9:
            return ~(src) ^ dst;
        case 0xa:
            return dst;
        case 0xb:
            return (~src) | dst;
        case 0xc:
            return src;
        case 0xd:
            return src | (~dst);
        case 0xe:
            return src | dst;
        case 0xf:
            return ~0;
    }

    return dst;
}
#endif

/*****************************************************************************/
int
xrdp_painter_text_width(struct xrdp_painter *self, const char *text)
{
    return xrdp_painter_text_width_count(self, text, UINT_MAX);
}

/*****************************************************************************/
int
xrdp_painter_text_width_count(struct xrdp_painter *self, const char *text,
                              unsigned int c32_count)
{
    int rv = 0;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_text_width_count:");
    xrdp_painter_font_needed(self);

    if (self->font != NULL && text != NULL)
    {
        unsigned int index;
        for (index = 0 ; index < c32_count; ++index)
        {
            struct xrdp_font_char *font_item;
            char32_t c32 = utf8_get_next_char(&text, NULL);
            if (c32 == 0)
            {
                break// Terminator
            }
            font_item = XRDP_FONT_GET_CHAR(self->font, c32);
            rv += font_item->incby;
        }
    }

    return rv;
}

/*****************************************************************************/
int
xrdp_painter_repeated_char_width(struct xrdp_painter *self,
                                 char32_t chr, unsigned int repeat_count)
{
    int rv = 0;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_repeated_char_width:");
    xrdp_painter_font_needed(self);

    if (self->font != NULL)
    {
        struct xrdp_font_char *font_item = XRDP_FONT_GET_CHAR(self->font, chr);
        rv = font_item->incby * repeat_count;
    }

    return rv;
}

/*****************************************************************************/
unsigned int
xrdp_painter_font_body_height(const struct xrdp_painter *self)
{
    return (self->font == NULL) ? 0 : self->font->body_height;
}

/*****************************************************************************/
static int
xrdp_painter_setup_brush(struct xrdp_painter *self,
                         struct xrdp_brush *out_brush,
                         struct xrdp_brush *in_brush)
{
    int cache_id;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_setup_brush:");

    if (self->painter != 0)
    {
        return 0;
    }

    g_memcpy(out_brush, in_brush, sizeof(struct xrdp_brush));

    if (in_brush->style == 3)
    {
        if (self->session->client_info->brush_cache_code == 1)
        {
            cache_id = xrdp_cache_add_brush(self->wm->cache, in_brush->pattern);
            g_memset(out_brush->pattern, 08);
            out_brush->pattern[0] = cache_id;
            out_brush->style = 0x81;
        }
    }

    return 0;
}

#if defined(XRDP_PAINTER)

/*****************************************************************************/
static int
get_pt_format(struct xrdp_painter *self)
{
    switch (self->wm->screen->bpp)
    {
        case 8:
            return PT_FORMAT_r3g3b2;
        case 15:
            return PT_FORMAT_a1r5g5b5;
        case 16:
            return PT_FORMAT_r5g6b5;
    }
    return PT_FORMAT_a8r8g8b8;
}

/*****************************************************************************/
static int
get_rgb_from_rdp_color(struct xrdp_painter *self, int rdp_color)
{
    if (self->wm->screen->bpp < 24)
    {
        return rdp_color;
    }
    /* well, this is really BGR2RGB */
    return XR_RGB2BGR(rdp_color);
}

#endif

/*****************************************************************************/
/* fill in an area of the screen with one color */
int
xrdp_painter_fill_rect(struct xrdp_painter *self,
                       struct xrdp_bitmap *dst,
                       int x, int y, int cx, int cy)
{
    struct xrdp_rect clip_rect;
    struct xrdp_rect draw_rect;
    struct xrdp_rect rect;
    struct xrdp_region *region;
    struct xrdp_brush brush;
    int k;
    int dx;
    int dy;
    int rop;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_fill_rect:");

    if (self == 0)
    {
        return 0;
    }

    dx = 0;
    dy = 0;

    if (self->painter != 0)
    {
#if defined(XRDP_PAINTER)
        struct painter_bitmap dst_pb;
        struct xrdp_bitmap *ldst;
        struct painter_bitmap pat;

        LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_fill_rect: dst->type %d", dst->type);
        if (dst->type != WND_TYPE_OFFSCREEN)
        {
            LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_fill_rect: using painter");

            ldst = self->wm->screen;

            g_memset(&dst_pb, 0sizeof(dst_pb));
            dst_pb.format = get_pt_format(self);
            dst_pb.width = ldst->width;
            dst_pb.stride_bytes = ldst->line_size;
            dst_pb.height = ldst->height;
            dst_pb.data = ldst->data;

            LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_fill_rect: ldst->width %d ldst->height %d "
                      "dst->data %p self->fg_color %d",
                      ldst->width, ldst->height, ldst->data, self->fg_color);

            xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
            region = xrdp_region_create(self->wm);
            xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, region,
                                   self->clip_children);
            x += dx;
            y += dy;

            rop = self->rop;
            switch (self->rop)
            {
                case 0x5a:
                    rop = PT_ROP_DSx;
                    break;
                case 0xf0:
                    rop = PT_ROP_S;
                    break;
                case 0xfb:
                    rop = PT_ROP_D;
                    break;
                case 0xc0:
                    rop = PT_ROP_DSa;
                    break;
            }
            painter_set_rop(self->painter, rop);

            if (self->mix_mode == 0)
            {
                painter_set_pattern_mode(self->painter, PT_PATTERN_MODE_OPAQUE);
                painter_set_fgcolor(self->painter, get_rgb_from_rdp_color(self, self->fg_color));
                k = 0;
                while (xrdp_region_get_rect(region, k, &rect) == 0)
                {
                    if (rect_intersect(&rect, &clip_rect, &draw_rect))
                    {
                        painter_set_clip(self->painter,
                                         draw_rect.left, draw_rect.top,
                                         draw_rect.right - draw_rect.left,
                                         draw_rect.bottom - draw_rect.top);
                        painter_fill_rect(self->painter, &dst_pb, x, y, cx, cy);
                        xrdp_painter_add_dirty_rect(self, x, y, cx, cy, &draw_rect);
                    }
                    k++;
                }
            }
            else
            {
                painter_set_pattern_mode(self->painter, PT_PATTERN_MODE_OPAQUE);
                painter_set_fgcolor(self->painter, get_rgb_from_rdp_color(self, self->fg_color));
                painter_set_bgcolor(self->painter, get_rgb_from_rdp_color(self, self->bg_color));
                painter_set_pattern_origin(self->painter, self->brush.x_origin, self->brush.y_origin);
                g_memset(&pat, 0sizeof(pat));
                pat.format = PT_FORMAT_c1;
                pat.width = 8;
                pat.stride_bytes = 1;
                pat.height = 8;
                pat.data = self->brush.pattern;
                k = 0;
                while (xrdp_region_get_rect(region, k, &rect) == 0)
                {
                    if (rect_intersect(&rect, &clip_rect, &draw_rect))
                    {
                        painter_set_clip(self->painter,
                                         draw_rect.left, draw_rect.top,
                                         draw_rect.right - draw_rect.left,
                                         draw_rect.bottom - draw_rect.top);
                        painter_fill_pattern(self->painter, &dst_pb, &pat,
                                             x, y, x, y, cx, cy);
                        xrdp_painter_add_dirty_rect(self, x, y, cx, cy, &draw_rect);
                    }
                    k++;
                }
            }
            painter_clear_clip(self->painter);
            xrdp_region_delete(region);
        }
        return 0;
#endif
    }

    /* todo data */

    if (dst->type == WND_TYPE_BITMAP) /* 0 */
    {
        return 0;
    }

    xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
    region = xrdp_region_create(self->wm);

    if (dst->type != WND_TYPE_OFFSCREEN)
    {
        xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, region,
                               self->clip_children);
    }
    else
    {
        xrdp_region_add_rect(region, &clip_rect);
    }

    x += dx;
    y += dy;

    if (self->mix_mode == 0 && self->rop == 0xcc)
    {
        k = 0;

        while (xrdp_region_get_rect(region, k, &rect) == 0)
        {
            if (rect_intersect(&rect, &clip_rect, &draw_rect))
            {
                libxrdp_orders_rect(self->session, x, y, cx, cy,
                                    self->fg_color, &draw_rect);
            }

            k++;
        }
    }
    else if (self->mix_mode == 0 &&
             ((self->rop & 0xf) == 0x0 || /* black */
              (self->rop & 0xf) == 0xf || /* white */
              (self->rop & 0xf) == 0x5))  /* DSTINVERT */
    {
        k = 0;

        while (xrdp_region_get_rect(region, k, &rect) == 0)
        {
            if (rect_intersect(&rect, &clip_rect, &draw_rect))
            {
                libxrdp_orders_dest_blt(self->session, x, y, cx, cy,
                                        self->rop, &draw_rect);
            }

            k++;
        }
    }
    else
    {
        k = 0;
        rop = self->rop;

        /* if opcode is in the form 0x00, 0x11, 0x22, ... convert it */
        if (((rop & 0xf0) >> 4) == (rop & 0xf))
        {
            switch (rop)
            {
                case 0x66: /* xor */
                    rop = 0x5a;
                    break;
                case 0xaa: /* noop */
                    rop = 0xfb;
                    break;
                case 0xcc: /* copy */
                    rop = 0xf0;
                    break;
                case 0x88: /* and */
                    rop = 0xc0;
                    break;
            }
        }

        xrdp_painter_setup_brush(self, &brush, &self->brush);

        while (xrdp_region_get_rect(region, k, &rect) == 0)
        {
            if (rect_intersect(&rect, &clip_rect, &draw_rect))
            {
                libxrdp_orders_pat_blt(self->session, x, y, cx, cy,
                                       rop, self->bg_color, self->fg_color,
                                       &brush, &draw_rect);
            }

            k++;
        }
    }

    xrdp_region_delete(region);
    return 0;
}

/*****************************************************************************/
static int
xrdp_painter_draw_utf32(struct xrdp_painter *self,
                        struct xrdp_bitmap *dst,
                        int x, int y,
                        char32_t utf32[], unsigned int utf32len)
{
    int i;
    int f;
    int c;
    int k;
    int x1;
    int y1;
    int flags;
    unsigned int index;
    int total_width;
    int total_height;
    int dx;
    int dy;
    char *data;
    struct xrdp_region *region;
    struct xrdp_rect rect;
    struct xrdp_rect clip_rect;
    struct xrdp_rect draw_rect;
    struct xrdp_font *font;
    struct xrdp_font_char *font_item;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_draw_text:");

    if (self == 0)
    {
        return 0;
    }

    if (utf32len < 1)
    {
        return 0;
    }

    /* todo data */

    if (dst->type == 0)
    {
        return 0;
    }

    xrdp_painter_font_needed(self);

    if (self->font == 0)
    {
        return 0;
    }

    if (self->painter != 0)
    {
#if defined(XRDP_PAINTER)
        struct painter_bitmap pat;
        struct painter_bitmap dst_pb;
        struct xrdp_bitmap *ldst;

        if (dst->type != WND_TYPE_OFFSCREEN)
        {
            ldst = self->wm->screen;
            font = self->font;

            // Calculate total width and height fields
            total_width = 0;
            total_height = 0;

            for (index = 0 ; index < utf32len; ++index)
            {
                font_item = XRDP_FONT_GET_CHAR(font, utf32[index]);
                k = font_item->incby;
                total_width += k;
                /* 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);
            xrdp_wm_get_vis_region(self->wm, dst, x, y,
                                   total_width, total_height,
                                   region, self->clip_children);
            x += dx;
            y += dy;
            g_memset(&dst_pb, 0sizeof(dst_pb));
            dst_pb.format = get_pt_format(self);
            dst_pb.width = ldst->width;
            dst_pb.stride_bytes = ldst->line_size;
            dst_pb.height = ldst->height;
            dst_pb.data = ldst->data;
            painter_set_rop(self->painter, PT_ROP_S);
            painter_set_pattern_origin(self->painter, 00);
            painter_set_pattern_mode(self->painter, PT_PATTERN_MODE_NORMAL);
            painter_set_fgcolor(self->painter,
                                get_rgb_from_rdp_color(self, self->fg_color));
            k = 0;
            while (xrdp_region_get_rect(region, k, &rect) == 0)
            {
                if (rect_intersect(&rect, &clip_rect, &draw_rect))
                {
                    painter_set_clip(self->painter,
                                     draw_rect.left, draw_rect.top,
                                     draw_rect.right - draw_rect.left,
                                     draw_rect.bottom - draw_rect.top);
                    for (index = 0 ; index < utf32len; ++index)
                    {
                        font_item = XRDP_FONT_GET_CHAR(font, utf32[index]);
                        g_memset(&pat, 0sizeof(pat));
                        pat.format = PT_FORMAT_c1;
                        pat.width = font_item->width;
                        pat.stride_bytes = (font_item->width + 7) / 8;
                        pat.height = font_item->height;
                        pat.data = font_item->data;
                        x1 = x + font_item->offset;
                        y1 = y + (font->body_height + font_item->baseline);
                        painter_fill_pattern(self->painter, &dst_pb, &pat,
                                             00, x1, y1,
                                             font_item->width,
                                             font_item->height);
                        xrdp_painter_add_dirty_rect(self, x1, y1,
                                                    font_item->width,
                                                    font_item->height,
                                                    &draw_rect);
                        x += font_item->incby;
                    }
                }
                k++;
            }
            painter_clear_clip(self->painter);
            xrdp_region_delete(region);
        }
        return 0;
#endif
    }

    font = self->font;
    f = 0;
    k = 0;
    total_width = 0;
    total_height = 0;
    index = 0;
    data = (char *)g_malloc(utf32len * 21);

    for (index = 0 ; index < utf32len; ++index)
    {
        font_item = XRDP_FONT_GET_CHAR(font, utf32[index]);
        i = xrdp_cache_add_char(self->wm->cache, font_item);
        f = HIWORD(i);
        c = LOWORD(i);
        data[index * 2] = c;
        data[index * 2 + 1] = k;
        k = font_item->incby;
        total_width += k;
        /* 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);

    if (dst->type != WND_TYPE_OFFSCREEN)
    {
        xrdp_wm_get_vis_region(self->wm, dst, x, y, total_width, total_height,
                               region, self->clip_children);
    }
    else
    {
        xrdp_region_add_rect(region, &clip_rect);
    }

    x += dx;
    y += dy;
    k = 0;

    while (xrdp_region_get_rect(region, k, &rect) == 0)
    {
        if (rect_intersect(&rect, &clip_rect, &draw_rect))
        {
            x1 = x;
            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,
                                x - 1, y - 1, x + total_width, y + total_height,
                                0000,
                                x1, y1, data, utf32len * 2, &draw_rect);
        }

        k++;
    }

    xrdp_region_delete(region);
    g_free(data);
    return 0;
}


/*****************************************************************************/
int
xrdp_painter_draw_text(struct xrdp_painter *self,
                       struct xrdp_bitmap *dst,
                       int x, int y, const char *text)
{
    int rv = 0;
    unsigned int c32_count = utf8_char_count(text);

    if (c32_count > 0)
    {
        char32_t *utf32 = (char32_t *)malloc(c32_count * sizeof(char32_t));
        if (utf32 == NULL)
        {
            rv = 1;
        }
        else
        {
            unsigned int i = 0;
            char32_t c32;

            while ((c32 = utf8_get_next_char(&text, NULL)) != 0)
            {
                utf32[i++] = c32;
            }

            rv = xrdp_painter_draw_utf32(self, dst, x, y, utf32, c32_count);
            free (utf32);
        }
    }

    return rv;
}

/*****************************************************************************/
int
xrdp_painter_draw_text2(struct xrdp_painter *self,
                        struct xrdp_bitmap *dst,
                        int font, int flags, int mixmode,
                        int clip_left, int clip_top,
                        int clip_right, int clip_bottom,
                        int box_left, int box_top,
                        int box_right, int box_bottom,
                        int x, int y, char *data, int data_len)
{
    struct xrdp_rect clip_rect;
    struct xrdp_rect draw_rect;
    struct xrdp_rect rect;
    struct xrdp_region *region;
    int k;
    int dx;
    int dy;

    LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_painter_draw_text2:");

    if (self == 0)
    {
        return 0;
    }

    if (self->painter != 0)
    {
        return 0;
    }

    /* todo data */

    if (dst->type == WND_TYPE_BITMAP)
    {
        return 0;
    }

    xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
    region = xrdp_region_create(self->wm);

    if (dst->type != WND_TYPE_OFFSCREEN)
    {
        if (box_right - box_left > 1)
        {
            xrdp_wm_get_vis_region(self->wm, dst, box_left, box_top,
                                   box_right - box_left, box_bottom - box_top,
                                   region, self->clip_children);
        }
        else
        {
            xrdp_wm_get_vis_region(self->wm, dst, clip_left, clip_top,
                                   clip_right - clip_left, clip_bottom - clip_top,
                                   region, self->clip_children);
        }
    }
    else
    {
        xrdp_region_add_rect(region, &clip_rect);
    }

    clip_left += dx;
    clip_top += dy;
    clip_right += dx;
    clip_bottom += dy;
    box_left += dx;
    box_top += dy;
    box_right += dx;
    box_bottom += dy;
    x += dx;
    y += dy;
    k = 0;

    while (xrdp_region_get_rect(region, k, &rect) == 0)
    {
        if (rect_intersect(&rect, &clip_rect, &draw_rect))
        {
            libxrdp_orders_text(self->session, font, flags, mixmode,
                                self->fg_color, self->bg_color,
                                clip_left, clip_top, clip_right, clip_bottom,
                                box_left, box_top, box_right, box_bottom,
                                x, y, data, data_len, &draw_rect);
        }

        k++;
    }

    xrdp_region_delete(region);
    return 0;
}

/*****************************************************************************/
int
xrdp_painter_draw_char(struct xrdp_painter *self,
                       struct xrdp_bitmap *dst,
                       int x, int y, char32_t chr,
                       unsigned int repeat_count)
{
    int rv = 0;

    if (repeat_count > 0)
    {
        char32_t *utf32 =
            (char32_t *)malloc(repeat_count * sizeof(char32_t));

        if (utf32 == NULL)
        {
            rv = 1;
        }
        else
        {
            unsigned int i = 0;
            for (i = 0; i < repeat_count; ++i)
            {
                utf32[i] = chr;
            }

            rv = xrdp_painter_draw_utf32(self, dst, x, y, utf32, repeat_count);
            free (utf32);
        }
    }

    return rv;
}

/*****************************************************************************/
int
xrdp_painter_copy(struct xrdp_painter *self,
                  struct xrdp_bitmap *src,
                  struct xrdp_bitmap *dst,
                  int x, int y, int cx, int cy,
                  int srcx, int srcy)
{
    struct xrdp_rect clip_rect;
    struct xrdp_rect draw_rect;
    struct xrdp_rect rect1;
    struct xrdp_rect rect2;
    struct xrdp_region *region;
    struct xrdp_bitmap *b;
    int i;
    int j;
    int k;
    int dx;
    int dy;
    int palette_id;
    int bitmap_id;
    int cache_id;
    int cache_idx;
    int dstx;
    int dsty;
    int w;
    int h;
    int index;
    struct list *del_list;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_copy:");

    if (self == 0 || src == 0 || dst == 0)
    {
        return 0;
    }

    if (self->painter != 0)
    {
#if defined(XRDP_PAINTER)
        struct painter_bitmap src_pb;
        struct painter_bitmap dst_pb;
        struct xrdp_bitmap *ldst;

        LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_copy: src->type %d dst->type %d", src->type, dst->type);
        LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_copy: self->rop 0x%2.2x", self->rop);

        if (dst->type != WND_TYPE_OFFSCREEN)
        {
            LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_copy: using painter");
            ldst = self->wm->screen;

            g_memset(&dst_pb, 0sizeof(dst_pb));
            dst_pb.format = get_pt_format(self);
            dst_pb.width = ldst->width;
            dst_pb.stride_bytes = ldst->line_size;
            dst_pb.height = ldst->height;
            dst_pb.data = ldst->data;

            g_memset(&src_pb, 0sizeof(src_pb));
            src_pb.format = get_pt_format(self);
            src_pb.width = src->width;
            src_pb.stride_bytes = src->line_size;
            src_pb.height = src->height;
            src_pb.data = src->data;

            xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
            region = xrdp_region_create(self->wm);
            xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, region,
                                   self->clip_children);
            x += dx;
            y += dy;
            k = 0;

            painter_set_rop(self->painter, self->rop);
            while (xrdp_region_get_rect(region, k, &rect1) == 0)
            {
                if (rect_intersect(&rect1, &clip_rect, &draw_rect))
                {
                    painter_set_clip(self->painter,
                                     draw_rect.left, draw_rect.top,
                                     draw_rect.right - draw_rect.left,
                                     draw_rect.bottom - draw_rect.top);
                    LOG_DEVEL(LOG_LEVEL_DEBUG, "  x %d y %d cx %d cy %d srcx %d srcy %d",
                              x, y, cx, cy, srcx, srcy);
                    painter_copy(self->painter, &dst_pb, x, y, cx, cy,
                                 &src_pb, srcx, srcy);
                    xrdp_painter_add_dirty_rect(self, x, y, cx, cy,
                                                &draw_rect);
                }
                k++;
            }
            painter_clear_clip(self->painter);
            xrdp_region_delete(region);
        }

        return 0;
#endif
    }

    /* todo data */

    if (dst->type == WND_TYPE_BITMAP)
    {
        return 0;
    }

    if (src->type == WND_TYPE_SCREEN)
    {
        xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
        region = xrdp_region_create(self->wm);

        if (dst->type != WND_TYPE_OFFSCREEN)
        {
            xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy,
                                   region, self->clip_children);
        }
        else
        {
            xrdp_region_add_rect(region, &clip_rect);
        }

        x += dx;
        y += dy;
        srcx += dx;
        srcy += dy;
        k = 0;

        while (xrdp_region_get_rect(region, k, &rect1) == 0)
        {
            if (rect_intersect(&rect1, &clip_rect, &draw_rect))
            {
                libxrdp_orders_screen_blt(self->session, x, y, cx, cy,
                                          srcx, srcy, self->rop, &draw_rect);
            }

            k++;
        }

        xrdp_region_delete(region);
    }
    else if (src->type == WND_TYPE_OFFSCREEN)
    {
        LOG(LOG_LEVEL_DEBUG, "xrdp_painter_copy: todo");

        xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
        region = xrdp_region_create(self->wm);

        if (dst->type != WND_TYPE_OFFSCREEN)
        {
            LOG(LOG_LEVEL_DEBUG, "off screen to screen");
            xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy,
                                   region, self->clip_children);
        }
        else
        {
            LOG(LOG_LEVEL_DEBUG, "off screen to off screen");
            xrdp_region_add_rect(region, &clip_rect);
        }

        x += dx;
        y += dy;

        palette_id = 0;
        cache_id = 255// todo
        cache_idx = src->item_index; // todo

        if (src->tab_stop == 0)
        {
            LOG(LOG_LEVEL_WARNING, "xrdp_painter_copy: warning src not created");
            del_list = self->wm->cache->xrdp_os_del_list;
            index = list_index_of(del_list, cache_idx);
            list_remove_item(del_list, index);
            libxrdp_orders_send_create_os_surface(self->session,
                                                  cache_idx,
                                                  src->width,
                                                  src->height,
                                                  del_list);
            src->tab_stop = 1;
            list_clear(del_list);
        }


        k = 0;

        while (xrdp_region_get_rect(region, k, &rect1) == 0)
        {
            if (rect_intersect(&rect1, &clip_rect, &rect2))
            {
                MAKERECT(rect1, x, y, cx, cy);

                if (rect_intersect(&rect2, &rect1, &draw_rect))
                {
                    libxrdp_orders_mem_blt(self->session, cache_id, palette_id,
                                           x, y, cx, cy, self->rop, srcx, srcy,
                                           cache_idx, &draw_rect);
                }
            }

            k++;
        }

        xrdp_region_delete(region);
    }
    else if (src->data != 0)
        /* todo, the non bitmap cache part is gone, it should be put back */
    {
        xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
        region = xrdp_region_create(self->wm);

        if (dst->type != WND_TYPE_OFFSCREEN)
        {
            xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy,
                                   region, self->clip_children);
        }
        else
        {
            xrdp_region_add_rect(region, &clip_rect);
        }

        x += dx;
        y += dy;
        palette_id = 0;
        j = srcy;

        while (j < (srcy + cy))
        {
            i = srcx;

            while (i < (srcx + cx))
            {
                w = MIN(64, ((srcx + cx) - i));
                h = MIN(64, ((srcy + cy) - j));
                b = xrdp_bitmap_create(w, h, src->bpp, 0, self->wm);
#if 1
                xrdp_bitmap_copy_box_with_crc(src, b, i, j, w, h);
#else
                xrdp_bitmap_copy_box(src, b, i, j, w, h);
                xrdp_bitmap_hash_crc(b);
#endif
                bitmap_id = xrdp_cache_add_bitmap(self->wm->cache, b, self->wm->hints);
                cache_id = HIWORD(bitmap_id);
                cache_idx = LOWORD(bitmap_id);
                dstx = (x + i) - srcx;
                dsty = (y + j) - srcy;
                k = 0;

                while (xrdp_region_get_rect(region, k, &rect1) == 0)
                {
                    if (rect_intersect(&rect1, &clip_rect, &rect2))
                    {
                        MAKERECT(rect1, dstx, dsty, w, h);

                        if (rect_intersect(&rect2, &rect1, &draw_rect))
                        {
                            libxrdp_orders_mem_blt(self->session, cache_id, palette_id,
                                                   dstx, dsty, w, h, self->rop, 00,
                                                   cache_idx, &draw_rect);
                        }
                    }

                    k++;
                }

                i += 64;
            }

            j += 64;
        }

        xrdp_region_delete(region);
    }

    return 0;
}

/*****************************************************************************/
int
xrdp_painter_composite(struct xrdp_painter *self,
                       struct xrdp_bitmap *src,
                       int srcformat,
                       int srcwidth,
                       int srcrepeat,
                       struct xrdp_bitmap *dst,
                       int *srctransform,
                       int mskflags,
                       struct xrdp_bitmap *msk,
                       int mskformat, int mskwidth, int mskrepeat, int op,
                       int srcx, int srcy, int mskx, int msky,
                       int dstx, int dsty, int width, int height, int dstformat)
{
    struct xrdp_rect clip_rect;
    struct xrdp_rect draw_rect;
    struct xrdp_rect rect1;
    struct xrdp_rect rect2;
    struct xrdp_region *region;
    int k;
    int dx;
    int dy;
    int cache_srcidx;
    int cache_mskidx;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_composite:");

    if (self == 0 || src == 0 || dst == 0)
    {
        return 0;
    }

    if (self->painter != 0)
    {
        return 0;
    }

    /* todo data */

    if (dst->type == WND_TYPE_BITMAP)
    {
        return 0;
    }

    if (src->type == WND_TYPE_OFFSCREEN)
    {
        xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
        region = xrdp_region_create(self->wm);
        xrdp_region_add_rect(region, &clip_rect);
        dstx += dx;
        dsty += dy;

        cache_srcidx = src->item_index;
        cache_mskidx = -1;
        if (mskflags & 1)
        {
            if (msk != 0)
            {
                cache_mskidx = msk->item_index; // todo
            }
        }

        k = 0;
        while (xrdp_region_get_rect(region, k, &rect1) == 0)
        {
            if (rect_intersect(&rect1, &clip_rect, &rect2))
            {
                MAKERECT(rect1, dstx, dsty, width, height);
                if (rect_intersect(&rect2, &rect1, &draw_rect))
                {
                    libxrdp_orders_composite_blt(self->session, cache_srcidx, srcformat, srcwidth,
                                                 srcrepeat, srctransform, mskflags, cache_mskidx,
                                                 mskformat, mskwidth, mskrepeat, op, srcx, srcy,
                                                 mskx, msky, dstx, dsty, width, height, dstformat,
                                                 &draw_rect);
                }
            }
            k++;
        }
        xrdp_region_delete(region);
    }
    return 0;
}

/*****************************************************************************/
int
xrdp_painter_line(struct xrdp_painter *self,
                  struct xrdp_bitmap *dst,
                  int x1, int y1, int x2, int y2)
{
    struct xrdp_rect clip_rect;
    struct xrdp_rect draw_rect;
    struct xrdp_rect rect;
    struct xrdp_region *region;
    int k;
    int dx;
    int dy;
    int rop;

    LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_line:");
    if (self == 0)
    {
        return 0;
    }
    if (self->painter != 0)
    {
#if defined(XRDP_PAINTER)
        int x;
        int y;
        int cx;
        int cy;
        struct painter_bitmap dst_pb;
        struct xrdp_bitmap *ldst;

        LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_line: dst->type %d", dst->type);
        LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_line: self->rop 0x%2.2x", self->rop);

        if (dst->type != WND_TYPE_OFFSCREEN)
        {
            LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_line: using painter");
            ldst = self->wm->screen;

            g_memset(&dst_pb, 0sizeof(dst_pb));
            dst_pb.format = get_pt_format(self);
            dst_pb.width = ldst->width;
            dst_pb.stride_bytes = ldst->line_size;
            dst_pb.height = ldst->height;
            dst_pb.data = ldst->data;

            xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
            region = xrdp_region_create(self->wm);
            x = MIN(x1, x2);
            y = MIN(y1, y2);
            cx = g_abs(x1 - x2) + 1;
            cy = g_abs(y1 - y2) + 1;
            xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy,
                                   region, self->clip_children);
            x1 += dx;
            y1 += dy;
            x2 += dx;
            y2 += dy;
            k = 0;
            rop = self->rop;

            painter_set_rop(self->painter, rop);
            painter_set_fgcolor(self->painter, self->pen.color);
            while (xrdp_region_get_rect(region, k, &rect) == 0)
            {
                if (rect_intersect(&rect, &clip_rect, &draw_rect))
                {
                    painter_set_clip(self->painter,
                                     draw_rect.left, draw_rect.top,
                                     draw_rect.right - draw_rect.left,
                                     draw_rect.bottom - draw_rect.top);
                    painter_line(self->painter, &dst_pb, x1, y1, x2, y2,
                                 self->pen.width, 0);
                    xrdp_painter_add_dirty_rect(self, x, y, cx, cy,
                                                &draw_rect);
                }
                k++;
            }
            painter_clear_clip(self->painter);
            xrdp_region_delete(region);
        }

        return 0;
#endif
    }

    /* todo data */

    if (dst->type == WND_TYPE_BITMAP)
    {
        return 0;
    }

    xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
    region = xrdp_region_create(self->wm);

    if (dst->type != WND_TYPE_OFFSCREEN)
    {
        xrdp_wm_get_vis_region(self->wm, dst, MIN(x1, x2), MIN(y1, y2),
                               g_abs(x1 - x2) + 1, g_abs(y1 - y2) + 1,
                               region, self->clip_children);
    }
    else
    {
        xrdp_region_add_rect(region, &clip_rect);
    }

    x1 += dx;
    y1 += dy;
    x2 += dx;
    y2 += dy;
    k = 0;
    rop = self->rop;

    if (rop < 0x01 || rop > 0x10)
    {
        rop = (rop & 0xf) + 1;
    }

    while (xrdp_region_get_rect(region, k, &rect) == 0)
    {
        if (rect_intersect(&rect, &clip_rect, &draw_rect))
        {
            libxrdp_orders_line(self->session, 1, x1, y1, x2, y2,
                                rop, self->bg_color,
                                &self->pen, &draw_rect);
        }

        k++;
    }

    xrdp_region_delete(region);
    return 0;
}

Messung V0.5 in Prozent
C=87 H=91 G=88

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-07-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik