shadow: initial font rendering
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 29 Sep 2014 18:07:48 +0000 (14:07 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 29 Sep 2014 18:07:48 +0000 (14:07 -0400)
server/shadow/shadow_client.c
server/shadow/shadow_font.c
server/shadow/shadow_font.h
server/shadow/shadow_server.c

index 2fe6c1b..e03e97d 100644 (file)
@@ -33,6 +33,8 @@
 
 #define TAG CLIENT_TAG("shadow")
 
+extern rdpShadowFont* g_Font;
+
 void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
 {
        rdpSettings* settings;
@@ -130,13 +132,47 @@ BOOL shadow_client_capabilities(freerdp_peer* peer)
        return TRUE;
 }
 
+int shadow_client_init_lobby(rdpShadowClient* client)
+{
+       int width;
+       int height;
+       RECTANGLE_16 invalidRect;
+       rdpShadowSurface* lobby;
+       rdpContext* context = (rdpContext*) client;
+       rdpSettings* settings = context->settings;
+
+       width = settings->DesktopWidth;
+       height = settings->DesktopHeight;
+
+       lobby = client->lobby = shadow_surface_new(client->server, 0, 0, width, height);
+
+       if (!client->lobby)
+               return -1;
+
+       freerdp_image_fill(lobby->data, PIXEL_FORMAT_XRGB32, lobby->scanline,
+                       0, 0, lobby->width, lobby->height, 0x3BB9FF);
+
+       if (g_Font)
+       {
+               shadow_font_draw_text(lobby, 16, 16, g_Font, "Welcome to the shadow server!");
+       }
+
+       invalidRect.left = 0;
+       invalidRect.top = 0;
+       invalidRect.right = width;
+       invalidRect.bottom = height;
+
+       region16_union_rect(&(lobby->invalidRegion), &(lobby->invalidRegion), &invalidRect);
+
+       return 1;
+}
+
 BOOL shadow_client_post_connect(freerdp_peer* peer)
 {
        int authStatus;
        int width, height;
        rdpSettings* settings;
        rdpShadowClient* client;
-       rdpShadowSurface* lobby;
        rdpShadowServer* server;
        RECTANGLE_16 invalidRect;
        rdpShadowSubsystem* subsystem;
@@ -177,15 +213,7 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
 
        region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &invalidRect);
 
-       lobby = client->lobby = shadow_surface_new(client->server, 0, 0, width, height);
-
-       if (!client->lobby)
-               return FALSE;
-
-       freerdp_image_fill(lobby->data, PIXEL_FORMAT_XRGB32, lobby->scanline,
-                       0, 0, lobby->width, lobby->height, 0x3BB9FF);
-
-       region16_union_rect(&(lobby->invalidRegion), &(lobby->invalidRegion), &invalidRect);
+       shadow_client_init_lobby(client);
 
        authStatus = -1;
 
index 83d9ce8..c61c401 100644 (file)
 #include "config.h"
 #endif
 
+#include <winpr/crt.h>
+#include <winpr/path.h>
+
 #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"
+int shadow_font_draw_glyph(rdpShadowSurface* surface, int nXDst, int nYDst, rdpShadowFont* font, rdpShadowGlyph* glyph)
+{
+       int x, y;
+       int nXSrc;
+       int nYSrc;
+       int nWidth;
+       int nHeight;
+       int nSrcStep;
+       int nDstStep;
+       int nSrcPad;
+       int nDstPad;
+       BYTE* pSrcData;
+       BYTE* pSrcPixel;
+       BYTE* pDstData;
+       BYTE* pDstPixel;
+       BYTE A, R, G, B;
+
+       nXDst += glyph->offsetX;
+       nYDst += glyph->offsetY;
+
+       nXSrc = glyph->rectX;
+       nYSrc = glyph->rectY;
+
+       nWidth = glyph->rectWidth;
+       nHeight = glyph->rectHeight;
+
+       nSrcStep = font->image->scanline;
+       pSrcData = font->image->data;
+
+       pDstData = surface->data;
+       nDstStep = surface->scanline;
+
+       nSrcPad = (nSrcStep - (nWidth * 4));
+       nDstPad = (nDstStep - (nWidth * 4));
+
+       pSrcPixel = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
+       pDstPixel = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
+
+       for (y = 0; y < nHeight; y++)
+       {
+               pSrcPixel = &pSrcData[((nYSrc + y) * nSrcStep) + (nXSrc * 4)];
+               pDstPixel = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)];
+
+               for (x = 0; x < nWidth; x++)
+               {
+                       B = pSrcPixel[0];
+                       G = pSrcPixel[1];
+                       R = pSrcPixel[2];
+                       A = pSrcPixel[3];
+                       pSrcPixel += 4;
+
+                       if (1)
+                       {
+                               /* tint black */
+                               R = 255 - R;
+                               G = 255 - G;
+                               B = 255 - B;
+                       }
+
+                       if (A == 255)
+                       {
+                               pDstPixel[0] = B;
+                               pDstPixel[1] = G;
+                               pDstPixel[2] = R;
+                       }
+                       else
+                       {
+                               R = (R * A) / 255;
+                               G = (G * A) / 255;
+                               B = (B * A) / 255;
+
+                               pDstPixel[0] = B + (pDstPixel[0] * (255 - A) + (255 / 2)) / 255;
+                               pDstPixel[1] = G + (pDstPixel[1] * (255 - A) + (255 / 2)) / 255;
+                               pDstPixel[2] = R + (pDstPixel[2] * (255 - A) + (255 / 2)) / 255;
+                       }
+
+                       pDstPixel[3] = 0xFF;
+                       pDstPixel += 4;
+               }
+
+               pSrcPixel += nSrcPad;
+               pDstPixel += nDstPad;
+       }
+
+       return 1;
+}
+
+int shadow_font_draw_text(rdpShadowSurface* surface, int nXDst, int nYDst, rdpShadowFont* font, const char* text)
+{
+       int index;
+       int length;
+       rdpShadowGlyph* glyph;
+
+       length = strlen(text);
+
+       for (index = 0; index < length; index++)
+       {
+               glyph = &font->glyphs[text[index] - 32];
+               shadow_font_draw_glyph(surface, nXDst, nYDst, font, glyph);
+               nXDst += (glyph->width + 1);
+       }
+
+       return 1;
+}
 
 char* shadow_font_load_descriptor_file(const char* filename, int* pSize)
 {
@@ -86,6 +191,9 @@ int shadow_font_convert_descriptor_code_to_utf8(const char* str, BYTE* utf8)
 
        *((UINT32*) utf8) = 0;
 
+       if (len < 1)
+               return 1;
+
        if (len == 1)
        {
                if ((str[0] > 31) && (str[0] < 127))
@@ -93,6 +201,22 @@ int shadow_font_convert_descriptor_code_to_utf8(const char* str, BYTE* utf8)
                        utf8[0] = str[0];
                }
        }
+       else
+       {
+               if (str[0] == '&')
+               {
+                       const char* acc = &str[1];
+
+                       if (strcmp(acc, "quot;") == 0)
+                               utf8[0] = '"';
+                       else if (strcmp(acc, "amp;") == 0)
+                               utf8[0] = '&';
+                       else if (strcmp(acc, "lt;") == 0)
+                               utf8[0] = '<';
+                       else if (strcmp(acc, "gt;") == 0)
+                               utf8[0] = '>';
+               }
+       }
 
        return 1;
 }
@@ -416,10 +540,45 @@ int shadow_font_load_descriptor(rdpShadowFont* font, const char* filename)
        return 1;
 }
 
-rdpShadowFont* shadow_font_new(const char* filename)
+rdpShadowFont* shadow_font_new(const char* path, const char* file)
 {
        int status;
+       int length;
        rdpShadowFont* font;
+       char* fontBaseFile;
+       char* fontImageFile;
+       char* fontDescriptorFile;
+
+       fontBaseFile = GetCombinedPath(path, file);
+
+       if (!fontBaseFile)
+               return NULL;
+
+       length = strlen(fontBaseFile);
+
+       fontImageFile = (char*) malloc(length + 8);
+
+       if (!fontImageFile)
+               return NULL;
+
+       strcpy(fontImageFile, fontBaseFile);
+       strcpy(&fontImageFile[length], ".png");
+
+       fontDescriptorFile = (char*) malloc(length + 8);
+
+       if (!fontImageFile)
+               return NULL;
+
+       strcpy(fontDescriptorFile, fontBaseFile);
+       strcpy(&fontDescriptorFile[length], ".xml");
+
+       free(fontBaseFile);
+
+       if (!PathFileExistsA(fontImageFile))
+               return NULL;
+
+       if (!PathFileExistsA(fontDescriptorFile))
+               return NULL;
 
        font = (rdpShadowFont*) calloc(1, sizeof(rdpShadowFont));
 
@@ -431,12 +590,15 @@ rdpShadowFont* shadow_font_new(const char* filename)
        if (!font->image)
                return NULL;
 
-       status = winpr_image_read(font->image, TEST_FONT_IMAGE);
+       status = winpr_image_read(font->image, fontImageFile);
 
        if (status < 0)
                return NULL;
 
-       status = shadow_font_load_descriptor(font, TEST_FONT_DESCRIPTOR);
+       status = shadow_font_load_descriptor(font, fontDescriptorFile);
+
+       free(fontImageFile);
+       free(fontDescriptorFile);
 
        return font;
 }
index 69615e5..2ec8ecb 100644 (file)
@@ -53,7 +53,10 @@ struct rdp_shadow_font
 extern "C" {
 #endif
 
-rdpShadowFont* shadow_font_new(const char* filename);
+int shadow_font_draw_text(rdpShadowSurface* surface, int nXDst, int nYDst, rdpShadowFont* font, const char* text);
+int shadow_font_draw_glyph(rdpShadowSurface* surface, int nXDst, int nYDst, rdpShadowFont* font, rdpShadowGlyph* glyph);
+
+rdpShadowFont* shadow_font_new(const char* path, const char* file);
 void shadow_font_free(rdpShadowFont* font);
 
 #ifdef __cplusplus
index caf6d95..c4acec3 100644 (file)
@@ -41,6 +41,8 @@
 
 #define TAG SERVER_TAG("shadow")
 
+rdpShadowFont* g_Font = NULL;
+
 static COMMAND_LINE_ARGUMENT_A shadow_args[] =
 {
        { "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" },
@@ -529,11 +531,16 @@ int shadow_server_init_certificate(rdpShadowServer* server)
 
 int shadow_server_init_fonts(rdpShadowServer* server)
 {
+       char* fontPath;
        rdpShadowFont* font;
 
-       font = shadow_font_new("source_serif_pro_regular_12");
+       fontPath = GetCombinedPath(server->ConfigPath, "shadow/fonts");
+
+       font = shadow_font_new(fontPath, "source_serif_pro_regular_12");
+
+       g_Font = font;
 
-       shadow_font_free(font);
+       free(fontPath);
 
        return 1;
 }
@@ -562,7 +569,7 @@ int shadow_server_init(rdpShadowServer* server)
        if (status < 0)
                return -1;
 
-       //shadow_server_init_fonts(server);
+       shadow_server_init_fonts(server);
 
        server->listener = freerdp_listener_new();