{"record":{"id":"173a1fca621af09d","repo":"PHPOffice/PhpSpreadsheet","slug":"imagettfbbox-failed","errorCode":null,"errorMessage":"imagettfbbox failed","messagePattern":"imagettfbbox failed","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Shared/Font.php","lineNumber":434,"sourceCode":"        // Convert from pixel width to column width\n        $columnWidth = Drawing::pixelsToCellDimension((int) $columnWidth, $defaultFont ?? new FontStyle());\n\n        // Return\n        return round($columnWidth, 4);\n    }\n\n    /**\n     * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle.\n     */\n    public static function getTextWidthPixelsExact(string $text, FontStyle $font, int $rotation = 0): float\n    {\n        // font size should really be supplied in pixels in GD2,\n        // but since GD2 seems to assume 72dpi, pixels and points are the same\n        $fontFile = self::getTrueTypeFontFileFromFont($font);\n        $textBox = imagettfbbox($font->getSize() ?? 10.0, $rotation, $fontFile, $text);\n        if ($textBox === false) {\n            // @codeCoverageIgnoreStart\n            throw new PhpSpreadsheetException('imagettfbbox failed');\n            // @codeCoverageIgnoreEnd\n        }\n\n        // Get corners positions\n        /** @var int[] $textBox */\n        $lowerLeftCornerX = $textBox[0];\n        $lowerRightCornerX = $textBox[2];\n        $upperRightCornerX = $textBox[4];\n        $upperLeftCornerX = $textBox[6];\n\n        // Consider the rotation when calculating the width\n        return round(max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX), 4);\n    }\n\n    /**\n     * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle.\n     *\n     * @return int Text width in pixels (no padding added)","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Shared/Font.php#L416-L452","documentation":"Thrown by Font::getTextWidthPixelsExact() when PHP's GD function imagettfbbox() returns false while measuring rendered text width. This method is only used for the 'exact' column auto-size mode (Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT)); the default 'approx' mode never calls GD. The failure almost always means the resolved TrueType font file could not be parsed by FreeType, or the GD extension lacks usable FreeType support.","triggerScenarios":"Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT) followed by enabling $sheet->getColumnDimension('X')->setAutoSize(true) and saving via any writer; calculateColumnWidth() routes to getTextWidthPixelsExact(), which calls getTrueTypeFontFileFromFont() and then imagettfbbox(). It fails when the TTF file at the resolved path is corrupt/empty/not a real TTF, when the file is unreadable by the PHP process, or when GD is compiled without FreeType.","commonSituations":"Deploying to a slim Docker/alpine image where the GD extension has no freetype support; pointing Font::setTrueTypeFontPath() at a directory with placeholder or zero-byte font files; a font name that maps to a file that exists but is actually a collection/OTF/var-font FreeType cannot open in this build; upgrading PHP/GD versions that drop FreeType.","solutions":["Check GD capabilities: var_dump(gd_info()) and confirm ['FreeType Support'] => true; if missing, reinstall/enable php-gd compiled with FreeType (e.g. apt install libfreetype6-dev + rebuild, or use an image that bundles it).","Verify the exact TTF file being used: inspect Font::getTrueTypeFontPath() and the file getTrueTypeFontFileFromFont() resolves for the cell font; open that .ttf with fontforge/fc-query to confirm it is a valid TrueType font readable by the web server user.","Point Font::setTrueTypeFontPath() to a directory of known-good .ttf files (e.g. a copy of the Calibri/Arial files you actually use) and make sure the font name set on cells maps to a real variant (bold/italic files present).","If exact measurement is not required, stay with the default: Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_APPROX) — it uses an approximation and never touches GD."],"exampleFix":"// before\nFont::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT);\n$sheet->getColumnDimension('A')->setAutoSize(true);\n$writer->save('out.xlsx'); // imagettfbbox failed\n\n// after\nif (function_exists('gd_info') && (gd_info()['FreeType Support'] ?? false)) {\n    Font::setTrueTypeFontPath('/var/www/fonts'); // dir with valid .ttf files\n    Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_EXACT);\n} else {\n    Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_APPROX);\n}","handlingStrategy":"fallback","validationCode":"$info = function_exists('gd_info') ? gd_info() : [];\n$canExact = ($info['FreeType Support'] ?? false)\n    && is_dir(\\PhpOffice\\PhpSpreadsheet\\Shared\\Font::getTrueTypeFontPath());\n\\PhpOffice\\PhpSpreadsheet\\Shared\\Font::setAutoSizeMethod(\n    $canExact ? Font::AUTOSIZE_METHOD_EXACT : Font::AUTOSIZE_METHOD_APPROX\n);","typeGuard":null,"tryCatchPattern":"try {\n    $writer->save($path); // exact autosize runs here\n} catch (\\PhpOffice\\PhpSpreadsheet\\Exception $e) {\n    if (str_contains($e->getMessage(), 'imagettfbbox')) {\n        \\PhpOffice\\PhpSpreadsheet\\Shared\\Font::setAutoSizeMethod(Font::AUTOSIZE_METHOD_APPROX);\n        $writer->save($path); // retry without GD\n    } else { throw $e; }\n}","preventionTips":["Confirm gd_info()['FreeType Support'] before enabling AUTOSIZE_METHOD_EXACT in a new environment.","Treat exact autosize as an optional enhancement: default to approx in containers where you do not control the GD build.","Keep a fonts fixture directory under test and run one exact-autosize export in CI to catch missing FreeType early."],"tags":["gd","freetype","fonts","column-autosize","phpspreadsheet"],"backgroundTag":"gd-freetype-font-load-failure","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}