Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tc Lib Pdf Graph Laravel Package

tecnickcom/tc-lib-pdf-graph

Low-level geometric drawing and transformation primitives for PDF content streams. Compose paths, lines, curves, clipping, stroke/fill styles, gradients and shading, plus matrix transforms and coordinate helpers, with PDF/A-aware behavior.

View on GitHub
Deep Wiki
Context7

Getting Started

What you're actually adopting. This is not a PDF writer. It is the geometry layer of the TCPDF ecosystem: a class (\Com\Tecnick\Pdf\Graph\Draw) that emits raw PDF graphics operators (m, l, c, re, W n, cm, sh, f, S, …) as strings. Everything day-to-day about this package follows from that one fact — you feed it numbers, you get content-stream fragments back, and something else (usually tecnickcom/tc-lib-pdf) has to place those fragments on a page.

Install and verify the environment.

composer require tecnickcom/tc-lib-pdf-graph
php -r 'var_dump(extension_loaded("zlib"), PHP_VERSION_ID >= 80200);'

PHP 8.2+ and zlib are hard requirements. If you're on PHP 8.1 or earlier, stop here — the release line has moved past you.

Minimal bootstrap. The constructor takes the working unit scale, the page dimensions, a color factory, an encrypt service, and a PDF/A flag. All of the "PDF-ness" lives in those collaborators, not in Draw itself:

require_once __DIR__ . '/vendor/autoload.php';

$draw = new \Com\Tecnick\Pdf\Graph\Draw(
    1.0,                                   // scale factor (unit -> point conversion)
    210, 297,                              // page width/height, used for origin flipping
    new \Com\Tecnick\Color\Pdf(),          // color/colour-space resolution
    new \Com\Tecnick\Pdf\Encrypt\Encrypt(),// encryption context (may be inert)
    false                                  // PDF/A mode
);

echo $draw->getClippingRect(10, 10, 50, 20);

If that emits a q … re W n block, you understand the package.

Where to look first, in order.

  1. src/Draw.php — it is the entire public surface. Read the method list top to bottom once; it is the de facto API reference.
  2. The generated API docs at https://tcpdf.org/docs/srcdoc/tc-lib-pdf-graph — useful for signatures, useless for intent.
  3. The parent package, tecnickcom/tc-lib-pdf, for how Draw is instantiated and where its output is concatenated into page content. This is where the real usage patterns live.
  4. The test suite (Codecov badge in the README) — the fastest way to see expected output strings for each primitive.

First real use case. Choose one of these, not "generate a report":

  • A vector overlay you can't express in HTML/CSS (custom stamp, seal, watermark, registration marks).
  • A chart or diagram where you want direct control over path operators rather than rasterizing.
  • A layout engine of your own where you need path construction but not document assembly.

If your need is "put text and images on a page," use tecnickcom/tc-lib-pdf or TCPDF directly and never touch this package.

Implementation Patterns

Treat Draw as an operator generator, not a renderer. The idiomatic flow is: build a buffer of strings, wrap it in the correct graphics state, and hand it to a page/content object.

$content = '';
$content .= $draw->getClippingRect(10, 10, 50, 20);   // q ... re W n
$content .= $draw->getLine(10, 30, 60, 30);           // path operators
$content .= $draw->getStyle(...);                     // stroke/fill selection
$content .= "Q\n";                                    // pop state

Always balance the q/Q pair yourself if you injected one — clipping and transformations set inside a q block will leak into the rest of the stream otherwise. This is the single most common source of "why is my whole page clipped" bugs.

Wrap it before you spread it. Draw's API is broad and operator-flavored. Do not let getStyle() string arguments leak into controllers or Blade templates. Introduce a thin domain layer:

final class PdfCanvas
{
    public function __construct(private \Com\Tecnick\Pdf\Graph\Draw $draw) {}

    public function rect(float $x, float $y, float $w, float $h, Stroke $s): string
    {
        return $this->draw->getRect($x, $y, $w, $h)
             . $this->draw->getStyle($s->toPdfArgs());
    }
}

This pays off immediately when the package bumps minor versions (see Gotchas) or when you want to swap in a different geometry backend for tests.

Coordinate and unit discipline. Draw receives a scale and the page height. Input coordinates are interpreted in your working unit with a top-left origin, and are converted to the PDF's bottom-left origin using the page height. Concretely:

  • Pick a unit once (points, mm, or inches) and set scale to match — e.g. 72/25.4 for millimetres.
  • Pass the same page height you will ultimately render at. If you later place the fragment on a different-sized page, your vertical positions drift.
  • Keep all input math in one coordinate convention in your own code, and convert only at the Draw boundary.

Compose primitives rather than reaching for one method per shape. Most real drawings are paths: move, line/curve repeatedly, then close and paint. Build a small internal builder that accumulates path operators and applies a single style at the end; it minimizes redundant q/Q and keeps output compact (content streams are not free — zlib compresses them, but large charts still bloat).

State management for multi-element drawings. For anything with more than a handful of elements, emit q at the start of each element, set colour/line-width/transform for that element, paint, and Q. This is verbose but robust and matches how Draw's transform helpers behave. Only hand-optimize state changes once you've profiled.

Transformations. Matrix helpers are the right tool for repeated elements (tick marks, legend symbols, repeated glyph paths): define the geometry once at the origin, then re-emit under different cm matrices. Do the multiply yourself or use the provided helpers, and remember PDF matrices are applied to the coordinate system, not the object — composition order matters.

Gradients and shading need the surrounding document. Draw can emit shading operators, but the actual gradient definition lives in a PDF resource dictionary, which is the document layer's job. In practice, use gradients through tc-lib-pdf rather than hand-assembling them here; otherwise you will produce operators referencing a resource that does not exist and get a silently blank area.

Integration with tc-lib-pdf. The realistic production pattern is: let tc-lib-pdf own the page, and use Draw only when you need a primitive whose output you want to control precisely. Grab the Draw instance from the page/document object rather than constructing your own — a second instance with different scale/page-size settings will produce misaligned output that is very hard to diagnose.

Testing pattern. Snapshot the operator strings.

it('emits a balanced clipping rect', function () {
    $out = $this->draw->getClippingRect(10, 10, 50, 20);
    expect($out)->toContain(' re ')->toContain('W n');
});

Then, for integration, render to a real PDF and diff rasterized pages (pdftoppm or mutool draw) against a golden image. Operator-level assertions catch API regressions; raster diffs catch geometry regressions.

Gotchas and Tips

The constructor is not optional. You must supply a Com\Tecnick\Color\Pdf instance and something that satisfies the encrypt dependency. The encrypt object is frequently unused in unencrypted documents but still required by the signature — instantiate it and move on. Do not try to "simplify" by passing null; check Draw.php for the exact nullability of each parameter in your pinned version.

Scale and page height are a silent trap. getClippingRect(10, 10, 50, 20) looks unambiguous, but the numbers mean nothing without the constructor's scale and height. Two developers with different constructor arguments will produce different PDFs from identical code. Put the constructor parameters in config, not in scattered call sites.

This is a leaf of a monorepo, with a matching release cadence. Versions ship frequently and track tc-lib-pdf. Pin an exact minor ("tecnickcom/tc-lib-pdf-graph": "2.18.*") and upgrade deliberately. Because the public surface is broad and largely undocumented, minor bumps can change method signatures without a prose changelog entry — the release notes are compare links, nothing more.

Read the licence, not the badge. The repository metadata reports NOASSERTION, but the README and the upstream project state GNU LGPL v3. That has practical consequences: dynamic linking from proprietary code is generally fine, but you must ship the licence notice and provide the library (or a written offer) — and any modifications to the library itself stay LGPL. Get this reviewed if the PDF feature is part of a closed-source product you distribute.

Star count is misleading. 5 stars and 0 listed dependents understate reality: this package is pulled in transitively by the TCPDF stack (100M+ installs claimed by the ecosystem). Do not read the low metrics as abandonment — but do read them as "there is no community to ask." Support comes from the maintainer's sponsorship channel and the source itself.

No prose documentation exists. The API docs are generated from source. Budget time for reading Draw.php. If you find yourself guessing what a method returns, write a two-line script that echoes it and paste the result into a PDF by hand — faster than searching.

Debugging recipe. When output renders wrong:

  1. Dump the raw content stream to a file (do not go through the compressor).
  2. qpdf --qdf --object-streams=disable in.pdf out.pdf and inspect the page content.
  3. mutool draw -o page-%d.png in.pdf to rasterize.
  4. Unbalanced q/Q, a missing W n, or a stale cm will be obvious in the QDF output.

Transparency and PDF/A are conditional. The PDF/A flag toggles behaviour and, depending on the primitive, alpha and soft masks may be dropped or handled differently. If your design depends on transparency, test both true and false for the flag early — discovering the divergence after you've built a visual layer is expensive.

Performance is content-stream size, not CPU. The library is fast; the output can be large. Ten thousand individually-styled elements will produce a fat uncompressed stream. Batch path construction, reuse cm transforms for repeated elements, and let the document layer compress.

Extension points are limited by design. The class is a concrete primitive emitter; there are no interfaces to implement or events to hook. Extend by composition (your own builder around Draw), not by subclassing — that keeps you insulated from the churn described above and lets you write pure-function unit tests for your geometry logic. If you genuinely need new primitives, fork or contribute upstream: the make deps && make qa workflow plus make rpm/make deb packaging targets are documented and functional.

For system-packaged installs, the bootstrap differs (require_once '/usr/share/php/Com/Tecnick/Pdf/Graph/autoload.php'). Don't mix Composer and distro packages in the same process — you will get two Draw classes and a confusing instanceof failure.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource