TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
6.8 KiB
261 lines
6.8 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Yangweijie\Ui2\Games\OnePieceDoudizhu;
|
|
|
|
/**
|
|
* Win32 rendering shim.
|
|
*
|
|
* The original GameController was written against libui's DrawContext /
|
|
* Brush / Color / FontDescriptor API. Those symbols are re-declared here, in
|
|
* the SAME namespace, so the controller's drawing code stays byte-for-byte
|
|
* identical while the actual pixels are produced by the Win32 GDI primitives
|
|
* declared in win32.stub.php (implemented in cpp-src/win32.cc).
|
|
*
|
|
* Colour convention: PHP code passes 0xRRGGBB ints. GDI needs 0xBBGGRR, so
|
|
* ddz_rgb() flips the channels on the way down to C++.
|
|
*/
|
|
|
|
/* ----------------------------- constants ------------------------------ */
|
|
|
|
/** Text alignment — mirrors libui DrawTextAlign. */
|
|
final class DrawTextAlign
|
|
{
|
|
public const Left = 0;
|
|
public const Center = 1;
|
|
public const Right = 2;
|
|
}
|
|
|
|
/** Font weight — mirrors libui TextWeight. */
|
|
final class TextWeight
|
|
{
|
|
public const Normal = 400;
|
|
public const Bold = 700;
|
|
}
|
|
|
|
/* ----------------------------- color types ---------------------------- */
|
|
|
|
final class Color
|
|
{
|
|
public int $hex;
|
|
|
|
public function __construct(int $hex)
|
|
{
|
|
$this->hex = $hex & 0xFFFFFF;
|
|
}
|
|
|
|
public static function rgb(int $hex): self
|
|
{
|
|
return new self($hex);
|
|
}
|
|
|
|
/** libui accepts normalised floats here (r,g,b in 0..1). */
|
|
public static function rgba(float $r, float $g, float $b, float $a): self
|
|
{
|
|
$rr = (int) ($r * 255);
|
|
$gg = (int) ($g * 255);
|
|
$bb = (int) ($b * 255);
|
|
|
|
return new self(($rr << 16) | ($gg << 8) | $bb);
|
|
}
|
|
}
|
|
|
|
final class Brush
|
|
{
|
|
public int $hex;
|
|
|
|
public function __construct(int $hex)
|
|
{
|
|
$this->hex = $hex & 0xFFFFFF;
|
|
}
|
|
|
|
public static function rgb(int $hex): self
|
|
{
|
|
return new self($hex);
|
|
}
|
|
|
|
/** Extract the int colour from a Color (or pass-through an int brush). */
|
|
public static function color($c): int
|
|
{
|
|
if ($c instanceof Color) {
|
|
return $c->hex;
|
|
}
|
|
if ($c instanceof Brush) {
|
|
return $c->hex;
|
|
}
|
|
|
|
return (int) $c;
|
|
}
|
|
|
|
/**
|
|
* Gradients are approximated by a solid fill in this GDI port.
|
|
*
|
|
* Signature mirrors libui's brushForFill linearGradient: four float
|
|
* coordinates plus a list of [offset, r, g, b, a] stops. We take the
|
|
* colour of the LAST stop (or the deep-navy fallback) as the flat fill.
|
|
*
|
|
* @param array<int, array{0: float, 1: float, 2: float, 3: float, 4?: float}> $stops
|
|
*/
|
|
public static function linearGradient(float $x0, float $y0, float $x1, float $y1, array $stops): self
|
|
{
|
|
$hex = 0x08152e;
|
|
if (\count($stops) > 0) {
|
|
$last = $stops[\count($stops) - 1];
|
|
$r = (int) ($last[1] * 255);
|
|
$g = (int) ($last[2] * 255);
|
|
$b = (int) ($last[3] * 255);
|
|
$hex = ($r << 16) | ($g << 8) | $b;
|
|
}
|
|
|
|
return new self($hex);
|
|
}
|
|
}
|
|
|
|
final class StrokeParams
|
|
{
|
|
public int $thickness = 1;
|
|
|
|
public function thickness(int $t): self
|
|
{
|
|
$this->thickness = $t;
|
|
|
|
return $this;
|
|
}
|
|
}
|
|
|
|
final class FontDescriptor
|
|
{
|
|
public string $family;
|
|
public int $size;
|
|
public int $weight;
|
|
|
|
public function __construct(string $family, int $size, int $weight = TextWeight::Normal)
|
|
{
|
|
$this->family = $family;
|
|
$this->size = $size;
|
|
$this->weight = $weight;
|
|
}
|
|
}
|
|
|
|
/* ----------------------------- helpers -------------------------------- */
|
|
|
|
/** 0xRRGGBB -> Win32 COLORREF (0xBBGGRR). */
|
|
function ddz_rgb(int $hex): int
|
|
{
|
|
$r = ($hex >> 16) & 0xFF;
|
|
$g = ($hex >> 8) & 0xFF;
|
|
$b = $hex & 0xFF;
|
|
|
|
return ($r) | ($g << 8) | ($b << 16);
|
|
}
|
|
|
|
/* ------------------- UTF-8 helpers (no mbstring) ---------------------- */
|
|
|
|
/**
|
|
* Character (code point) length of a UTF-8 string.
|
|
* mbstring is not linked into the TypePHP runtime, so we count code points
|
|
* with PCRE instead of mb_strlen().
|
|
*/
|
|
function ddz_utf8_len(string $s): int
|
|
{
|
|
if ($s === '') {
|
|
return 0;
|
|
}
|
|
|
|
return \preg_match_all('/./us', $s);
|
|
}
|
|
|
|
/**
|
|
* Safe UTF-8 substring by code points (no mbstring).
|
|
* Negative $start/$len behave like mb_substr() (offsets from the end).
|
|
*/
|
|
function ddz_utf8_substr(string $s, int $start, int $len = 0): string
|
|
{
|
|
if ($s === '') {
|
|
return '';
|
|
}
|
|
\preg_match_all('/./us', $s, $m);
|
|
$chars = $m[0];
|
|
$n = \count($chars);
|
|
if ($len === 0) {
|
|
$len = $n;
|
|
}
|
|
if ($start < 0) {
|
|
$start = \max(0, $n + $start);
|
|
}
|
|
if ($len < 0) {
|
|
$len = \max(0, $n - $start + $len);
|
|
}
|
|
$slice = \array_slice($chars, $start, $len);
|
|
|
|
return \implode('', $slice);
|
|
}
|
|
|
|
/* --------------------------- draw context ----------------------------- */
|
|
|
|
/**
|
|
* Mimics libui's DrawContext but renders through Win32 GDI. The single
|
|
* constructor argument is the memory-DC handle produced by win_begin_paint().
|
|
*/
|
|
final class WinDrawContext
|
|
{
|
|
private int $hdc;
|
|
|
|
public function __construct(int $hdc)
|
|
{
|
|
$this->hdc = $hdc;
|
|
}
|
|
|
|
private function colOf($b): int
|
|
{
|
|
if ($b instanceof Color || $b instanceof Brush) {
|
|
return $b->hex;
|
|
}
|
|
|
|
return (int) $b;
|
|
}
|
|
|
|
public function fillRect(float $x, float $y, float $w, float $h, $brush): void
|
|
{
|
|
win_fill_rect($this->hdc, (int) $x, (int) $y, (int) $w, (int) $h, ddz_rgb($this->colOf($brush)));
|
|
}
|
|
|
|
/** Ellipse centred at (cx, cy) — matches libui semantics. */
|
|
public function fillEllipse(float $cx, float $cy, float $w, float $h, $brush): void
|
|
{
|
|
win_fill_ellipse($this->hdc, (int) $cx, (int) $cy, (int) $w, (int) $h, ddz_rgb($this->colOf($brush)));
|
|
}
|
|
|
|
public function fillRoundedRect(float $x, float $y, float $w, float $h, float $r, $brush): void
|
|
{
|
|
win_fill_rounded_rect($this->hdc, (int) $x, (int) $y, (int) $w, (int) $h, (int) $r, ddz_rgb($this->colOf($brush)));
|
|
}
|
|
|
|
public function strokeRoundedRect(float $x, float $y, float $w, float $h, float $r, $brush, StrokeParams $stroke): void
|
|
{
|
|
win_stroke_rounded_rect(
|
|
$this->hdc,
|
|
(int) $x, (int) $y, (int) $w, (int) $h, (int) $r,
|
|
ddz_rgb($this->colOf($brush)),
|
|
(int) $stroke->thickness
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param int $w width of the alignment box (0 = no alignment)
|
|
* @param int $align DrawTextAlign::Left|Center|Right
|
|
*/
|
|
public function drawString(string $text, FontDescriptor $font, Color $color, float $x, float $y, int $w = 0, int $align = DrawTextAlign::Left): void
|
|
{
|
|
win_draw_text_ex(
|
|
$this->hdc,
|
|
(int) $x, (int) $y, $text,
|
|
(int) $font->size,
|
|
ddz_rgb($color->hex),
|
|
$font->weight >= TextWeight::Bold ? 1 : 0,
|
|
(int) $w,
|
|
(int) $align
|
|
);
|
|
}
|
|
}
|
|
|