Hi,

We are currently working on a PDF-Rendering library in JavaFX and we
need to draw glyphs using the JavaFX Path API (there are multiple
reasons why we don't use the Text-Node and or Canvas).

When drawing a page full of Text this means that we have a Path-Object
with gazillions of MoveTo and CubicCurveTo elements who sum up to 30MB
just to represent them in the SG because PathElements store their
information in properties and forcefully intialize them in their
constructor.

The only public API to work around this problem is to construct a
StringBuffer and use SVGPath which means:
* it takes time to construct the SVG-Path-String
* it takes time to parse the SVG-Path-String in JavaFX

As an experiment (and because we are still on Java8 we can easily do
that) was that we created our own Shape-Subclass who:
* uses floats (there's no reason to use double in the SG when the
  backing API - Path2D - is float based)
* passes the floats directly to the Path2D/NGPath API

Guess what: We now need 2.5MB / page which means 27.5MB is the overhead
added by the current Path-API - ouch!

I think a fairly low hanging memory optimization for the PathElement
would be to create properties lazy (only if someone access the property).

For MoveTo this would mean the following minimal change (eg for the
x-value):

private DoubleProperty x;
private double _x;

public final void setX(double value) {
  if (x != null) {
     xProperty().set(value);
  } else {
     _x = value;
     u();
  }
}

public final double getX() {
  return x == null ? _x : x.get();
}

public final DoubleProperty xProperty() {
  if (x == null) {
    x = new DoublePropertyBase(_x) {

      @Override
      public void invalidated() {
        u();
      }

      @Override
      public Object getBean() {
        return MoveTo.this;
      }

      @Override
      public String getName() {
        return "x";
      }
   };
  }
  return x;
}

I guess 99% of the code out there never access the Property so the small
footprint added by the primitive field is justifiable.

This still has the overhead of all the needless PathElement objects
hanging around so another idea is to have a 3rd SG-Path-Type who
strictly uses the float-Primitives with a similar API to Path2D (in fact
it only acts as a public API to Path2D).

Thoughts?

Tom

-- 
Thomas Schindl, CTO
BestSolution.at EDV Systemhaus GmbH
Eduard-Bodem-Gasse 5-7, A-6020 Innsbruck
http://www.bestsolution.at/
Reg. Nr. FN 222302s am Firmenbuchgericht Innsbruck

Reply via email to