diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index a3ff1b4b0..35c6c7ca2 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -46,6 +46,7 @@ typedef struct rdp_shadow_surface rdpShadowSurface; typedef struct rdp_shadow_encoder rdpShadowEncoder; typedef struct rdp_shadow_capture rdpShadowCapture; typedef struct rdp_shadow_subsystem rdpShadowSubsystem; +typedef struct rdp_shadow_font rdpShadowFont; typedef struct _RDP_SHADOW_ENTRY_POINTS RDP_SHADOW_ENTRY_POINTS; typedef int (*pfnShadowSubsystemEntry)(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index 4e69817f1..14c348c7e 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -167,6 +167,8 @@ set(${MODULE_PREFIX}_SRCS shadow_encomsp.h shadow_remdesk.c shadow_remdesk.h + shadow_font.c + shadow_font.h shadow_subsystem.c shadow_subsystem.h shadow_server.c diff --git a/server/shadow/shadow.h b/server/shadow/shadow.h index f2114bde7..ce7d6f091 100644 --- a/server/shadow/shadow.h +++ b/server/shadow/shadow.h @@ -29,6 +29,7 @@ #include "shadow_capture.h" #include "shadow_channels.h" #include "shadow_subsystem.h" +#include "shadow_font.h" #ifdef __cplusplus extern "C" { diff --git a/server/shadow/shadow_font.c b/server/shadow/shadow_font.c new file mode 100644 index 000000000..83d9ce89d --- /dev/null +++ b/server/shadow/shadow_font.c @@ -0,0 +1,450 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau + * + * 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 "shadow.h" + +#include "shadow_font.h" + +#define TEST_FONT_IMAGE "source_serif_pro_regular_12.png" +#define TEST_FONT_DESCRIPTOR "source_serif_pro_regular_12.xml" + +char* shadow_font_load_descriptor_file(const char* filename, int* pSize) +{ + BYTE* buffer; + FILE* fp = NULL; + size_t readSize; + size_t fileSize; + + fp = fopen(filename, "r"); + + if (!fp) + return NULL; + + fseek(fp, 0, SEEK_END); + fileSize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (fileSize < 1) + { + fclose(fp); + return NULL; + } + + buffer = (BYTE*) malloc(fileSize + 2); + + if (!buffer) + { + fclose(fp); + return NULL; + } + + readSize = fread(buffer, fileSize, 1, fp); + + if (!readSize) + { + if (!ferror(fp)) + readSize = fileSize; + } + + fclose(fp); + + if (readSize < 1) + { + free(buffer); + return NULL; + } + + buffer[fileSize] = '\0'; + buffer[fileSize + 1] = '\0'; + + *pSize = (int) fileSize; + return (char*) buffer; +} + +int shadow_font_convert_descriptor_code_to_utf8(const char* str, BYTE* utf8) +{ + int len = strlen(str); + + *((UINT32*) utf8) = 0; + + if (len == 1) + { + if ((str[0] > 31) && (str[0] < 127)) + { + utf8[0] = str[0]; + } + } + + return 1; +} + +int shadow_font_load_descriptor(rdpShadowFont* font, const char* filename) +{ + char* p; + char* q; + char* r; + char* beg; + char* end; + char* tok[4]; + int index; + int count; + int size; + char* buffer; + rdpShadowGlyph* glyph; + + buffer = shadow_font_load_descriptor_file(filename, &size); + + if (!buffer) + return -1; + + p = strstr(buffer, ""); + + if (!p) + return -1; + + p += sizeof("") - 1; + + p = strstr(p, ""); + + if (!end) + return -1; + + /* parse font size */ + + p = strstr(p, "size=\""); + + if (!p) + return -1; + + p += sizeof("size=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + font->size = atoi(p); + *q = '"'; + + if (font->size <= 0) + return -1; + + p = q + 1; + + /* parse font family */ + + p = strstr(p, "family=\""); + + if (!p) + return -1; + + p += sizeof("family=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + font->family = _strdup(p); + *q = '"'; + + if (!font->family) + return -1; + + p = q + 1; + + /* parse font height */ + + p = strstr(p, "height=\""); + + if (!p) + return -1; + + p += sizeof("height=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + font->height = atoi(p); + *q = '"'; + + if (font->height <= 0) + return -1; + + p = q + 1; + + /* parse font style */ + + p = strstr(p, "style=\""); + + if (!p) + return -1; + + p += sizeof("style=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + font->style = _strdup(p); + *q = '"'; + + if (!font->style) + return -1; + + p = q + 1; + + printf("size: %d family: %s height: %d style: %s\n", + font->size, font->family, font->height, font->style); + + beg = p; + count = 0; + + while (p < end) + { + p = strstr(p, ""); + + if (!r) + return -1; + + *r = '\0'; + + p = r + sizeof("/>"); + *r = '/'; + + count++; + } + + font->glyphCount = count; + font->glyphs = (rdpShadowGlyph*) calloc(font->glyphCount, sizeof(rdpShadowGlyph)); + + if (!font->glyphs) + return -1; + + p = beg; + index = 0; + + while (p < end) + { + p = strstr(p, ""); + + if (!r) + return -1; + + *r = '\0'; + + /* start parsing glyph */ + + glyph = &font->glyphs[index]; + + /* parse glyph width */ + + p = strstr(p, "width=\""); + + if (!p) + return -1; + + p += sizeof("width=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + glyph->width = atoi(p); + *q = '"'; + + if (glyph->width < 0) + return -1; + + p = q + 1; + + /* parse glyph offset x,y */ + + p = strstr(p, "offset=\""); + + if (!p) + return -1; + + p += sizeof("offset=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + + tok[0] = p; + + p = strchr(tok[0] + 1, ' '); + + if (!p) + return -1; + + *p = 0; + tok[1] = p + 1; + + glyph->offsetX = atoi(tok[0]); + glyph->offsetY = atoi(tok[1]); + + *q = '"'; + + p = q + 1; + + /* parse glyph rect x,y,w,h */ + + p = strstr(p, "rect=\""); + + if (!p) + return -1; + + p += sizeof("rect=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + + tok[0] = p; + + p = strchr(tok[0] + 1, ' '); + + if (!p) + return -1; + + *p = 0; + tok[1] = p + 1; + + p = strchr(tok[1] + 1, ' '); + + if (!p) + return -1; + + *p = 0; + tok[2] = p + 1; + + p = strchr(tok[2] + 1, ' '); + + if (!p) + return -1; + + *p = 0; + tok[3] = p + 1; + + glyph->rectX = atoi(tok[0]); + glyph->rectY = atoi(tok[1]); + glyph->rectWidth = atoi(tok[2]); + glyph->rectHeight = atoi(tok[3]); + + *q = '"'; + + p = q + 1; + + /* parse code */ + + p = strstr(p, "code=\""); + + if (!p) + return -1; + + p += sizeof("code=\"") - 1; + q = strchr(p, '"'); + + if (!q) + return -1; + + *q = '\0'; + shadow_font_convert_descriptor_code_to_utf8(p, glyph->code); + *q = '"'; + + p = q + 1; + + /* finish parsing glyph */ + + p = r + sizeof("/>"); + *r = '/'; + + index++; + } + + return 1; +} + +rdpShadowFont* shadow_font_new(const char* filename) +{ + int status; + rdpShadowFont* font; + + font = (rdpShadowFont*) calloc(1, sizeof(rdpShadowFont)); + + if (!font) + return NULL; + + font->image = winpr_image_new(); + + if (!font->image) + return NULL; + + status = winpr_image_read(font->image, TEST_FONT_IMAGE); + + if (status < 0) + return NULL; + + status = shadow_font_load_descriptor(font, TEST_FONT_DESCRIPTOR); + + return font; +} + +void shadow_font_free(rdpShadowFont* font) +{ + if (!font) + return; + + free(font); +} diff --git a/server/shadow/shadow_font.h b/server/shadow/shadow_font.h new file mode 100644 index 000000000..69615e580 --- /dev/null +++ b/server/shadow/shadow_font.h @@ -0,0 +1,63 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau + * + * 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. + */ + +#ifndef FREERDP_SHADOW_SERVER_FONT_H +#define FREERDP_SHADOW_SERVER_FONT_H + +#include + +#include +#include +#include + +struct rdp_shadow_glyph +{ + int width; + int offsetX; + int offsetY; + int rectX; + int rectY; + int rectWidth; + int rectHeight; + BYTE code[4]; +}; +typedef struct rdp_shadow_glyph rdpShadowGlyph; + +struct rdp_shadow_font +{ + int size; + int height; + char* family; + char* style; + wImage* image; + int glyphCount; + rdpShadowGlyph* glyphs; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +rdpShadowFont* shadow_font_new(const char* filename); +void shadow_font_free(rdpShadowFont* font); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_SHADOW_SERVER_FONT_H */ diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c index 48b0192ed..caf6d95b1 100644 --- a/server/shadow/shadow_server.c +++ b/server/shadow/shadow_server.c @@ -527,6 +527,17 @@ int shadow_server_init_certificate(rdpShadowServer* server) return 1; } +int shadow_server_init_fonts(rdpShadowServer* server) +{ + rdpShadowFont* font; + + font = shadow_font_new("source_serif_pro_regular_12"); + + shadow_font_free(font); + + return 1; +} + int shadow_server_init(rdpShadowServer* server) { int status; @@ -551,6 +562,8 @@ int shadow_server_init(rdpShadowServer* server) if (status < 0) return -1; + //shadow_server_init_fonts(server); + server->listener = freerdp_listener_new(); if (!server->listener)