Hello zyx,

my comments below.

On Mon, 6 Feb 2023 at 09:18, zyx <z...@gmx.us> wrote:
> From my point of view the "base" PdfPainter
> should do just what the PDF standard drawing does, to expose all those
> APIs in 1:1 manner. After that the "extensions" (or better a
> PafPainter, which derives from the PdfPanterBase - or some better name)
> can add wrapper functions, which will build on top of the base, adding
> higher level API for common operations. It felt like your
> PdfPainterExtensions aims to.

First let's clarify what PdfPainterExtensions is right now: really
it's a bunch of quarantined functions that were once in PdfPainter and
needs to be cleaned/reviewed (if it will ever happen) before being
reintegrated in PdfPainter once again. Secondly: somehow I am now
feeling intrigued by your proposal that I translate to "Let's have a
base class/interface of PdfPanter with just methods that match PDF
operators 1:1". I think it could be a very interesting idea to have
for power users, if we ensure the inherited PdfPainter will still be
easy to user for most users and performing the same validations, and
still have convenience methods like it has now (for example to draw
circles/ellipses/etc). Let me work on it on a separate branch and show
it to you what I have in mind.

> That the wrappers/contexts need to access private members of the
> PdfPainter makes me feel like not a great API design.

The usefulness of the helper classes PdfPainterPathContext and
PdfPainterTextContext is really just to conceptually separate these
functions from the others in PdfPainter because they need a
Beging()/End() semantics plus the other reasons I explained in my first
email and the friendship is in fact used only to directly call private
functions with same signature in PdfPainter through conveniently named
public member instances painter.Path and painter.Text. If we agree
that helpers class can be used to perform such conceptual separation,
and we move to use them this way, I don't think we can come up with a
design that's more friendly/convenient from the API user perspective.

> I'd still reconsider whether the subobjects and all those "AddSometing()"
> methods are needed (the 'Add' prefix of the functions feels unnecessary
> and awful to me).

I believe there must be a distinction between DrawSomething()
functions that actually perform some stroking and/or filling and just
adding to a path. If you noticed, DrawSomething() are just in PdfPainter
and AddSomething() is just in PdfPainterPathContext. This is a similar
approach from .NET Graphics[1] and GraphicsPath[2] (but the latter
don't have "prolong to" stateful methods). I think you may want to
imagine having no Draw/Add prefix at all or you imagine just the
"Draw" prefix in PdfPainter and no prefix at all in
PdfPainterPathContext. That would be more confusing to me.

> I'm missing PdfPainter::/PdfPainterPathContext::getCurrentPath(), it's
> needed for some drawing operators. Return it back, please.
>

First I explain why I removed it: I was trying to avoid double caching
the raw string stream being built. So I ask you:
- Why you need to access a raw string stream with just the content of
the path? Consider that logically the paths may stack up, even if in
the PDF content stream semantics maybe they don't do it really. This
opens further questions that I don't really want to answer;
- Later we may consider adding to the API logical paths, meaning a
class PdfGraphicsPath that has similar methods to
PdfPainterPathContext but logically contains the path being built and
that can be re-used, for example with a function
PdfPainter::DrawPath(path). In this sense it would be very similar to
NET GraphicsPath class[2]. Would this fit better your use case?
- For now, would direct access to the global string stream as a
backdoor to be configured during PdfPainter construction (eg.
"PdfPainter painter(stream);" be enough for you? I'm thinking adding
it as well as discussed this issue[3]. Or access to the interface with
all PDF operators as discussed above.

> By the way, what is the reason to repeat in the class definition that
> some code is "private:", while you already declared that the current
> declaration section is "private:"? Similarly with the "public:"
> section. Unneeded redundancy in the code, is it not?
>

It's a stylistic choice I invented to help me keeping disciplined and
organized. Few examples I separate private functions that's called
just inside the class and private functions that can be called outside
by means of friendship, or default/deleted members or inline
getters/setters. In general I like to keep a discipline in the code,
but it must be lightweight, so of course it's redundant but I believe
it's not that terrible. That's the reason I use Hungarian notation
like "m_" or "s_" prefixes for members or static variables but I don't
like full Hungarian notation itself, which it's just too
heavy/redundant.

Cheers,
Francesco

[1] https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics
[2] 
https://learn.microsoft.com/en-us/dotnet/api/system.drawing.drawing2d.graphicspath
[3] https://github.com/podofo/podofo/issues/41#issuecomment-1418281159


_______________________________________________
Podofo-users mailing list
Podofo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to