diff --git a/src/Milon/Barcode/DNS1D.php b/src/Milon/Barcode/DNS1D.php index 603ccba..50b08ca 100644 --- a/src/Milon/Barcode/DNS1D.php +++ b/src/Milon/Barcode/DNS1D.php @@ -149,15 +149,18 @@ public function getBarcodeHTML($code, $type, $w = 2, $h = 30, $color = 'black', $this->ensureStorePath(); $this->setBarcode($code, $type); $pad = $this->getPadding(); + $eanLayout = $this->usesEanUpcLayout(); + $labelMargin = ($showCode && $eanLayout) ? max(10, $w * 6) : 0; + $fontSize = is_bool($showCode) ? 12 : (int) $showCode; $contentWidth = $this->barcode_array['maxw'] * $w; - $html = '
' . "\n"; + $html = '
' . "\n"; // print bars - $x = $pad; + $x = $pad + $labelMargin; foreach ($this->barcode_array['bcode'] as $k => $v) { $bw = round(($v['w'] * $w), 3); $bh = round(($v['h'] * $h / $this->barcode_array['maxh']), 3); - if($showCode) - $bh -= ($showCode + 12); + if($showCode && !$eanLayout) + $bh -= ($fontSize + 12); if ($v['t']) { $y = round(($v['p'] * $h / $this->barcode_array['maxh']), 3) + $pad; // draw a vertical bar @@ -166,7 +169,11 @@ public function getBarcodeHTML($code, $type, $w = 2, $h = 30, $color = 'black', $x += $bw; } if($showCode) - $html .= '
' . $code . '
'; + if ($eanLayout) { + $html .= $this->buildEanUpcHriHtml($color, $w, $h, $pad, $labelMargin, $contentWidth, $fontSize); + } else { + $html .= '
' . $code . '
'; + } $html .= '
' . "\n"; return $html; @@ -402,6 +409,64 @@ protected function buildEanUpcHriSvg($color, $w, $h, $pad, $labelMargin, $conten return $svg; } + /** + * Draw retail-style human-readable digits for EAN/UPC (HTML). + * + * @param string $color + * @param float|int $w + * @param float|int $h + * @param int $pad + * @param int $labelMargin + * @param float|int $contentWidth + * @param int $fontSize + * @return string + */ + protected function buildEanUpcHriHtml($color, $w, $h, $pad, $labelMargin, $contentWidth, $fontSize) + { + if (empty($this->barcode_array['hri']) || !is_array($this->barcode_array['hri'])) { + return ''; + } + + $hri = $this->barcode_array['hri']; + $barsLeft = $pad + $labelMargin; + $style = 'position:absolute;bottom:' . $pad . 'px;color:' . $color . ';font-size:' . $fontSize . 'px;line-height:1;'; + $html = ''; + + if (isset($hri['left']) && $hri['left'] !== '') { + $html .= '
' . $hri['left'] . '
' . "\n"; + } + if (isset($hri['right']) && $hri['right'] !== '') { + $html .= '
' . $hri['right'] . '
' . "\n"; + } + if (isset($hri['middle']) && $hri['middle'] !== '') { + $html .= '
' . $hri['middle'] . '
' . "\n"; + + return $html; + } + + $type = isset($this->barcode_array['ean_type']) ? $this->barcode_array['ean_type'] : 'EAN13'; + if ($type === 'EAN8') { + $leftStart = 3; + $leftMods = 28; + $rightStart = 36; + $rightMods = 28; + } else { + $leftStart = 3; + $leftMods = 42; + $rightStart = 50; + $rightMods = 42; + } + + if (isset($hri['middle_left']) && $hri['middle_left'] !== '') { + $html .= '
' . $hri['middle_left'] . '
' . "\n"; + } + if (isset($hri['middle_right']) && $hri['middle_right'] !== '') { + $html .= '
' . $hri['middle_right'] . '
' . "\n"; + } + + return $html; + } + /** * Return a .png file path which create in server * @param $code (string) code to print diff --git a/tests/UpcALayoutAndQrLogoTest.php b/tests/UpcALayoutAndQrLogoTest.php index 8d2d7f4..15f08f2 100644 --- a/tests/UpcALayoutAndQrLogoTest.php +++ b/tests/UpcALayoutAndQrLogoTest.php @@ -44,6 +44,47 @@ public function testEan13HriKeepsFirstDigitSeparate(): void $this->assertStringContainsString('>123457<', $svg); } + public function testEan13HtmlRetailLayoutKeepsFullHeightAndSplitHri(): void + { + $dns = new DNS1D(); + $html = $dns->getBarcodeHTML('5901234123457', 'EAN13', 2, 60, 'black', 14); + + // Digit bars keep 7/11 of the height instead of subtracting showCode a second time. + $this->assertStringContainsString('height:38.182px', $html); + // Guard bars stay at full height and the root box does not grow. + $this->assertStringContainsString('height:60px', $html); + // Split human-readable digits, like the SVG/PNG output. + $this->assertStringContainsString('>5
', $html); + $this->assertStringContainsString('>901234', $html); + $this->assertStringContainsString('>123457', $html); + } + + public function testEan13HtmlWithoutShowCodeHasNoDigits(): void + { + $dns = new DNS1D(); + $html = $dns->getBarcodeHTML('5901234123457', 'EAN13', 2, 55); + + $this->assertStringNotContainsString('text-align:center;color', $html); + } + + public function testEan13HtmlShowCodeTrueUsesSvgDefaultFontSize(): void + { + $dns = new DNS1D(); + $html = $dns->getBarcodeHTML('5901234123457', 'EAN13', 2, 60, 'black', true); + + $this->assertStringContainsString('font-size:12px', $html); + } + + public function testNonEanHtmlStillReservesSpaceForCode(): void + { + $dns = new DNS1D(); + $html = $dns->getBarcodeHTML('TEST123', 'C128', 2, 50, 'black', 12); + + // 50 - (12 + 12) = 26px, same as before the retail layout. + $this->assertStringContainsString('height:26px', $html); + $this->assertStringContainsString('font-size: 12px;">TEST123', $html); + } + public function testQrLogoIsCompositedInCenter(): void { $logoPath = sys_get_temp_dir() . '/milon-barcode-logo-' . uniqid('', true) . '.png';