9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/* $Id$ */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/** @file
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VBox XPDM Display driver
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2011-2012 Oracle Corporation
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * available from http://www.virtualbox.org. This file is free software;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * General Public License (GPL) as published by the Free Software
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#include "VBoxDisp.h"
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#include <VBox/RemoteDesktop/VRDEOrders.h>
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync#include <iprt/crc.h>
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync/*
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The client's glyph cache theoretically consists of 10 caches:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * cache index: 0 1 2 3 4 5 6 7 8 9
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * glyph size (max): 0x4 0x4 0x8 0x8 0x10 0x20 0x40 0x80 0x100 0x800
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * glyphs: 0xfe 0xfe 0xfe 0xfe 0xfe 0xfe 0xfe 0xfe 0xfe 0x40
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Glyph size is the size of the 1 BPP glyph bitmap bytes rounded up to 32 bit dword:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * glyph size = (((w + 7) / 8) * h + 3) & ~3
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Following simplifications are used:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * * Cache index 9 is not used, such huge glyphs (~40x40 pixel) are unlikely,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * (especially for raster fonts) so without it all caches contain up to 0xfe
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * characters.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * * Maximum string length is 0xfe, so a string can always
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * be placed in the cache, even if the string consists of
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * all different characters.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The driver always sends glyphs to the host.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The host maintains the glyph cache. Performance issues:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - increased the CPU load to copy glyph info.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * + eliminates the driver side of the cache.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * + lets the host to optimize memory usage.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Therefore, on a textout the driver must send to the host
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The string attributes:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - number of glyphs;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - flags: HORIZONTAL, VERTICAL, CHAR_INC_EQUAL_BM_BASE, ... (1);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - glyph increment for monospaced font (== 0 for not monospaced font) or a flag fMonospaced;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - the bounding box of the string background (prclOpaque or the pstro->rclBkGround);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - the foreground and background colors;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - the mix (two ROP2);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - ... (1).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The glyph information for each glyph in the string:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - unique glyph handle 64 bit for use of crc64;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - the glyph bitmap coordinates on the screen;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - width, height of the glyph;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - the glyph origin in the bitmap (2);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - the 1BPP glyph bitmap;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - whether it is a 'space' character (3);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * - ... (1).
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * Remarks:
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * (1) to be defined;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * (2) might be not necessary;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * (3) it seems to be not necessary to know the codepoint value,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * strings are considered to be a set of bitmaps from
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * the cache space. But reporting that the glyph actually
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * represents a 'space' character might allow some optimizations.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * The VRDEORDERTEXT consists of the string info and glyph infos.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic BOOL vrdpReportGlyph(GLYPHPOS *pGlyphPos, uint8_t **ppu8Ptr, uint8_t *pu8End)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync{
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint32_t cbOrder;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint32_t cbBitmap;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VRDEORDERGLYPH *pOrder = (VRDEORDERGLYPH *)*ppu8Ptr;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync GLYPHBITS *pgb = pGlyphPos->pgdf->pgb;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* BYTE-aligned 1BPP bitmap of the glyph. The array includes padding at the end to DWORD-align. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cbBitmap = (pgb->sizlBitmap.cx + 7) / 8; /* Line size in bytes. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cbBitmap *= pgb->sizlBitmap.cy; /* Size of bitmap. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cbBitmap = (cbBitmap + 3) & ~3; /* DWORD align. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cbOrder = (uint32_t)((uint8_t *)&pOrder->au8Bitmap - (uint8_t *)pOrder);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cbOrder += cbBitmap;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (*ppu8Ptr + cbOrder > pu8End)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return FALSE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->o32NextGlyph = cbOrder;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u64Handle = RTCrc64Start();
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u64Handle = RTCrc64Process(pOrder->u64Handle, pgb->aj, cbBitmap);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u64Handle = RTCrc64Process(pOrder->u64Handle, &pgb->ptlOrigin, sizeof (pgb->ptlOrigin));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u64Handle = RTCrc64Finish(pOrder->u64Handle);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->x = (int16_t)pGlyphPos->ptl.x;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->y = (int16_t)pGlyphPos->ptl.y;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->w = (uint16_t)pgb->sizlBitmap.cx;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->h = (uint16_t)pgb->sizlBitmap.cy;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->xOrigin = (int16_t)pgb->ptlOrigin.x;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->yOrigin = (int16_t)pgb->ptlOrigin.y;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* 1BPP bitmap. Rows are byte aligned. Size is (((w + 7)/8) * h + 3) & ~3. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync memcpy (pOrder->au8Bitmap, pgb->aj, cbBitmap);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync *ppu8Ptr += cbOrder;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return TRUE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync}
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncstatic uint32_t vrdpSizeofTextOrder(ULONG cGlyphs, ULONG cbMaxGlyph)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync{
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint32_t cb = sizeof (VRDEORDERTEXT);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cb += cGlyphs * (sizeof (VRDEORDERGLYPH) + cbMaxGlyph);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return cb;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync}
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsyncBOOL vrdpReportText(PVBOXDISPDEV pDev, VRDPCLIPRECTS *pClipRects, STROBJ *pstro, FONTOBJ *pfo,
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync RECTL *prclOpaque, ULONG ulForeRGB, ULONG ulBackRGB)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync{
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync FONTINFO fi;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint32_t cbOrderMax;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync VRDEORDERTEXT *pOrder;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync BOOL fResult;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t *pu8GlyphPtr;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync uint8_t *pu8GlyphEnd;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOGF(("pDev %p, pClipRects %p, pstro %p, pfo %p, prclOpaque %p, ulForeRGB %x, ulBackRGB %x",
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pDev, pClipRects, pstro, pfo, prclOpaque, ulForeRGB, ulBackRGB));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (pstro->ulCharInc > 0xFF)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return FALSE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
a0ec9d4bb3ccc2a9b3ff673c4506f9deb0e905d9vboxsync /* The driver can get vertical strings with both SO_HORIZONTAL and SO_VERTICAL bits equal to zero. */
a0ec9d4bb3ccc2a9b3ff673c4506f9deb0e905d9vboxsync if ( (pstro->flAccel & SO_HORIZONTAL) == 0
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || (pstro->flAccel & SO_REVERSED) != 0)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Do not support (yet) the vertical and right to left strings.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync * @todo implement and test.
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return FALSE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync memset (&fi, 0, sizeof (fi));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync FONTOBJ_vGetInfo (pfo, sizeof (fi), &fi);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if ( fi.cjMaxGlyph1 == 0
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync || fi.cjMaxGlyph1 > VRDP_TEXT_MAX_GLYPH_SIZE)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* No 1BPP bitmaps or the bitmap is larger than the cache supports. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("fi.cjMaxGlyph1 = %x. Return FALSE", fi.cjMaxGlyph1));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return FALSE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync cbOrderMax = vrdpSizeofTextOrder(pstro->cGlyphs, fi.cjMaxGlyph1);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("pstro->cGlyphs = %d, fi.cjMaxGlyph1 = 0x%x, cbOrderMax = 0x%x.", pstro->cGlyphs, fi.cjMaxGlyph1, cbOrderMax));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder = (VRDEORDERTEXT *)EngAllocMem(0, cbOrderMax, MEM_ALLOC_TAG);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (!pOrder)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("pOrder = %x. Return FALSE", pOrder));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return FALSE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pu8GlyphPtr = (uint8_t *)&pOrder[1]; /* Follows the order header. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pu8GlyphEnd = (uint8_t *)pOrder + cbOrderMax;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->xBkGround = (int16_t)pstro->rclBkGround.left;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->yBkGround = (int16_t)pstro->rclBkGround.top;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->wBkGround = (uint16_t)(pstro->rclBkGround.right - pstro->rclBkGround.left);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->hBkGround = (uint16_t)(pstro->rclBkGround.bottom - pstro->rclBkGround.top);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (prclOpaque)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->xOpaque = (int16_t)prclOpaque->left;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->yOpaque = (int16_t)prclOpaque->top;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->wOpaque = (uint16_t)(prclOpaque->right - prclOpaque->left);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->hOpaque = (uint16_t)(prclOpaque->bottom - prclOpaque->top);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync else
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->xOpaque = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->yOpaque = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->wOpaque = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->hOpaque = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u16MaxGlyph = (uint16_t)fi.cjMaxGlyph1;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u8Glyphs = (uint8_t)pstro->cGlyphs;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u8Flags = (uint8_t)pstro->flAccel;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u8CharInc = (uint8_t)pstro->ulCharInc;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u32FgRGB = ulForeRGB;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->u32BgRGB = ulBackRGB;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("pstro->pgp %p.", pstro->pgp));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync /* Enumerate glyphs. */
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync STROBJ_vEnumStart(pstro);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync fResult = TRUE;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync for (;;)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync ULONG i;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync ULONG cGlyphs = 0;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync GLYPHPOS *pGlyphPos = NULL;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync BOOL fMore = STROBJ_bEnum (pstro, &cGlyphs, &pGlyphPos);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("cGlyphs %d.", cGlyphs));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync for (i = 0; i < cGlyphs; i++)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync fResult = vrdpReportGlyph(&pGlyphPos[i], &pu8GlyphPtr, pu8GlyphEnd);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (!fResult)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync break;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (!fMore || !fResult)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync break;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync LOG(("fResult %d", fResult));
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync if (fResult)
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync {
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync pOrder->cbOrder = (uint32_t)(pu8GlyphPtr - (uint8_t *)pOrder);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync vrdpReportOrderGeneric(pDev, pClipRects, pOrder, pOrder->cbOrder, VRDE_ORDER_TEXT);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync }
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync EngFreeMem(pOrder);
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync return fResult;
9055f61bb57d2a625c6434d55beac7565c3b3c0dvboxsync}