\
<?php
/**
 * Minimal PDF engine (1 page) with WinAnsi (Windows-1252) encoding.
 * Fixes:
 * - Ensures UTF-8 is converted to CP1252 bytes so € and accents render correctly.
 */

function pdf_escape_bytes(string $bytes): string {
  $bytes = str_replace(["\\", "(", ")", "\r", "\n"], ["\\\\", "\(", "\)", "", ""], $bytes);
  $out = '';
  for ($i=0; $i<strlen($bytes); $i++){
    $c = ord($bytes[$i]);
    if ($c < 32 || $c > 126) $out .= sprintf("\\%03o", $c);
    else $out .= chr($c);
  }
  return $out;
}

function pdf_to_winansi(string $utf8): string {
  // Prefer iconv to CP1252
  if (function_exists('iconv')) {
    $b = @iconv('UTF-8', 'Windows-1252//TRANSLIT//IGNORE', $utf8);
    if ($b !== false && $b !== '') {
      // Make sure € is correctly represented (0x80)
      // Some iconv setups may drop it; re-inject if needed.
      if (strpos($utf8, '€') !== false && strpos($b, chr(0x80)) === false) {
        $b = str_replace('EUR', chr(0x80), $b);
      }
      return $b;
    }
  }
  // Manual fallback mapping for common Spanish chars + €
  $map = [
    '€'=>chr(0x80),
    'Á'=>chr(0xC1),'É'=>chr(0xC9),'Í'=>chr(0xCD),'Ó'=>chr(0xD3),'Ú'=>chr(0xDA),
    'á'=>chr(0xE1),'é'=>chr(0xE9),'í'=>chr(0xED),'ó'=>chr(0xF3),'ú'=>chr(0xFA),
    'Ñ'=>chr(0xD1),'ñ'=>chr(0xF1),
    'Ü'=>chr(0xDC),'ü'=>chr(0xFC),
    'º'=>chr(0xBA),'ª'=>chr(0xAA),
    '¿'=>chr(0xBF),'¡'=>chr(0xA1),
  ];
  $s = strtr($utf8, $map);
  // Strip remaining non-ascii/latin-1 bytes
  $s = preg_replace('/[^\x09\x0A\x0D\x20-\xFF]/', '?', $s);
  return $s;
}

function pdf_text($x,$y,$text,$size=10): string {
  $bytes = pdf_to_winansi((string)$text);
  $t = pdf_escape_bytes($bytes);
  return "BT /F1 {$size} Tf {$x} {$y} Td ({$t}) Tj ET\n";
}

function pdf_line($x1,$y1,$x2,$y2): string { return "{$x1} {$y1} m {$x2} {$y2} l S\n"; }
function pdf_rect($x,$y,$w,$h): string { return "{$x} {$y} {$w} {$h} re S\n"; }
function pdf_image_do($name,$x,$y,$w,$h): string { return "q {$w} 0 0 {$h} {$x} {$y} cm /{$name} Do Q\n"; }

function pdf_load_image_any(string $absPath, string $name='Im1'): ?array {
  if(!is_file($absPath)) return null;
  $data = @file_get_contents($absPath);
  if($data===false) return null;
  $info = @getimagesizefromstring($data);
  if(!$info) return null;
  $type = $info[2] ?? null;

  if($type === IMAGETYPE_JPEG){
    return ['name'=>$name,'data'=>$data,'w'=>$info[0],'h'=>$info[1]];
  }

  // Convert any format to JPEG if GD exists
  if(!function_exists('imagecreatefromstring') || !function_exists('imagejpeg')) return null;
  $im = @imagecreatefromstring($data);
  if(!$im) return null;
  $w = imagesx($im); $h = imagesy($im);
  $canvas = imagecreatetruecolor($w, $h);
  $white = imagecolorallocate($canvas, 255,255,255);
  imagefill($canvas, 0,0, $white);
  imagecopy($canvas, $im, 0,0,0,0, $w,$h);
  ob_start();
  imagejpeg($canvas, null, 88);
  $jpg = ob_get_clean();
  imagedestroy($im); imagedestroy($canvas);
  if(!$jpg) return null;
  return ['name'=>$name,'data'=>$jpg,'w'=>$w,'h'=>$h];
}

function pdf_build_onepage(string $contentStream, ?array $img=null): string {
  $objects = [];
  $objects[] = "<< /Type /Catalog /Pages 2 0 R >>";
  $objects[] = "<< /Type /Pages /Kids [3 0 R] /Count 1 >>";

  $xobj = "";
  if($img){ $xobj = "/XObject << /".$img['name']." 5 0 R >>"; }
  $objects[] = "<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R >> {$xobj} >> /Contents 6 0 R >>";

  $objects[] = "<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>";

  if($img){
    $len = strlen($img['data']);
    $objects[] = "<< /Type /XObject /Subtype /Image /Width {$img['w']} /Height {$img['h']} /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length {$len} >>\nstream\n".$img['data']."\nendstream";
  }

  $stream = $contentStream;
  $objects[] = "<< /Length ".strlen($stream)." >>\nstream\n{$stream}\nendstream";

  $pdf = "%PDF-1.4\n";
  $offsets = [0];
  for($i=0; $i<count($objects); $i++){
    $offsets[] = strlen($pdf);
    $n = $i+1;
    $pdf .= "{$n} 0 obj\n{$objects[$i]}\nendobj\n";
  }
  $xrefPos = strlen($pdf);
  $pdf .= "xref\n0 ".(count($objects)+1)."\n";
  $pdf .= "0000000000 65535 f \n";
  for($i=1; $i<=count($objects); $i++){
    $pdf .= str_pad((string)$offsets[$i], 10, "0", STR_PAD_LEFT)." 00000 n \n";
  }
  $pdf .= "trailer\n<< /Size ".(count($objects)+1)." /Root 1 0 R >>\nstartxref\n{$xrefPos}\n%%EOF";
  return $pdf;
}
