<commit_before>/*
 * nt loader
 *
 * Copyright 2006-2008 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <stdarg.h>
#include <stdio.h>
#include <assert.h>

#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winternl.h"

#include "ntcall.h"
#include "debug.h"
#include "win32mgr.h"
#include "ntwin32.h"
#include "sdl.h"

#include <ft2build.h>
#include FT_FREETYPE_H

#if defined (HAVE_SDL) && defined (HAVE_SDL_SDL_H)
#include <SDL/SDL.h>

class win32k_sdl_t : public win32k_manager_t, public sleeper_t
{
protected:
	SDL_Surface *screen;
	FT_Library ftlib;
public:
	virtual BOOL init();
	virtual void fini();
	win32k_sdl_t();
	virtual BOOL set_pixel( INT x, INT y, COLORREF color );
	virtual BOOL rectangle( INT left, INT top, INT right, INT bottom, brush_t* brush );
	virtual BOOL exttextout( INT x, INT y, UINT options,
		 LPRECT rect, UNICODE_STRING& text );
	virtual BOOL bitblt( INT xDest, INT yDest, INT cx, INT cy, device_context_t *src, INT xSrc, INT ySrc, ULONG rop );
	virtual BOOL polypatblt( ULONG Rop, PRECT rect );

protected:
	Uint16 map_colorref( COLORREF );
	virtual SDL_Surface* set_mode() = 0;
	virtual void set_pixel_l( INT x, INT y, COLORREF color ) = 0;
	virtual void rectangle_l( INT left, INT top, INT right, INT bottom, brush_t* brush ) = 0;
	virtual void bitblt_l( INT xDest, INT yDest, INT cx, INT cy, device_context_t *src, INT xSrc, INT ySrc, ULONG rop ) = 0;
	virtual BOOL polypatblt_l( ULONG Rop, PRECT rect ) = 0;
	virtual bool check_events( bool wait );
	virtual int getcaps( int index );
	static Uint32 timeout_callback( Uint32 interval, void *arg );
	bool handle_sdl_event( SDL_Event& event );
	WORD sdl_keysum_to_vkey( SDLKey sym );
	ULONG get_mouse_button( Uint8 button, bool up );
};

win32k_sdl_t::win32k_sdl_t()
{
}

BOOL win32k_sdl_t::set_pixel( INT x, INT y, COLORREF color )
{
	if ( SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0 )
		return FALSE;

	set_pixel_l( x, y, color );

	if ( SDL_MUSTLOCK(screen) )
		SDL_UnlockSurface(screen);

	SDL_UpdateRect(screen, x, y, 1, 1);

	return TRUE;
}

template<typename T> void swap( T& A, T& B )
{
	T x = A;
	A = B;
	B = x;
}

BOOL win32k_sdl_t::rectangle(INT left, INT top, INT right, INT bottom, brush_t* brush )
{
	if ( SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0 )
		return FALSE;

	if (left > right)
		swap( left, right );
	if (top > bottom)
		swap( top, bottom );

	top = max( 0, top );
	left = max( 0, left );
	right = min( screen->w - 1, right );
	bottom = min( screen->h - 1, bottom );

	rectangle_l( left, top, right, bottom, brush );

	if ( SDL_MUSTLOCK(screen) )
		SDL_UnlockSurface(screen);

	SDL_UpdateRect( screen, left, top, right - left, bottom - top );

	return TRUE;
}

BOOL win32k_sdl_t::exttextout( INT x, INT y, UINT options,
		 LPRECT rect, UNICODE_STRING& text )
{
	if ( SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0 )
		return FALSE;

	dprintf("text: %pus\n", &text );

	if ( SDL_MUSTLOCK(screen) )
		SDL_UnlockSurface(screen);

	//SDL_UpdateRect( screen, left, top, right - left, bottom - top );

	return TRUE;
}

BOOL win32k_sdl_t::bitblt(
	INT xDest, INT yDest,
	INT cx, INT cy,
	device_context_t *src,
	INT xSrc, INT ySrc, ULONG rop )
{
	// keep everything on the screen
	xDest = max( xDest, 0 );
	yDest = max( yDest, 0 );
	if ((xDest + cx) > screen->w)<commit_msg>Add basic support for TextOut<commit_after>/*
 * nt loader
 *
 * Copyright 2006-2009 <NAME>
 *
 * Portions based upon Wine DIB engine implementation by:
 *
 *  Copyright 2007 <NAME>en
 *  Copyright 2008 <NAME>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <stdarg.h>
#include <stdio.h>
#include <assert.h>

#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winternl.h"

#include "ntcall.h"
#include "debug.h"
#include "win32mgr.h"
#include "ntwin32.h"
#include "sdl.h"

// the freetype project certainly has their own way of doing things :/
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H

#if defined (HAVE_SDL) && defined (HAVE_SDL_SDL_H)
#include <SDL/SDL.h>

class win32k_sdl_t : public win32k_manager_t, public sleeper_t
{
protected:
	SDL_Surface *screen;
	FT_Library ftlib;
	FT_Face face;
public:
	virtual BOOL init();
	virtual void fini();
	win32k_sdl_t();
	virtual BOOL set_pixel( INT x, INT y, COLORREF color );
	virtual BOOL rectangle( INT left, INT top, INT right, INT bottom, brush_t* brush );
	virtual BOOL exttextout( INT x, INT y, UINT options,
		 LPRECT rect, UNICODE_STRING& text );
	virtual BOOL bitblt( INT xDest, INT yDest, INT cx, INT cy, device_context_t *src, INT xSrc, INT ySrc, ULONG rop );
	virtual BOOL polypatblt( ULONG Rop, PRECT rect );

protected:
	Uint16 map_colorref( COLORREF );
	virtual SDL_Surface* set_mode() = 0;
	virtual void set_pixel_l( INT x, INT y, COLORREF color ) = 0;
	virtual void rectangle_l( INT left, INT top, INT right, INT bottom, brush_t* brush ) = 0;
	virtual void bitblt_l( INT xDest, INT yDest, INT cx, INT cy, device_context_t *src, INT xSrc, INT ySrc, ULONG rop ) = 0;
	virtual BOOL polypatblt_l( ULONG Rop, PRECT rect ) = 0;
	virtual bool check_events( bool wait );
	virtual int getcaps( int index );
	static Uint32 timeout_callback( Uint32 interval, void *arg );
	bool handle_sdl_event( SDL_Event& event );
	WORD sdl_keysum_to_vkey( SDLKey sym );
	ULONG get_mouse_button( Uint8 button, bool up );
	void freetype_bitblt( int x, int y, FT_Bitmap* bitmap );
	COLORREF freetype_get_pixel( int x, int y, FT_Bitmap* bitmap );
};

win32k_sdl_t::win32k_sdl_t()
{
}

BOOL win32k_sdl_t::set_pixel( INT x, INT y, COLORREF color )
{
	if ( SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0 )
		return FALSE;

	set_pixel_l( x, y, color );

	if ( SDL_MUSTLOCK(screen) )
		SDL_UnlockSurface(screen);

	SDL_UpdateRect(screen, x, y, 1, 1);

	return TRUE;
}

template<typename T> void swap( T& A, T& B )
{
	T x = A;
	A = B;
	B = x;
}

BOOL win32k_sdl_t::rectangle(INT left, INT top, INT right, INT bottom, brush_t* brush )
{
	if ( SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0 )
		return FALSE;

	if (left > right)
		swap( left, right );
	if (top > bottom)
		swap( top, bottom );

	top = max( 0, top );
	left = max( 0, left );
	right = min( screen->w - 1, right );
	bottom = min( screen->h - 1, bottom );

	rectangle_l( left, top, right, bottom, brush );

	if ( SDL_MUSTLOCK(screen) )
		SDL_UnlockSurface(screen);

	SDL_UpdateRect( screen, left, top, right - left, bottom - top );

	return TRUE;
}

COLORREF win32k_sdl_t::freetype_get_pixel( int x, int y, FT_Bitmap* bitmap )
{
	int bytes_per_row;
	int val;
	switch (bitmap->pixel_mode)
	{
	case FT_PIXEL_MODE_MONO:
		bytes_per_row = bitmap->pitch;
		val = (bitmap->buffer[bytes_per_row*y + (x>>3)] << (x&7)) & 0x80;
		return val ? RGB( 255, 255, 255 ) : RGB( 0, 0, 0 );
	default:
		dprintf("unknown freetype pixel mode %d\n", bitmap->pixel_mode);
		return 0;
	}
}

void win32k_sdl_t::freetype_bitblt( int x, int y, FT_Bitmap* bitmap )
{
	INT bmpX, bmpY;
	BYTE *buf;
	INT j, i;

	dprintf("glyph is %dx%d\n", bitmap->rows, bitmap->width);
	dprintf("pixel mode is %d\n", bitmap->pixel_mode );
	dprintf("destination is %d,%d\n", x, y );
	dprintf("pitch is %d\n", bitmap->pitch );

	/* loop for every pixel in bitmap */
	buf = bitmap->buffer;
	for (bmpY = 0, i = y; bmpY < bitmap->rows; bmpY++, i++)
	{
		for (bmpX = 0, j = x; bmpX < bitmap->width; bmpX++, j++)
		{
			// FIXME: assumes text color is black
			COLORREF color = freetype_get_pixel( bmpX, bmpY, bitmap );
			set_pixel( j, i, color );
		}
	}

}

BOOL win32k_sdl_t::exttextout( INT x, INT y, UINT options,
		 LPRECT rect, UNICODE_STRING& text )
{
	dprintf("text: %pus\n", &text );

	FT_Open_Args args;
	memset( &args, 0, sizeof args );
	args.flags = FT_OPEN_PATHNAME;
	args.pathname = "drive/winnt/system32/vgasys.fon";

	FT_Error r = FT_Open_Face( ftlib, &args, 0, &face );
	if (r)
		return FALSE;

	if ( SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0 )
		return FALSE;

	int dx = 0, dy = 0;
	for (int i=0; i<text.Length/2; i++)
	{
		WCHAR ch = text.Buffer[i];
		FT_UInt glyph_index = FT_Get_Char_Index( face, ch );

		r = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
		if (r)
			continue;

		FT_Glyph glyph;
		r = FT_Get_Glyph( face->glyph, &glyph );
		if (r)
			continue;

		if (glyph->format != FT_GLYPH_FORMAT_BITMAP )
			continue;

		FT_BitmapGlyph bitmap = (FT_BitmapGlyph) glyph;
		dx += bitmap->bitmap.width;
		dy += 0;

		freetype_bitblt( x+dx+bitmap->left, y+dy+bitmap->top, &bitmap->bitmap );

		FT_Done_Glyph( glyph );
	}

	if ( SDL_MUSTLOCK(screen) )
		SDL_UnlockSurface(screen);

	SDL_UpdateRect( screen, x, y, x+dx, y+dy);

	return TRUE;
}

BOOL win32k_sdl_t::bitblt(
	INT xDest, INT yDest,
	INT cx, INT cy,
	device_context_t *src,
	INT xSrc, INT ySrc, ULONG rop )
{
	// keep everything on the screen
	xDest = max( xDest, 0 );
	yDest = max( yDest, 0 );
	if ((xDest + cx) > screen->w)
{'fraction_non_alphanumeric': 0.12083535696940262, 'fraction_numerical': 0.017387081107333658, 'mean_word_length': 4.102081268582755, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5472694', 'n_tokens_mistral': 4139, 'n_tokens_neox': 3806, 'n_words': 1258}