FreeRDP/libfreerdp/cache/pointer.c

463 lines
11 KiB
C
Raw Normal View History

2011-08-24 19:20:41 +04:00
/**
2012-10-09 07:02:04 +04:00
* FreeRDP: A Remote Desktop Protocol Implementation
2011-08-24 19:20:41 +04:00
* Glyph Cache
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
2011-08-24 19:20:41 +04:00
#include <freerdp/log.h>
2011-08-24 19:20:41 +04:00
#include <freerdp/cache/pointer.h>
#include "pointer.h"
#define TAG FREERDP_TAG("cache.pointer")
2011-08-24 19:20:41 +04:00
2016-10-10 11:26:54 +03:00
static BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index,
2016-07-18 15:16:13 +03:00
rdpPointer* pointer);
static const rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache,
UINT32 index);
2016-10-10 11:26:54 +03:00
static void pointer_free(rdpContext* context, rdpPointer* pointer)
{
if (pointer)
{
IFCALL(pointer->Free, context, pointer);
2016-10-10 11:26:54 +03:00
if (pointer->xorMaskData)
{
free(pointer->xorMaskData);
pointer->xorMaskData = NULL;
}
if (pointer->andMaskData)
{
free(pointer->andMaskData);
pointer->andMaskData = NULL;
}
free(pointer);
}
}
static BOOL update_pointer_position(rdpContext* context,
2016-07-18 15:16:13 +03:00
const POINTER_POSITION_UPDATE* pointer_position)
2011-08-24 19:20:41 +04:00
{
2016-07-18 15:16:13 +03:00
rdpPointer* pointer;
if (!context || !context->graphics || !context->graphics->Pointer_Prototype
|| !pointer_position)
return FALSE;
pointer = context->graphics->Pointer_Prototype;
return IFCALLRESULT(TRUE, pointer->SetPosition, context, pointer_position->xPos,
2016-07-18 15:16:13 +03:00
pointer_position->yPos);
}
static BOOL update_pointer_system(rdpContext* context,
2016-07-18 15:16:13 +03:00
const POINTER_SYSTEM_UPDATE* pointer_system)
{
2016-07-18 15:16:13 +03:00
rdpPointer* pointer;
if (!context || !context->graphics || !context->graphics->Pointer_Prototype
|| !pointer_system)
return FALSE;
pointer = context->graphics->Pointer_Prototype;
switch (pointer_system->type)
{
case SYSPTR_NULL:
return IFCALLRESULT(TRUE, pointer->SetNull, context);
case SYSPTR_DEFAULT:
return IFCALLRESULT(TRUE, pointer->SetDefault, context);
default:
WLog_ERR(TAG, "Unknown system pointer type (0x%08"PRIX32")", pointer_system->type);
}
return TRUE;
}
static BOOL update_pointer_color(rdpContext* context,
2016-07-18 15:16:13 +03:00
const POINTER_COLOR_UPDATE* pointer_color)
{
rdpPointer* pointer;
rdpCache* cache = context->cache;
pointer = Pointer_Alloc(context);
if (pointer != NULL)
{
pointer->xorBpp = 24;
pointer->xPos = pointer_color->xPos;
pointer->yPos = pointer_color->yPos;
pointer->width = pointer_color->width;
pointer->height = pointer_color->height;
pointer->lengthAndMask = pointer_color->lengthAndMask;
pointer->lengthXorMask = pointer_color->lengthXorMask;
if (pointer->lengthAndMask && pointer_color->andMaskData)
2013-06-28 17:17:37 +04:00
{
pointer->andMaskData = (BYTE*) malloc(pointer->lengthAndMask);
2016-07-18 15:16:13 +03:00
if (!pointer->andMaskData)
goto out_fail;
2016-07-18 15:16:13 +03:00
CopyMemory(pointer->andMaskData, pointer_color->andMaskData,
pointer->lengthAndMask);
2013-06-28 17:17:37 +04:00
}
if (pointer->lengthXorMask && pointer_color->xorMaskData)
{
pointer->xorMaskData = (BYTE*) malloc(pointer->lengthXorMask);
2016-07-18 15:16:13 +03:00
if (!pointer->xorMaskData)
goto out_fail;
2016-07-18 15:16:13 +03:00
CopyMemory(pointer->xorMaskData, pointer_color->xorMaskData,
pointer->lengthXorMask);
2013-06-28 17:17:37 +04:00
}
2016-07-18 15:16:13 +03:00
if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
2016-10-10 11:26:54 +03:00
goto out_fail;
if (!pointer_cache_put(cache->pointer, pointer_color->cacheIndex, pointer))
goto out_fail;
return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
}
2016-07-18 15:16:13 +03:00
return FALSE;
out_fail:
2016-10-10 11:26:54 +03:00
pointer_free(context, pointer);
return FALSE;
}
static BOOL update_pointer_new(rdpContext* context,
2016-07-18 15:16:13 +03:00
const POINTER_NEW_UPDATE* pointer_new)
{
rdpPointer* pointer;
2016-08-04 14:24:35 +03:00
rdpCache* cache;
if (!context || !pointer_new)
return FALSE;
cache = context->cache;
pointer = Pointer_Alloc(context);
2016-07-18 15:16:13 +03:00
if (!pointer)
return FALSE;
pointer->xorBpp = pointer_new->xorBpp;
pointer->xPos = pointer_new->colorPtrAttr.xPos;
pointer->yPos = pointer_new->colorPtrAttr.yPos;
pointer->width = pointer_new->colorPtrAttr.width;
pointer->height = pointer_new->colorPtrAttr.height;
pointer->lengthAndMask = pointer_new->colorPtrAttr.lengthAndMask;
pointer->lengthXorMask = pointer_new->colorPtrAttr.lengthXorMask;
if (pointer->lengthAndMask)
{
pointer->andMaskData = (BYTE*) malloc(pointer->lengthAndMask);
2016-07-18 15:16:13 +03:00
if (!pointer->andMaskData)
goto out_fail;
2016-07-18 15:16:13 +03:00
CopyMemory(pointer->andMaskData, pointer_new->colorPtrAttr.andMaskData,
pointer->lengthAndMask);
}
if (pointer->lengthXorMask)
{
pointer->xorMaskData = (BYTE*) malloc(pointer->lengthXorMask);
2016-07-18 15:16:13 +03:00
if (!pointer->xorMaskData)
goto out_fail;
2016-07-18 15:16:13 +03:00
CopyMemory(pointer->xorMaskData, pointer_new->colorPtrAttr.xorMaskData,
pointer->lengthXorMask);
}
if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
goto out_fail;
2016-10-10 11:26:54 +03:00
if (!pointer_cache_put(cache->pointer, pointer_new->colorPtrAttr.cacheIndex,
pointer))
goto out_fail;
return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
out_fail:
2016-10-10 11:26:54 +03:00
pointer_free(context, pointer);
return FALSE;
}
static BOOL update_pointer_cached(rdpContext* context,
2016-07-18 15:16:13 +03:00
const POINTER_CACHED_UPDATE* pointer_cached)
{
const rdpPointer* pointer;
rdpCache* cache = context->cache;
pointer = pointer_cache_get(cache->pointer, pointer_cached->cacheIndex);
if (pointer != NULL)
return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
2016-07-18 15:16:13 +03:00
return FALSE;
}
2016-07-18 15:16:13 +03:00
const rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache,
UINT32 index)
{
const rdpPointer* pointer;
if (index >= pointer_cache->cacheSize)
2011-08-24 19:20:41 +04:00
{
WLog_ERR(TAG, "invalid pointer index:%"PRIu32"", index);
2011-08-24 19:20:41 +04:00
return NULL;
}
pointer = pointer_cache->entries[index];
return pointer;
2011-08-24 19:20:41 +04:00
}
2016-10-10 11:26:54 +03:00
BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index,
2016-07-18 15:16:13 +03:00
rdpPointer* pointer)
2011-08-24 19:20:41 +04:00
{
2012-02-02 06:11:46 +04:00
rdpPointer* prevPointer;
if (index >= pointer_cache->cacheSize)
2011-08-24 19:20:41 +04:00
{
WLog_ERR(TAG, "invalid pointer index:%"PRIu32"", index);
2016-10-10 11:26:54 +03:00
return FALSE;
2011-08-24 19:20:41 +04:00
}
2012-02-02 06:11:46 +04:00
prevPointer = pointer_cache->entries[index];
2016-10-10 11:26:54 +03:00
pointer_free(pointer_cache->update->context, prevPointer);
pointer_cache->entries[index] = pointer;
2016-10-10 11:26:54 +03:00
return TRUE;
2011-08-24 19:20:41 +04:00
}
void pointer_cache_register_callbacks(rdpUpdate* update)
2011-08-24 19:20:41 +04:00
{
rdpPointerUpdate* pointer = update->pointer;
pointer->PointerPosition = update_pointer_position;
pointer->PointerSystem = update_pointer_system;
pointer->PointerColor = update_pointer_color;
pointer->PointerNew = update_pointer_new;
pointer->PointerCached = update_pointer_cached;
}
2011-08-24 19:20:41 +04:00
rdpPointerCache* pointer_cache_new(rdpSettings* settings)
{
rdpPointerCache* pointer_cache;
pointer_cache = (rdpPointerCache*) calloc(1, sizeof(rdpPointerCache));
2016-07-18 15:16:13 +03:00
if (!pointer_cache)
return NULL;
pointer_cache->settings = settings;
pointer_cache->cacheSize = settings->PointerCacheSize;
pointer_cache->update = ((freerdp*) settings->instance)->update;
2016-07-18 15:16:13 +03:00
pointer_cache->entries = (rdpPointer**) calloc(pointer_cache->cacheSize,
sizeof(rdpPointer*));
if (!pointer_cache->entries)
{
free(pointer_cache);
return NULL;
2011-08-24 19:20:41 +04:00
}
return pointer_cache;
2011-08-24 19:20:41 +04:00
}
void pointer_cache_free(rdpPointerCache* pointer_cache)
2011-08-24 19:20:41 +04:00
{
if (pointer_cache != NULL)
2011-08-24 19:20:41 +04:00
{
UINT32 i;
rdpPointer* pointer;
2011-08-24 19:20:41 +04:00
for (i = 0; i < pointer_cache->cacheSize; i++)
2011-08-24 19:20:41 +04:00
{
pointer = pointer_cache->entries[i];
2016-10-10 11:26:54 +03:00
pointer_free(pointer_cache->update->context, pointer);
2011-08-24 19:20:41 +04:00
}
free(pointer_cache->entries);
free(pointer_cache);
2011-08-24 19:20:41 +04:00
}
}
POINTER_COLOR_UPDATE* copy_pointer_color_update(rdpContext* context,
const POINTER_COLOR_UPDATE* src)
{
POINTER_COLOR_UPDATE* dst = calloc(1, sizeof(POINTER_COLOR_UPDATE));
if (!dst || !src)
goto fail;
*dst = *src;
if (src->lengthAndMask > 0)
{
dst->andMaskData = calloc(src->lengthAndMask, sizeof(BYTE));
if (!dst->andMaskData)
goto fail;
memcpy(dst->andMaskData, src->andMaskData, src->lengthAndMask);
}
if (src->lengthXorMask > 0)
{
dst->xorMaskData = calloc(src->lengthXorMask, sizeof(BYTE));
if (!dst->xorMaskData)
goto fail;
memcpy(dst->xorMaskData, src->xorMaskData, src->lengthXorMask);
}
return dst;
fail:
free_pointer_color_update(context, dst);
return NULL;
}
void free_pointer_color_update(rdpContext* context, POINTER_COLOR_UPDATE* pointer)
{
if (!pointer)
return;
free(pointer->xorMaskData);
free(pointer->andMaskData);
free(pointer);
}
POINTER_NEW_UPDATE* copy_pointer_new_update(rdpContext* context, const POINTER_NEW_UPDATE* src)
{
POINTER_NEW_UPDATE* dst = calloc(1, sizeof(POINTER_NEW_UPDATE));
if (!dst || !src)
goto fail;
*dst = *src;
if (src->colorPtrAttr.lengthAndMask > 0)
{
dst->colorPtrAttr.andMaskData = calloc(src->colorPtrAttr.lengthAndMask, sizeof(BYTE));
if (!dst->colorPtrAttr.andMaskData)
goto fail;
memcpy(dst->colorPtrAttr.andMaskData, src->colorPtrAttr.andMaskData,
src->colorPtrAttr.lengthAndMask);
}
if (src->colorPtrAttr.lengthXorMask > 0)
{
dst->colorPtrAttr.xorMaskData = calloc(src->colorPtrAttr.lengthXorMask, sizeof(BYTE));
if (!dst->colorPtrAttr.xorMaskData)
goto fail;
memcpy(dst->colorPtrAttr.xorMaskData, src->colorPtrAttr.xorMaskData,
src->colorPtrAttr.lengthXorMask);
}
return dst;
fail:
free_pointer_new_update(context, dst);
return NULL;
}
void free_pointer_new_update(rdpContext* context, POINTER_NEW_UPDATE* pointer)
{
if (!pointer)
return;
free(pointer->colorPtrAttr.xorMaskData);
free(pointer->colorPtrAttr.andMaskData);
free(pointer);
}
POINTER_CACHED_UPDATE* copy_pointer_cached_update(rdpContext* context,
const POINTER_CACHED_UPDATE* pointer)
{
POINTER_CACHED_UPDATE* dst = calloc(1, sizeof(POINTER_CACHED_UPDATE));
if (!dst)
goto fail;
*dst = *pointer;
return dst;
fail:
free_pointer_cached_update(context, dst);
return NULL;
}
void free_pointer_cached_update(rdpContext* context, POINTER_CACHED_UPDATE* pointer)
{
free(pointer);
}
void free_pointer_position_update(rdpContext* context, POINTER_POSITION_UPDATE* pointer)
{
free(pointer);
}
POINTER_POSITION_UPDATE* copy_pointer_position_update(rdpContext* context,
const POINTER_POSITION_UPDATE* pointer)
{
POINTER_POSITION_UPDATE* dst = calloc(1, sizeof(POINTER_POSITION_UPDATE));
if (!dst || !pointer)
goto fail;
*dst = *pointer;
return dst;
fail:
free_pointer_position_update(context, dst);
return NULL;
}
void free_pointer_system_update(rdpContext* context, POINTER_SYSTEM_UPDATE* pointer)
{
free(pointer);
}
POINTER_SYSTEM_UPDATE* copy_pointer_system_update(rdpContext* context,
const POINTER_SYSTEM_UPDATE* pointer)
{
POINTER_SYSTEM_UPDATE* dst = calloc(1, sizeof(POINTER_SYSTEM_UPDATE));
if (!dst || !pointer)
goto fail;
*dst = *pointer;
return dst;
fail:
free_pointer_system_update(context, dst);
return NULL;
}