22#include <freerdp/config.h> 
   28#include <winpr/assert.h> 
   29#include <winpr/cast.h> 
   31#include <freerdp/api.h> 
   32#include <freerdp/log.h> 
   33#include <freerdp/freerdp.h> 
   34#include <freerdp/codecs.h> 
   36#include <freerdp/gdi/gdi.h> 
   37#include <freerdp/gdi/dc.h> 
   38#include <freerdp/gdi/pen.h> 
   39#include <freerdp/gdi/shape.h> 
   40#include <freerdp/gdi/region.h> 
   41#include <freerdp/gdi/bitmap.h> 
   48#include "../core/graphics.h" 
   49#include "../core/update.h" 
   50#include "../cache/cache.h" 
   52#define TAG FREERDP_TAG("gdi") 
   61static const rop_table_entry rop3_code_table[] = { { GDI_BLACKNESS, 
"0" },
 
   62                                                 { GDI_DPSoon, 
"DPSoon" },
 
   63                                                 { GDI_DPSona, 
"DPSona" },
 
   65                                                 { GDI_SDPona, 
"SDPona" },
 
   67                                                 { GDI_PDSxnon, 
"PDSxnon" },
 
   68                                                 { GDI_PDSaon, 
"PDSaon" },
 
   69                                                 { GDI_SDPnaa, 
"SDPnaa" },
 
   70                                                 { GDI_PDSxon, 
"PDSxon" },
 
   72                                                 { GDI_PSDnaon, 
"PSDnaon" },
 
   74                                                 { GDI_PDSnaon, 
"PDSnaon" },
 
   75                                                 { GDI_PDSonon, 
"PDSonon" },
 
   77                                                 { GDI_PDSona, 
"PDSona" },
 
   78                                                 { GDI_NOTSRCERASE, 
"DSon" },
 
   79                                                 { GDI_SDPxnon, 
"SDPxnon" },
 
   80                                                 { GDI_SDPaon, 
"SDPaon" },
 
   81                                                 { GDI_DPSxnon, 
"DPSxnon" },
 
   82                                                 { GDI_DPSaon, 
"DPSaon" },
 
   83                                                 { GDI_PSDPSanaxx, 
"PSDPSanaxx" },
 
   84                                                 { GDI_SSPxDSxaxn, 
"SSPxDSxaxn" },
 
   85                                                 { GDI_SPxPDxa, 
"SPxPDxa" },
 
   86                                                 { GDI_SDPSanaxn, 
"SDPSanaxn" },
 
   87                                                 { GDI_PDSPaox, 
"PDSPaox" },
 
   88                                                 { GDI_SDPSxaxn, 
"SDPSxaxn" },
 
   89                                                 { GDI_PSDPaox, 
"PSDPaox" },
 
   90                                                 { GDI_DSPDxaxn, 
"DSPDxaxn" },
 
   91                                                 { GDI_PDSox, 
"PDSox" },
 
   92                                                 { GDI_PDSoan, 
"PDSoan" },
 
   93                                                 { GDI_DPSnaa, 
"DPSnaa" },
 
   94                                                 { GDI_SDPxon, 
"SDPxon" },
 
   96                                                 { GDI_SPDnaon, 
"SPDnaon" },
 
   97                                                 { GDI_SPxDSxa, 
"SPxDSxa" },
 
   98                                                 { GDI_PDSPanaxn, 
"PDSPanaxn" },
 
   99                                                 { GDI_SDPSaox, 
"SDPSaox" },
 
  100                                                 { GDI_SDPSxnox, 
"SDPSxnox" },
 
  101                                                 { GDI_DPSxa, 
"DPSxa" },
 
  102                                                 { GDI_PSDPSaoxxn, 
"PSDPSaoxxn" },
 
  103                                                 { GDI_DPSana, 
"DPSana" },
 
  104                                                 { GDI_SSPxPDxaxn, 
"SSPxPDxaxn" },
 
  105                                                 { GDI_SPDSoax, 
"SPDSoax" },
 
  106                                                 { GDI_PSDnox, 
"PSDnox" },
 
  107                                                 { GDI_PSDPxox, 
"PSDPxox" },
 
  108                                                 { GDI_PSDnoan, 
"PSDnoan" },
 
  109                                                 { GDI_PSna, 
"PSna" },
 
  110                                                 { GDI_SDPnaon, 
"SDPnaon" },
 
  111                                                 { GDI_SDPSoox, 
"SDPSoox" },
 
  112                                                 { GDI_NOTSRCCOPY, 
"Sn" },
 
  113                                                 { GDI_SPDSaox, 
"SPDSaox" },
 
  114                                                 { GDI_SPDSxnox, 
"SPDSxnox" },
 
  115                                                 { GDI_SDPox, 
"SDPox" },
 
  116                                                 { GDI_SDPoan, 
"SDPoan" },
 
  117                                                 { GDI_PSDPoax, 
"PSDPoax" },
 
  118                                                 { GDI_SPDnox, 
"SPDnox" },
 
  119                                                 { GDI_SPDSxox, 
"SPDSxox" },
 
  120                                                 { GDI_SPDnoan, 
"SPDnoan" },
 
  122                                                 { GDI_SPDSonox, 
"SPDSonox" },
 
  123                                                 { GDI_SPDSnaox, 
"SPDSnaox" },
 
  124                                                 { GDI_PSan, 
"PSan" },
 
  125                                                 { GDI_PSDnaa, 
"PSDnaa" },
 
  126                                                 { GDI_DPSxon, 
"DPSxon" },
 
  127                                                 { GDI_SDxPDxa, 
"SDxPDxa" },
 
  128                                                 { GDI_SPDSanaxn, 
"SPDSanaxn" },
 
  129                                                 { GDI_SRCERASE, 
"SDna" },
 
  130                                                 { GDI_DPSnaon, 
"DPSnaon" },
 
  131                                                 { GDI_DSPDaox, 
"DSPDaox" },
 
  132                                                 { GDI_PSDPxaxn, 
"PSDPxaxn" },
 
  133                                                 { GDI_SDPxa, 
"SDPxa" },
 
  134                                                 { GDI_PDSPDaoxxn, 
"PDSPDaoxxn" },
 
  135                                                 { GDI_DPSDoax, 
"DPSDoax" },
 
  136                                                 { GDI_PDSnox, 
"PDSnox" },
 
  137                                                 { GDI_SDPana, 
"SDPana" },
 
  138                                                 { GDI_SSPxDSxoxn, 
"SSPxDSxoxn" },
 
  139                                                 { GDI_PDSPxox, 
"PDSPxox" },
 
  140                                                 { GDI_PDSnoan, 
"PDSnoan" },
 
  141                                                 { GDI_PDna, 
"PDna" },
 
  142                                                 { GDI_DSPnaon, 
"DSPnaon" },
 
  143                                                 { GDI_DPSDaox, 
"DPSDaox" },
 
  144                                                 { GDI_SPDSxaxn, 
"SPDSxaxn" },
 
  145                                                 { GDI_DPSonon, 
"DPSonon" },
 
  146                                                 { GDI_DSTINVERT, 
"Dn" },
 
  147                                                 { GDI_DPSox, 
"DPSox" },
 
  148                                                 { GDI_DPSoan, 
"DPSoan" },
 
  149                                                 { GDI_PDSPoax, 
"PDSPoax" },
 
  150                                                 { GDI_DPSnox, 
"DPSnox" },
 
  151                                                 { GDI_PATINVERT, 
"DPx" },
 
  152                                                 { GDI_DPSDonox, 
"DPSDonox" },
 
  153                                                 { GDI_DPSDxox, 
"DPSDxox" },
 
  154                                                 { GDI_DPSnoan, 
"DPSnoan" },
 
  155                                                 { GDI_DPSDnaox, 
"DPSDnaox" },
 
  156                                                 { GDI_DPan, 
"DPan" },
 
  157                                                 { GDI_PDSxa, 
"PDSxa" },
 
  158                                                 { GDI_DSPDSaoxxn, 
"DSPDSaoxxn" },
 
  159                                                 { GDI_DSPDoax, 
"DSPDoax" },
 
  160                                                 { GDI_SDPnox, 
"SDPnox" },
 
  161                                                 { GDI_SDPSoax, 
"SDPSoax" },
 
  162                                                 { GDI_DSPnox, 
"DSPnox" },
 
  163                                                 { GDI_SRCINVERT, 
"DSx" },
 
  164                                                 { GDI_SDPSonox, 
"SDPSonox" },
 
  165                                                 { GDI_DSPDSonoxxn, 
"DSPDSonoxxn" },
 
  166                                                 { GDI_PDSxxn, 
"PDSxxn" },
 
  167                                                 { GDI_DPSax, 
"DPSax" },
 
  168                                                 { GDI_PSDPSoaxxn, 
"PSDPSoaxxn" },
 
  169                                                 { GDI_SDPax, 
"SDPax" },
 
  170                                                 { GDI_PDSPDoaxxn, 
"PDSPDoaxxn" },
 
  171                                                 { GDI_SDPSnoax, 
"SDPSnoax" },
 
  172                                                 { GDI_PDSxnan, 
"PDSxnan" },
 
  173                                                 { GDI_PDSana, 
"PDSana" },
 
  174                                                 { GDI_SSDxPDxaxn, 
"SSDxPDxaxn" },
 
  175                                                 { GDI_SDPSxox, 
"SDPSxox" },
 
  176                                                 { GDI_SDPnoan, 
"SDPnoan" },
 
  177                                                 { GDI_DSPDxox, 
"DSPDxox" },
 
  178                                                 { GDI_DSPnoan, 
"DSPnoan" },
 
  179                                                 { GDI_SDPSnaox, 
"SDPSnaox" },
 
  180                                                 { GDI_DSan, 
"DSan" },
 
  181                                                 { GDI_PDSax, 
"PDSax" },
 
  182                                                 { GDI_DSPDSoaxxn, 
"DSPDSoaxxn" },
 
  183                                                 { GDI_DPSDnoax, 
"DPSDnoax" },
 
  184                                                 { GDI_SDPxnan, 
"SDPxnan" },
 
  185                                                 { GDI_SPDSnoax, 
"SPDSnoax" },
 
  186                                                 { GDI_DPSxnan, 
"DPSxnan" },
 
  187                                                 { GDI_SPxDSxo, 
"SPxDSxo" },
 
  188                                                 { GDI_DPSaan, 
"DPSaan" },
 
  189                                                 { GDI_DPSaa, 
"DPSaa" },
 
  190                                                 { GDI_SPxDSxon, 
"SPxDSxon" },
 
  191                                                 { GDI_DPSxna, 
"DPSxna" },
 
  192                                                 { GDI_SPDSnoaxn, 
"SPDSnoaxn" },
 
  193                                                 { GDI_SDPxna, 
"SDPxna" },
 
  194                                                 { GDI_PDSPnoaxn, 
"PDSPnoaxn" },
 
  195                                                 { GDI_DSPDSoaxx, 
"DSPDSoaxx" },
 
  196                                                 { GDI_PDSaxn, 
"PDSaxn" },
 
  197                                                 { GDI_SRCAND, 
"DSa" },
 
  198                                                 { GDI_SDPSnaoxn, 
"SDPSnaoxn" },
 
  199                                                 { GDI_DSPnoa, 
"DSPnoa" },
 
  200                                                 { GDI_DSPDxoxn, 
"DSPDxoxn" },
 
  201                                                 { GDI_SDPnoa, 
"SDPnoa" },
 
  202                                                 { GDI_SDPSxoxn, 
"SDPSxoxn" },
 
  203                                                 { GDI_SSDxPDxax, 
"SSDxPDxax" },
 
  204                                                 { GDI_PDSanan, 
"PDSanan" },
 
  205                                                 { GDI_PDSxna, 
"PDSxna" },
 
  206                                                 { GDI_SDPSnoaxn, 
"SDPSnoaxn" },
 
  207                                                 { GDI_DPSDPoaxx, 
"DPSDPoaxx" },
 
  208                                                 { GDI_SPDaxn, 
"SPDaxn" },
 
  209                                                 { GDI_PSDPSoaxx, 
"PSDPSoaxx" },
 
  210                                                 { GDI_DPSaxn, 
"DPSaxn" },
 
  211                                                 { GDI_DPSxx, 
"DPSxx" },
 
  212                                                 { GDI_PSDPSonoxx, 
"PSDPSonoxx" },
 
  213                                                 { GDI_SDPSonoxn, 
"SDPSonoxn" },
 
  214                                                 { GDI_DSxn, 
"DSxn" },
 
  215                                                 { GDI_DPSnax, 
"DPSnax" },
 
  216                                                 { GDI_SDPSoaxn, 
"SDPSoaxn" },
 
  217                                                 { GDI_SPDnax, 
"SPDnax" },
 
  218                                                 { GDI_DSPDoaxn, 
"DSPDoaxn" },
 
  219                                                 { GDI_DSPDSaoxx, 
"DSPDSaoxx" },
 
  220                                                 { GDI_PDSxan, 
"PDSxan" },
 
  222                                                 { GDI_PDSPnaoxn, 
"PDSPnaoxn" },
 
  223                                                 { GDI_DPSnoa, 
"DPSnoa" },
 
  224                                                 { GDI_DPSDxoxn, 
"DPSDxoxn" },
 
  225                                                 { GDI_PDSPonoxn, 
"PDSPonoxn" },
 
  226                                                 { GDI_PDxn, 
"PDxn" },
 
  227                                                 { GDI_DSPnax, 
"DSPnax" },
 
  228                                                 { GDI_PDSPoaxn, 
"PDSPoaxn" },
 
  229                                                 { GDI_DPSoa, 
"DPSoa" },
 
  230                                                 { GDI_DPSoxn, 
"DPSoxn" },
 
  231                                                 { GDI_DSTCOPY, 
"D" },
 
  232                                                 { GDI_DPSono, 
"DPSono" },
 
  233                                                 { GDI_SPDSxax, 
"SPDSxax" },
 
  234                                                 { GDI_DPSDaoxn, 
"DPSDaoxn" },
 
  235                                                 { GDI_DSPnao, 
"DSPnao" },
 
  236                                                 { GDI_DPno, 
"DPno" },
 
  237                                                 { GDI_PDSnoa, 
"PDSnoa" },
 
  238                                                 { GDI_PDSPxoxn, 
"PDSPxoxn" },
 
  239                                                 { GDI_SSPxDSxox, 
"SSPxDSxox" },
 
  240                                                 { GDI_SDPanan, 
"SDPanan" },
 
  241                                                 { GDI_PSDnax, 
"PSDnax" },
 
  242                                                 { GDI_DPSDoaxn, 
"DPSDoaxn" },
 
  243                                                 { GDI_DPSDPaoxx, 
"DPSDPaoxx" },
 
  244                                                 { GDI_SDPxan, 
"SDPxan" },
 
  245                                                 { GDI_PSDPxax, 
"PSDPxax" },
 
  246                                                 { GDI_DSPDaoxn, 
"DSPDaoxn" },
 
  247                                                 { GDI_DPSnao, 
"DPSnao" },
 
  248                                                 { GDI_MERGEPAINT, 
"DSno" },
 
  249                                                 { GDI_SPDSanax, 
"SPDSanax" },
 
  250                                                 { GDI_SDxPDxan, 
"SDxPDxan" },
 
  251                                                 { GDI_DPSxo, 
"DPSxo" },
 
  252                                                 { GDI_DPSano, 
"DPSano" },
 
  253                                                 { GDI_MERGECOPY, 
"PSa" },
 
  254                                                 { GDI_SPDSnaoxn, 
"SPDSnaoxn" },
 
  255                                                 { GDI_SPDSonoxn, 
"SPDSonoxn" },
 
  256                                                 { GDI_PSxn, 
"PSxn" },
 
  257                                                 { GDI_SPDnoa, 
"SPDnoa" },
 
  258                                                 { GDI_SPDSxoxn, 
"SPDSxoxn" },
 
  259                                                 { GDI_SDPnax, 
"SDPnax" },
 
  260                                                 { GDI_PSDPoaxn, 
"PSDPoaxn" },
 
  261                                                 { GDI_SDPoa, 
"SDPoa" },
 
  262                                                 { GDI_SPDoxn, 
"SPDoxn" },
 
  263                                                 { GDI_DPSDxax, 
"DPSDxax" },
 
  264                                                 { GDI_SPDSaoxn, 
"SPDSaoxn" },
 
  265                                                 { GDI_SRCCOPY, 
"S" },
 
  266                                                 { GDI_SDPono, 
"SDPono" },
 
  267                                                 { GDI_SDPnao, 
"SDPnao" },
 
  268                                                 { GDI_SPno, 
"SPno" },
 
  269                                                 { GDI_PSDnoa, 
"PSDnoa" },
 
  270                                                 { GDI_PSDPxoxn, 
"PSDPxoxn" },
 
  271                                                 { GDI_PDSnax, 
"PDSnax" },
 
  272                                                 { GDI_SPDSoaxn, 
"SPDSoaxn" },
 
  273                                                 { GDI_SSPxPDxax, 
"SSPxPDxax" },
 
  274                                                 { GDI_DPSanan, 
"DPSanan" },
 
  275                                                 { GDI_PSDPSaoxx, 
"PSDPSaoxx" },
 
  276                                                 { GDI_DPSxan, 
"DPSxan" },
 
  277                                                 { GDI_PDSPxax, 
"PDSPxax" },
 
  278                                                 { GDI_SDPSaoxn, 
"SDPSaoxn" },
 
  279                                                 { GDI_DPSDanax, 
"DPSDanax" },
 
  280                                                 { GDI_SPxDSxan, 
"SPxDSxan" },
 
  281                                                 { GDI_SPDnao, 
"SPDnao" },
 
  282                                                 { GDI_SDno, 
"SDno" },
 
  283                                                 { GDI_SDPxo, 
"SDPxo" },
 
  284                                                 { GDI_SDPano, 
"SDPano" },
 
  285                                                 { GDI_PDSoa, 
"PDSoa" },
 
  286                                                 { GDI_PDSoxn, 
"PDSoxn" },
 
  287                                                 { GDI_DSPDxax, 
"DSPDxax" },
 
  288                                                 { GDI_PSDPaoxn, 
"PSDPaoxn" },
 
  289                                                 { GDI_SDPSxax, 
"SDPSxax" },
 
  290                                                 { GDI_PDSPaoxn, 
"PDSPaoxn" },
 
  291                                                 { GDI_SDPSanax, 
"SDPSanax" },
 
  292                                                 { GDI_SPxPDxan, 
"SPxPDxan" },
 
  293                                                 { GDI_SSPxDSxax, 
"SSPxDSxax" },
 
  294                                                 { GDI_DSPDSanaxxn, 
"DSPDSanaxxn" },
 
  295                                                 { GDI_DPSao, 
"DPSao" },
 
  296                                                 { GDI_DPSxno, 
"DPSxno" },
 
  297                                                 { GDI_SDPao, 
"SDPao" },
 
  298                                                 { GDI_SDPxno, 
"SDPxno" },
 
  299                                                 { GDI_SRCPAINT, 
"DSo" },
 
  300                                                 { GDI_SDPnoo, 
"SDPnoo" },
 
  301                                                 { GDI_PATCOPY, 
"P" },
 
  302                                                 { GDI_PDSono, 
"PDSono" },
 
  303                                                 { GDI_PDSnao, 
"PDSnao" },
 
  304                                                 { GDI_PSno, 
"PSno" },
 
  305                                                 { GDI_PSDnao, 
"PSDnao" },
 
  306                                                 { GDI_PDno, 
"PDno" },
 
  307                                                 { GDI_PDSxo, 
"PDSxo" },
 
  308                                                 { GDI_PDSano, 
"PDSano" },
 
  309                                                 { GDI_PDSao, 
"PDSao" },
 
  310                                                 { GDI_PDSxno, 
"PDSxno" },
 
  312                                                 { GDI_PATPAINT, 
"DPSnoo" },
 
  314                                                 { GDI_PSDnoo, 
"PSDnoo" },
 
  315                                                 { GDI_DPSoo, 
"DPSoo" },
 
  316                                                 { GDI_WHITENESS, 
"1" } };
 
  319static const BYTE GDI_BS_HATCHED_PATTERNS[] = {
 
  320  0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 
 
  321  0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 
 
  322  0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F, 
 
  323  0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE, 
 
  324  0xF7, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0xF7, 0xF7, 
 
  325  0x7E, 0xBD, 0xDB, 0xE7, 0xE7, 0xDB, 0xBD, 0x7E  
 
  328#define gdi_rop3_code_checked(code) gdi_rop3_code_checked_int((code), __FILE__, __func__, __LINE__) 
  329static inline DWORD gdi_rop3_code_checked_int(UINT32 code, WINPR_ATTR_UNUSED 
const char* file,
 
  330                                              WINPR_ATTR_UNUSED 
const char* fkt,
 
  331                                              WINPR_ATTR_UNUSED 
size_t line)
 
  333  WINPR_ASSERT_AT(code <= UINT8_MAX, file, fkt, line);
 
  334  return gdi_rop3_code((UINT8)code);
 
  337BOOL gdi_decode_color(rdpGdi* gdi, UINT32 srcColor, UINT32* color, UINT32* format)
 
  339  UINT32 SrcFormat = 0;
 
  341  if (!gdi || !color || !gdi->context || !gdi->context->settings)
 
  344  const UINT32 ColorDepth =
 
  351      SrcFormat = PIXEL_FORMAT_BGR24;
 
  355      SrcFormat = PIXEL_FORMAT_RGB16;
 
  359      SrcFormat = PIXEL_FORMAT_RGB15;
 
  363      SrcFormat = PIXEL_FORMAT_RGB8;
 
  371    *format = gdi->dstFormat;
 
  373  *color = FreeRDPConvertColor(srcColor, SrcFormat, gdi->dstFormat, &gdi->palette);
 
  378DWORD gdi_rop3_code(BYTE code)
 
  380  return rop3_code_table[code].code;
 
  383const char* gdi_rop3_code_string(BYTE code)
 
  385  return rop3_code_table[code].name;
 
  388const char* gdi_rop3_string(DWORD rop)
 
  390  const size_t count = 
sizeof(rop3_code_table) / 
sizeof(rop3_code_table[0]);
 
  392  for (
size_t x = 0; x < count; x++)
 
  394    if (rop3_code_table[x].code == rop)
 
  395      return rop3_code_table[x].name;
 
  401UINT32 gdi_get_pixel_format(UINT32 bitsPerPixel)
 
  405  switch (bitsPerPixel)
 
  408      format = PIXEL_FORMAT_BGRA32;
 
  412      format = PIXEL_FORMAT_BGR24;
 
  416      format = PIXEL_FORMAT_RGB16;
 
  420      format = PIXEL_FORMAT_RGB15;
 
  424      format = PIXEL_FORMAT_RGB8;
 
  428      WLog_ERR(TAG, 
"Unsupported color depth %" PRIu32, bitsPerPixel);
 
  436gdiBitmap* gdi_bitmap_new_ex(rdpGdi* gdi, 
int width, 
int height, 
int bpp, BYTE* data)
 
  438  gdiBitmap* bitmap = NULL;
 
  439  bitmap = (gdiBitmap*)calloc(1, 
sizeof(gdiBitmap));
 
  444  if (!(bitmap->hdc = gdi_CreateCompatibleDC(gdi->hdc)))
 
  447  WLog_Print(gdi->log, WLOG_DEBUG, 
"gdi_bitmap_new: width:%d height:%d bpp:%d", width, height,
 
  452        gdi_CreateCompatibleBitmap(gdi->hdc, WINPR_ASSERTING_INT_CAST(uint32_t, width),
 
  453                                   WINPR_ASSERTING_INT_CAST(uint32_t, height));
 
  455    bitmap->bitmap = gdi_create_bitmap(gdi, WINPR_ASSERTING_INT_CAST(uint32_t, width),
 
  456                                       WINPR_ASSERTING_INT_CAST(uint32_t, height),
 
  457                                       WINPR_ASSERTING_INT_CAST(uint32_t, bpp), data);
 
  460    goto fail_bitmap_bitmap;
 
  462  gdi_SelectObject(bitmap->hdc, (
HGDIOBJECT)bitmap->bitmap);
 
  463  bitmap->org_bitmap = NULL;
 
  466  gdi_DeleteDC(bitmap->hdc);
 
  473void gdi_bitmap_free_ex(gdiBitmap* bitmap)
 
  477    gdi_SelectObject(bitmap->hdc, (
HGDIOBJECT)bitmap->org_bitmap);
 
  479    gdi_DeleteDC(bitmap->hdc);
 
  484BOOL gdi_bitmap_update(rdpContext* context, 
const BITMAP_UPDATE* bitmapUpdate)
 
  486  if (!context || !bitmapUpdate || !context->gdi || !context->codecs)
 
  489             "Invalid arguments: context=%p, bitmapUpdate=%p, context->gdi=%p, " 
  490             "context->codecs=%p",
 
  491             context, bitmapUpdate, context ? context->gdi : NULL,
 
  492             context ? context->codecs : NULL);
 
  496  for (UINT32 index = 0; index < bitmapUpdate->number; index++)
 
  499    const BITMAP_DATA* bitmap = &(bitmapUpdate->rectangles[index]);
 
  500    rdpBitmap* bmp = Bitmap_Alloc(context);
 
  505    if (!Bitmap_SetDimensions(bmp, WINPR_ASSERTING_INT_CAST(UINT16, bitmap->width),
 
  506                              WINPR_ASSERTING_INT_CAST(UINT16, bitmap->height)))
 
  509    if (!Bitmap_SetRectangle(bmp, WINPR_ASSERTING_INT_CAST(UINT16, bitmap->destLeft),
 
  510                             WINPR_ASSERTING_INT_CAST(UINT16, bitmap->destTop),
 
  511                             WINPR_ASSERTING_INT_CAST(UINT16, bitmap->destRight),
 
  512                             WINPR_ASSERTING_INT_CAST(UINT16, bitmap->destBottom)))
 
  515    if (!bmp->Decompress(context, bmp, bitmap->bitmapDataStream, bitmap->width, bitmap->height,
 
  516                         bitmap->bitsPerPixel, bitmap->bitmapLength, bitmap->compressed,
 
  520    if (!bmp->New(context, bmp))
 
  523    if (!bmp->Paint(context, bmp))
 
  528    Bitmap_Free(context, bmp);
 
  536static BOOL gdi_palette_update(rdpContext* context, 
const PALETTE_UPDATE* palette)
 
  540  if (!context || !palette)
 
  544  gdi->palette.format = gdi->dstFormat;
 
  546  for (UINT32 index = 0; index < palette->number; index++)
 
  549    gdi->palette.palette[index] =
 
  550        FreeRDPGetColor(gdi->dstFormat, pe->red, pe->green, pe->blue, 0xFF);
 
  556static BOOL gdi_set_bounds(rdpContext* context, 
const rdpBounds* bounds)
 
  567    gdi_SetClipRgn(gdi->drawing->hdc, bounds->left, bounds->top,
 
  568                   bounds->right - bounds->left + 1, bounds->bottom - bounds->top + 1);
 
  571    gdi_SetNullClipRgn(gdi->drawing->hdc);
 
  576static BOOL gdi_dstblt(rdpContext* context, 
const DSTBLT_ORDER* dstblt)
 
  580  if (!context || !dstblt)
 
  584  return gdi_BitBlt(gdi->drawing->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth,
 
  585                    dstblt->nHeight, NULL, 0, 0, gdi_rop3_code_checked(dstblt->bRop),
 
  589static BOOL gdi_patblt(rdpContext* context, 
PATBLT_ORDER* patblt)
 
  591  const rdpBrush* brush = &patblt->brush;
 
  592  UINT32 foreColor = 0;
 
  593  UINT32 backColor = 0;
 
  594  UINT32 originalColor = 0;
 
  597  rdpGdi* gdi = context->gdi;
 
  599  const DWORD rop = gdi_rop3_code_checked(patblt->bRop);
 
  602  BYTE data[8 * 8 * 4];
 
  605  if (!gdi_decode_color(gdi, patblt->foreColor, &foreColor, NULL))
 
  608  if (!gdi_decode_color(gdi, patblt->backColor, &backColor, NULL))
 
  611  originalColor = gdi_SetTextColor(gdi->drawing->hdc, foreColor);
 
  612  originalBrush = gdi->drawing->hdc->brush;
 
  614  switch (brush->style)
 
  617      hbrush = gdi_CreateSolidBrush(foreColor);
 
  622      const BYTE* hatched = NULL;
 
  623      hatched = GDI_BS_HATCHED_PATTERNS + (8ULL * brush->hatch);
 
  625      if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8,
 
  626                                              hatched, backColor, foreColor, &gdi->palette))
 
  629      hBmp = gdi_CreateBitmapEx(8, 8, gdi->drawing->hdc->format, 0, data, NULL);
 
  634      hbrush = gdi_CreateHatchBrush(hBmp);
 
  640      UINT32 brushFormat = 0;
 
  644        UINT32 bpp = brush->bpp;
 
  650        brushFormat = gdi_get_pixel_format(bpp);
 
  652        if (!freerdp_image_copy_no_overlap(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8,
 
  653                                           brush->data, brushFormat, 0, 0, 0, &gdi->palette,
 
  659        if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0, 0, 8,
 
  660                                                8, brush->data, backColor, foreColor,
 
  665      hBmp = gdi_CreateBitmapEx(8, 8, gdi->drawing->hdc->format, 0, data, NULL);
 
  670      hbrush = gdi_CreatePatternBrush(hBmp);
 
  675      WLog_ERR(TAG, 
"unimplemented brush style:%" PRIu32 
"", brush->style);
 
  681    hbrush->nXOrg = WINPR_ASSERTING_INT_CAST(int32_t, brush->x);
 
  682    hbrush->nYOrg = WINPR_ASSERTING_INT_CAST(int32_t, brush->y);
 
  683    gdi->drawing->hdc->brush = hbrush;
 
  684    ret = gdi_BitBlt(gdi->drawing->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth,
 
  685                     patblt->nHeight, gdi->primary->hdc, nXSrc, nYSrc, rop, &gdi->palette);
 
  691  gdi->drawing->hdc->brush = originalBrush;
 
  692  gdi_SetTextColor(gdi->drawing->hdc, originalColor);
 
  696static BOOL gdi_scrblt(rdpContext* context, 
const SCRBLT_ORDER* scrblt)
 
  700  if (!context || !context->gdi)
 
  704  return gdi_BitBlt(gdi->drawing->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth,
 
  705                    scrblt->nHeight, gdi->primary->hdc, scrblt->nXSrc, scrblt->nYSrc,
 
  706                    gdi_rop3_code_checked(scrblt->bRop), &gdi->palette);
 
  709static BOOL gdi_opaque_rect(rdpContext* context, 
const OPAQUE_RECT_ORDER* opaque_rect)
 
  713  UINT32 brush_color = 0;
 
  714  rdpGdi* gdi = context->gdi;
 
  716  INT32 x = opaque_rect->nLeftRect;
 
  717  INT32 y = opaque_rect->nTopRect;
 
  718  INT32 w = opaque_rect->nWidth;
 
  719  INT32 h = opaque_rect->nHeight;
 
  720  gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
 
  721  gdi_CRgnToRect(x, y, w, h, &rect);
 
  723  if (!gdi_decode_color(gdi, opaque_rect->color, &brush_color, NULL))
 
  726  if (!(hBrush = gdi_CreateSolidBrush(brush_color)))
 
  729  ret = gdi_FillRect(gdi->drawing->hdc, &rect, hBrush);
 
  734static BOOL gdi_multi_opaque_rect(rdpContext* context,
 
  739  UINT32 brush_color = 0;
 
  740  rdpGdi* gdi = context->gdi;
 
  743  if (!gdi_decode_color(gdi, multi_opaque_rect->color, &brush_color, NULL))
 
  746  hBrush = gdi_CreateSolidBrush(brush_color);
 
  751  for (UINT32 i = 0; i < multi_opaque_rect->numRectangles; i++)
 
  753    const DELTA_RECT* rectangle = &multi_opaque_rect->rectangles[i];
 
  754    INT32 x = rectangle->left;
 
  755    INT32 y = rectangle->top;
 
  756    INT32 w = rectangle->width;
 
  757    INT32 h = rectangle->height;
 
  758    gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
 
  759    gdi_CRgnToRect(x, y, w, h, &rect);
 
  760    ret = gdi_FillRect(gdi->drawing->hdc, &rect, hBrush);
 
  770static BOOL gdi_line_to(rdpContext* context, 
const LINE_TO_ORDER* lineTo)
 
  774  rdpGdi* gdi = context->gdi;
 
  775  INT32 xStart = lineTo->nXStart;
 
  776  INT32 yStart = lineTo->nYStart;
 
  777  INT32 xEnd = lineTo->nXEnd;
 
  778  INT32 yEnd = lineTo->nYEnd;
 
  781  gdi_ClipCoords(gdi->drawing->hdc, &xStart, &yStart, &w, &h, NULL, NULL);
 
  782  gdi_ClipCoords(gdi->drawing->hdc, &xEnd, &yEnd, &w, &h, NULL, NULL);
 
  784  if (!gdi_decode_color(gdi, lineTo->penColor, &color, NULL))
 
  787  if (!(hPen = gdi_CreatePen(lineTo->penStyle, lineTo->penWidth, color, gdi->drawing->hdc->format,
 
  791  gdi_SelectObject(gdi->drawing->hdc, (
HGDIOBJECT)hPen);
 
  792  gdi_SetROP2(gdi->drawing->hdc, WINPR_ASSERTING_INT_CAST(int32_t, lineTo->bRop2));
 
  793  gdi_MoveToEx(gdi->drawing->hdc, lineTo->nXStart, lineTo->nYStart, NULL);
 
  794  gdi_LineTo(gdi->drawing->hdc, lineTo->nXEnd, lineTo->nYEnd);
 
  799static BOOL gdi_polyline(rdpContext* context, 
const POLYLINE_ORDER* polyline)
 
  806  rdpGdi* gdi = context->gdi;
 
  810  if (!gdi_decode_color(gdi, polyline->penColor, &color, NULL))
 
  813  if (!(hPen = gdi_CreatePen(GDI_PS_SOLID, 1, color, gdi->drawing->hdc->format, &gdi->palette)))
 
  816  gdi_SelectObject(gdi->drawing->hdc, (
HGDIOBJECT)hPen);
 
  817  gdi_SetROP2(gdi->drawing->hdc, WINPR_ASSERTING_INT_CAST(int32_t, polyline->bRop2));
 
  818  x = polyline->xStart;
 
  819  y = polyline->yStart;
 
  820  gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
 
  821  gdi_MoveToEx(gdi->drawing->hdc, x, y, NULL);
 
  822  points = polyline->points;
 
  824  for (UINT32 i = 0; i < polyline->numDeltaEntries; i++)
 
  828    gdi_ClipCoords(gdi->drawing->hdc, &x, &y, &w, &h, NULL, NULL);
 
  829    gdi_LineTo(gdi->drawing->hdc, x, y);
 
  830    gdi_MoveToEx(gdi->drawing->hdc, x, y, NULL);
 
  837static BOOL gdi_memblt(rdpContext* context, 
MEMBLT_ORDER* memblt)
 
  839  gdiBitmap* bitmap = NULL;
 
  842  if (!context || !memblt || !context->gdi || !memblt->bitmap)
 
  845  bitmap = (gdiBitmap*)memblt->bitmap;
 
  847  return gdi_BitBlt(gdi->drawing->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth,
 
  848                    memblt->nHeight, bitmap->hdc, memblt->nXSrc, memblt->nYSrc,
 
  849                    gdi_rop3_code_checked(memblt->bRop), &gdi->palette);
 
  852static BOOL gdi_mem3blt(rdpContext* context, 
MEM3BLT_ORDER* mem3blt)
 
  855  rdpGdi* gdi = context->gdi;
 
  857  const rdpBrush* brush = &mem3blt->brush;
 
  858  gdiBitmap* bitmap = (gdiBitmap*)mem3blt->bitmap;
 
  859  UINT32 foreColor = 0;
 
  860  UINT32 backColor = 0;
 
  861  UINT32 originalColor = 0;
 
  863  if (!gdi_decode_color(gdi, mem3blt->foreColor, &foreColor, NULL))
 
  866  if (!gdi_decode_color(gdi, mem3blt->backColor, &backColor, NULL))
 
  869  originalColor = gdi_SetTextColor(gdi->drawing->hdc, foreColor);
 
  871  switch (brush->style)
 
  874      originalBrush = gdi->drawing->hdc->brush;
 
  875      gdi->drawing->hdc->brush = gdi_CreateSolidBrush(foreColor);
 
  877      if (!gdi->drawing->hdc->brush)
 
  883      ret = gdi_BitBlt(gdi->drawing->hdc, mem3blt->nLeftRect, mem3blt->nTopRect,
 
  884                       mem3blt->nWidth, mem3blt->nHeight, bitmap->hdc, mem3blt->nXSrc,
 
  885                       mem3blt->nYSrc, gdi_rop3_code_checked(mem3blt->bRop), &gdi->palette);
 
  886      gdi_DeleteObject((
HGDIOBJECT)gdi->drawing->hdc->brush);
 
  887      gdi->drawing->hdc->brush = originalBrush;
 
  893      UINT32 brushFormat = 0;
 
  894      BYTE* data = (BYTE*)winpr_aligned_malloc(
 
  895          8ULL * 8ULL * FreeRDPGetBytesPerPixel(gdi->drawing->hdc->format), 16);
 
  905        UINT32 bpp = brush->bpp;
 
  907        const UINT32 ColorDepth =
 
  909        if ((bpp == 16) && (ColorDepth == 15))
 
  912        brushFormat = gdi_get_pixel_format(bpp);
 
  914        if (!freerdp_image_copy_no_overlap(data, gdi->drawing->hdc->format, 0, 0, 0, 8, 8,
 
  915                                           brush->data, brushFormat, 0, 0, 0, &gdi->palette,
 
  919          winpr_aligned_free(data);
 
  925        if (!freerdp_image_copy_from_monochrome(data, gdi->drawing->hdc->format, 0, 0, 0, 8,
 
  926                                                8, brush->data, backColor, foreColor,
 
  930          winpr_aligned_free(data);
 
  935      hBmp = gdi_CreateBitmap(8, 8, gdi->drawing->hdc->format, data);
 
  940        winpr_aligned_free(data);
 
  944      originalBrush = gdi->drawing->hdc->brush;
 
  945      gdi->drawing->hdc->brush = gdi_CreatePatternBrush(hBmp);
 
  947      if (!gdi->drawing->hdc->brush)
 
  953      gdi->drawing->hdc->brush->nXOrg = WINPR_ASSERTING_INT_CAST(int32_t, brush->x);
 
  954      gdi->drawing->hdc->brush->nYOrg = WINPR_ASSERTING_INT_CAST(int32_t, brush->y);
 
  955      ret = gdi_BitBlt(gdi->drawing->hdc, mem3blt->nLeftRect, mem3blt->nTopRect,
 
  956                       mem3blt->nWidth, mem3blt->nHeight, bitmap->hdc, mem3blt->nXSrc,
 
  957                       mem3blt->nYSrc, gdi_rop3_code_checked(mem3blt->bRop), &gdi->palette);
 
  958      gdi_DeleteObject((
HGDIOBJECT)gdi->drawing->hdc->brush);
 
  960      gdi->drawing->hdc->brush = originalBrush;
 
  965      WLog_ERR(TAG, 
"Mem3Blt unimplemented brush style:%" PRIu32 
"", brush->style);
 
  970  gdi_SetTextColor(gdi->drawing->hdc, originalColor);
 
  974static BOOL gdi_polygon_sc(WINPR_ATTR_UNUSED rdpContext* context,
 
  977  WLog_WARN(TAG, 
"not implemented");
 
  981static BOOL gdi_polygon_cb(WINPR_ATTR_UNUSED rdpContext* context,
 
  984  WLog_WARN(TAG, 
"not implemented");
 
  988static BOOL gdi_ellipse_sc(WINPR_ATTR_UNUSED rdpContext* context,
 
  991  WLog_WARN(TAG, 
"not implemented");
 
  995static BOOL gdi_ellipse_cb(WINPR_ATTR_UNUSED rdpContext* context,
 
  998  WLog_WARN(TAG, 
"not implemented");
 
 1002static BOOL gdi_frame_marker(WINPR_ATTR_UNUSED rdpContext* context,
 
 1008static BOOL gdi_surface_frame_marker(rdpContext* context,
 
 1011  WLog_Print(context->gdi->log, WLOG_DEBUG, 
"frameId %" PRIu32 
" frameAction %" PRIu32 
"",
 
 1012             surfaceFrameMarker->frameId, surfaceFrameMarker->frameAction);
 
 1014  switch (surfaceFrameMarker->frameAction)
 
 1016    case SURFACECMD_FRAMEACTION_BEGIN:
 
 1019    case SURFACECMD_FRAMEACTION_END:
 
 1022        IFCALL(context->update->SurfaceFrameAcknowledge, context,
 
 1023               surfaceFrameMarker->frameId);
 
 1036  const UINT32 w = (
const UINT32)gdi->width;
 
 1037  const UINT32 h = (
const UINT32)gdi->height;
 
 1039  if (cmd->destLeft > w)
 
 1041  if (cmd->destRight > w)
 
 1043  if (cmd->destLeft > cmd->destRight)
 
 1045  if (cmd->destRight > UINT16_MAX)
 
 1048  if (cmd->destTop > h)
 
 1050  if (cmd->destBottom > h)
 
 1052  if (cmd->destTop > cmd->destBottom)
 
 1054  if (cmd->destBottom > UINT16_MAX)
 
 1057  prect->left = (
const UINT16)cmd->destLeft;
 
 1058  prect->top = (
const UINT16)cmd->destTop;
 
 1059  prect->right = MIN((UINT16)cmd->destRight, prect->left + cmd->bmp.width);
 
 1060  prect->bottom = MIN((UINT16)cmd->destBottom, prect->top + cmd->bmp.height);
 
 1066  BOOL result = FALSE;
 
 1073  if (!context || !cmd)
 
 1077  WLog_Print(gdi->log, WLOG_DEBUG,
 
 1078             "destLeft %" PRIu32 
" destTop %" PRIu32 
" destRight %" PRIu32 
" destBottom %" PRIu32
 
 1080             "bpp %" PRIu8 
" flags %" PRIx8 
" codecID %s [0x%04" PRIu16 
"] width %" PRIu16
 
 1081             " height %" PRIu16 
" length %" PRIu32 
"",
 
 1082             cmd->destLeft, cmd->destTop, cmd->destRight, cmd->destBottom, cmd->bmp.bpp,
 
 1083             cmd->bmp.flags, freerdp_codec_id_to_str(cmd->bmp.codecID), cmd->bmp.codecID,
 
 1084             cmd->bmp.width, cmd->bmp.height, cmd->bmp.bitmapDataLength);
 
 1085  region16_init(®ion);
 
 1087  if (!intersect_rect(gdi, cmd, &cmdRect))
 
 1090  switch (cmd->bmp.codecID)
 
 1092    case RDP_CODEC_ID_REMOTEFX:
 
 1093    case RDP_CODEC_ID_IMAGE_REMOTEFX:
 
 1094      if (!rfx_process_message(context->codecs->rfx, cmd->bmp.bitmapData,
 
 1095                               cmd->bmp.bitmapDataLength, cmdRect.left, cmdRect.top,
 
 1096                               gdi->primary_buffer, gdi->dstFormat, gdi->stride,
 
 1097                               WINPR_ASSERTING_INT_CAST(uint32_t, gdi->height), ®ion))
 
 1099        WLog_ERR(TAG, 
"Failed to process RemoteFX message");
 
 1105    case RDP_CODEC_ID_NSCODEC:
 
 1106      format = gdi->dstFormat;
 
 1108      if (!nsc_process_message(
 
 1109              context->codecs->nsc, cmd->bmp.bpp, cmd->bmp.width, cmd->bmp.height,
 
 1110              cmd->bmp.bitmapData, cmd->bmp.bitmapDataLength, gdi->primary_buffer, format,
 
 1111              gdi->stride, cmdRect.left, cmdRect.top, cmdRect.right - cmdRect.left,
 
 1112              cmdRect.bottom - cmdRect.top, FREERDP_FLIP_VERTICAL))
 
 1114        WLog_ERR(TAG, 
"Failed to process NSCodec message");
 
 1118      region16_union_rect(®ion, ®ion, &cmdRect);
 
 1121    case RDP_CODEC_ID_NONE:
 
 1122      format = gdi_get_pixel_format(cmd->bmp.bpp);
 
 1123      size = 1ull * cmd->bmp.width * cmd->bmp.height * FreeRDPGetBytesPerPixel(format);
 
 1124      if (size > cmd->bmp.bitmapDataLength)
 
 1126        WLog_ERR(TAG, 
"Short nocodec message: got %" PRIu32 
" bytes, require %" PRIuz,
 
 1127                 cmd->bmp.bitmapDataLength, size);
 
 1131      if (!freerdp_image_copy_no_overlap(
 
 1132              gdi->primary_buffer, gdi->dstFormat, gdi->stride, cmdRect.left, cmdRect.top,
 
 1133              cmdRect.right - cmdRect.left, cmdRect.bottom - cmdRect.top, cmd->bmp.bitmapData,
 
 1134              format, 0, 0, 0, &gdi->palette, FREERDP_FLIP_VERTICAL))
 
 1136        WLog_ERR(TAG, 
"Failed to process nocodec message");
 
 1140      region16_union_rect(®ion, ®ion, &cmdRect);
 
 1144      WLog_ERR(TAG, 
"Unsupported codecID %" PRIu32 
"", cmd->bmp.codecID);
 
 1149  const RECTANGLE_16* rects = region16_rects(®ion, &nbRects);
 
 1150  if (!rects && (nbRects > 0))
 
 1155    const int32_t w = cmdRect.right - cmdRect.left;
 
 1156    const int32_t h = cmdRect.bottom - cmdRect.top;
 
 1157    if (!gdi_InvalidateRegion(gdi->primary->hdc, cmdRect.left, cmdRect.top, w, h))
 
 1160  for (UINT32 i = 0; i < nbRects; i++)
 
 1164    UINT32 left = rect->left;
 
 1165    UINT32 top = rect->top;
 
 1166    UINT32 width = rect->right - rect->left;
 
 1167    UINT32 height = rect->bottom - rect->top;
 
 1169    if (!gdi_InvalidateRegion(gdi->primary->hdc, WINPR_ASSERTING_INT_CAST(int32_t, left),
 
 1170                              WINPR_ASSERTING_INT_CAST(int32_t, top),
 
 1171                              WINPR_ASSERTING_INT_CAST(int32_t, width),
 
 1172                              WINPR_ASSERTING_INT_CAST(int32_t, height)))
 
 1174      WLog_ERR(TAG, 
"Failed to update invalid region");
 
 1181  region16_uninit(®ion);
 
 1190static void gdi_register_update_callbacks(rdpUpdate* update)
 
 1192  rdpPrimaryUpdate* primary = NULL;
 
 1193  const rdpSettings* settings = NULL;
 
 1195  WINPR_ASSERT(update);
 
 1196  WINPR_ASSERT(update->context);
 
 1198  settings = update->context->settings;
 
 1199  WINPR_ASSERT(settings);
 
 1201  primary = update->primary;
 
 1202  WINPR_ASSERT(primary);
 
 1206  update->Palette = gdi_palette_update;
 
 1207  update->SetBounds = gdi_set_bounds;
 
 1208  primary->DstBlt = gdi_dstblt;
 
 1209  primary->PatBlt = gdi_patblt;
 
 1210  primary->ScrBlt = gdi_scrblt;
 
 1211  primary->OpaqueRect = gdi_opaque_rect;
 
 1212  primary->DrawNineGrid = NULL;
 
 1213  primary->MultiDstBlt = NULL;
 
 1214  primary->MultiPatBlt = NULL;
 
 1215  primary->MultiScrBlt = NULL;
 
 1216  primary->MultiOpaqueRect = gdi_multi_opaque_rect;
 
 1217  primary->MultiDrawNineGrid = NULL;
 
 1218  primary->LineTo = gdi_line_to;
 
 1219  primary->Polyline = gdi_polyline;
 
 1220  primary->MemBlt = gdi_memblt;
 
 1221  primary->Mem3Blt = gdi_mem3blt;
 
 1222  primary->SaveBitmap = NULL;
 
 1223  primary->GlyphIndex = NULL;
 
 1224  primary->FastIndex = NULL;
 
 1225  primary->FastGlyph = NULL;
 
 1226  primary->PolygonSC = gdi_polygon_sc;
 
 1227  primary->PolygonCB = gdi_polygon_cb;
 
 1228  primary->EllipseSC = gdi_ellipse_sc;
 
 1229  primary->EllipseCB = gdi_ellipse_cb;
 
 1230  update->SurfaceBits = gdi_surface_bits;
 
 1231  update->SurfaceFrameMarker = gdi_surface_frame_marker;
 
 1232  update->altsec->FrameMarker = gdi_frame_marker;
 
 1235static BOOL gdi_init_primary(rdpGdi* gdi, UINT32 stride, UINT32 format, BYTE* buffer,
 
 1236                             void (*pfree)(
void*), BOOL isLocked)
 
 1239  WINPR_ASSERT(gdi->context);
 
 1240  WINPR_ASSERT(gdi->context->update);
 
 1242    rdp_update_lock(gdi->context->update);
 
 1244  gdi->primary = (gdiBitmap*)calloc(1, 
sizeof(gdiBitmap));
 
 1247    gdi->dstFormat = format;
 
 1250    gdi->stride = stride;
 
 1252    gdi->stride = WINPR_ASSERTING_INT_CAST(uint32_t, gdi->width) *
 
 1253                  FreeRDPGetBytesPerPixel(gdi->dstFormat);
 
 1258  if (!(gdi->primary->hdc = gdi_CreateCompatibleDC(gdi->hdc)))
 
 1263    gdi->primary->bitmap =
 
 1264        gdi_CreateCompatibleBitmap(gdi->hdc, WINPR_ASSERTING_INT_CAST(uint32_t, gdi->width),
 
 1265                                   WINPR_ASSERTING_INT_CAST(uint32_t, gdi->height));
 
 1269    gdi->primary->bitmap = gdi_CreateBitmapEx(WINPR_ASSERTING_INT_CAST(uint32_t, gdi->width),
 
 1270                                              WINPR_ASSERTING_INT_CAST(uint32_t, gdi->height),
 
 1271                                              gdi->dstFormat, gdi->stride, buffer, pfree);
 
 1274  if (!gdi->primary->bitmap)
 
 1277  gdi->stride = gdi->primary->bitmap->scanline;
 
 1278  gdi_SelectObject(gdi->primary->hdc, (
HGDIOBJECT)gdi->primary->bitmap);
 
 1279  gdi->primary->org_bitmap = NULL;
 
 1280  gdi->primary_buffer = gdi->primary->bitmap->data;
 
 1282  if (!(gdi->primary->hdc->hwnd = (
HGDI_WND)calloc(1, 
sizeof(
GDI_WND))))
 
 1285  if (!(gdi->primary->hdc->hwnd->invalid = gdi_CreateRectRgn(0, 0, 0, 0)))
 
 1288  gdi->primary->hdc->hwnd->invalid->null = TRUE;
 
 1289  gdi->primary->hdc->hwnd->count = 32;
 
 1291  if (!(gdi->primary->hdc->hwnd->cinvalid =
 
 1292            (
GDI_RGN*)calloc(gdi->primary->hdc->hwnd->count, 
sizeof(
GDI_RGN))))
 
 1295  gdi->primary->hdc->hwnd->ninvalid = 0;
 
 1298    gdi->drawing = gdi->primary;
 
 1300  rdp_update_unlock(gdi->context->update);
 
 1303  gdi_DeleteObject((
HGDIOBJECT)gdi->primary->bitmap);
 
 1305  gdi_DeleteDC(gdi->primary->hdc);
 
 1308  gdi->primary = NULL;
 
 1310  rdp_update_unlock(gdi->context->update);
 
 1314BOOL gdi_resize(rdpGdi* gdi, UINT32 width, UINT32 height)
 
 1316  return gdi_resize_ex(gdi, width, height, 0, 0, NULL, NULL);
 
 1319BOOL gdi_resize_ex(rdpGdi* gdi, UINT32 width, UINT32 height, UINT32 stride, UINT32 format,
 
 1320                   BYTE* buffer, 
void (*pfree)(
void*))
 
 1322  if (!gdi || !gdi->primary)
 
 1325  if ((width > INT32_MAX) || (height > INT32_MAX))
 
 1328  if ((gdi->width == (INT32)width) && (gdi->height == (INT32)height) &&
 
 1329      (!buffer || (gdi->primary_buffer == buffer)))
 
 1332  WINPR_ASSERT(gdi->context);
 
 1333  WINPR_ASSERT(gdi->context->update);
 
 1336  if (!update_end_paint(gdi->context->update))
 
 1338  rdp_update_lock(gdi->context->update);
 
 1340  if (gdi->drawing == gdi->primary)
 
 1341    gdi->drawing = NULL;
 
 1343  gdi->width = (INT32)width;
 
 1344  gdi->height = (INT32)height;
 
 1345  gdi_bitmap_free_ex(gdi->primary);
 
 1346  gdi->primary = NULL;
 
 1347  gdi->primary_buffer = NULL;
 
 1348  return gdi_init_primary(gdi, stride, format, buffer, pfree, TRUE);
 
 1358BOOL gdi_init(freerdp* instance, UINT32 format)
 
 1360  return gdi_init_ex(instance, format, 0, NULL, winpr_aligned_free);
 
 1374BOOL gdi_init_ex(freerdp* instance, UINT32 format, UINT32 stride, BYTE* buffer,
 
 1375                 void (*pfree)(
void*))
 
 1377  rdpContext* context = NULL;
 
 1378  UINT32 SrcFormat = 0;
 
 1381  WINPR_ASSERT(instance);
 
 1383  context = instance->context;
 
 1384  WINPR_ASSERT(context);
 
 1385  WINPR_ASSERT(context->settings);
 
 1388  SrcFormat = gdi_get_pixel_format(ColorDepth);
 
 1389  gdi = (rdpGdi*)calloc(1, 
sizeof(rdpGdi));
 
 1395  gdi->log = WLog_Get(TAG);
 
 1400  gdi->context = context;
 
 1401  gdi->width = WINPR_ASSERTING_INT_CAST(
 
 1403  gdi->height = WINPR_ASSERTING_INT_CAST(
 
 1405  gdi->dstFormat = format;
 
 1407  WLog_Print(gdi->log, WLOG_INFO, 
"Local framebuffer format  %s",
 
 1408             FreeRDPGetColorFormatName(gdi->dstFormat));
 
 1409  WLog_Print(gdi->log, WLOG_INFO, 
"Remote framebuffer format %s",
 
 1410             FreeRDPGetColorFormatName(SrcFormat));
 
 1412  if (!(gdi->hdc = gdi_GetDC()))
 
 1415  gdi->hdc->format = gdi->dstFormat;
 
 1417  if (!gdi_init_primary(gdi, stride, gdi->dstFormat, buffer, pfree, FALSE))
 
 1420  if (!(context->cache = cache_new(context)))
 
 1423  gdi_register_update_callbacks(context->update);
 
 1424  brush_cache_register_callbacks(context->update);
 
 1425  glyph_cache_register_callbacks(context->update);
 
 1426  bitmap_cache_register_callbacks(context->update);
 
 1427  offscreen_cache_register_callbacks(context->update);
 
 1428  palette_cache_register_callbacks(context->update);
 
 1430  if (!gdi_register_graphics(context->graphics))
 
 1436  WLog_ERR(TAG, 
"failed to initialize gdi");
 
 1440void gdi_free(freerdp* instance)
 
 1443  rdpContext* context = NULL;
 
 1445  if (!instance || !instance->context)
 
 1448  gdi = instance->context->gdi;
 
 1452    gdi_bitmap_free_ex(gdi->primary);
 
 1453    gdi_DeleteDC(gdi->hdc);
 
 1457  context = instance->context;
 
 1458  cache_free(context->cache);
 
 1459  context->cache = NULL;
 
 1460  instance->context->gdi = (rdpGdi*)NULL;
 
 1463BOOL gdi_send_suppress_output(rdpGdi* gdi, BOOL suppress)
 
 1465  if (!gdi || !gdi->context)
 
 1468  if (gdi->suppressOutput == suppress)
 
 1471  gdi->suppressOutput = suppress;
 
 1473  rdpContext* context = gdi->context;
 
 1474  rdpSettings* settings = context->settings;
 
 1475  WINPR_ASSERT(settings);
 
 1477  rdpUpdate* update = context->update;
 
 1478  WINPR_ASSERT(update);
 
 1485                            .right = WINPR_ASSERTING_INT_CAST(UINT16, w),
 
 1486                            .bottom = WINPR_ASSERTING_INT_CAST(UINT16, h) };
 
 1488  WINPR_ASSERT(update->SuppressOutput);
 
 1489  return update->SuppressOutput(context, !suppress, &rect);
 
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
 
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.