piet.jonas.com

WMFWriter

Home News Example Features Download Usage


 WMFViewer 

 WMF2Viewer 


 JSF FormBuilder 

How to use the WMFWriter package

Importing classes

Creating WMFs

WMFGraphics2D

WMFGraphics

Copying to the Clipboard

FAQ

Have you seen the example?


Importing classes

To use the WMFWriter package, you have to import the classes:
        import com.pietjonas.wmfwriter2d.WMF;
        import com.pietjonas.wmfwriter2d.WMFGraphics;
        import com.pietjonas.wmfwriter2d.WMFGraphics2D;
        import com.pietjonas.wmfwriter2d.ClipboardCopy;

Creating WMFs

    To create a Windows Metafile the following steps are necessary:

    1. Construct a WMF object:

         
        WMF wmf = new WMF();

    2. put something into the Metafile:
       

      • either with the help of a WMFGraphics2D object.

      • or with the help of a WMFGraphics object

      • or directly with the GDI commands provided as WMF methods:
            int pen = wmf.createPenIndirect(PS_DOT, 1, Color.red);
            wmf.selectObject(pen);
            wmf.moveTo(1, 1);
            wmf.lineTo(20, 30);
            wmf.setBKMode(WMF.OPAQUE);
            ...
            wmf.deleteObject(pen);
         
         

    3. write the Windows Metafile into a Java OuputStream:
       

      • either as Placeable Windows Metafile (necessary e.g. for MSOffice):
            wmf.writePlaceableWMF(out, dpi, 0, 0, width, height, dpi);
         

      • or as simple Windows Metafile (not recommended):
            wmf.writeWMF(out);

WMFGraphics2D

    It's easy to use the WMFGraphics2D object:

    • Construct a WMFGraphics2D object with the WMF object, you want to write at:
          WMFGraphics2D wmfg2d = new WMFGraphics2D(wmf, width, height);
       

    • Use this Graphics2D object in the paint routine to render the components content into the WMF:
          myComponent.paint(wmfg2d);
       

    • or use the Graphics objects methods directly to draw something:
          wmfg2d.setStroke(new BasicStroke(5));
          wmfg2d.drawLine(new Line2D.Float(1, 20, 5, 23));

          wmfg2d.shear(0.3, 0.2);
          wmfg2d.setPaint(new GradientPaint(15, 15, Color.red, 30, 30, Color.blue, true));
          wmfg2d.fillOval(15, 15, 40, 40);

          ...
       

    • Delete the GDI objects used by the WMFGraphics2D object:
          wmfg2d.dispose();


    You can specify how the WMF is generated:

    • Use GDI pens to draw shapes (ignoring end cap and join settings in BasicStroke):
          wmfg2d.setGDIPenDrawing(true);
          wmfg2d.setGDIPenWidthDrawing(true);
       

    • Reproduce the Java 2D settings as close as possible by using filled polygons:
          wmfg2d.setGDIPenDrawing(false);
       

    • Use GDI fonts to draw text (Improved in version 2.1):
          wmfg2d.setGDIFontDrawing(true);
       

    • Use polygons to draw text:
          wmfg2d.setGDIFontDrawing(false);
       

    • Control the number of polygons used to approach curved shapes (smaller flatness parameter leads to higher polygon count):
          wmfg2d.setFlatness(0.1);

WMFGraphics

    It's easy to use the WMFGraphics object:

    • Construct a WMFGraphics object with the WMF object, you want to write at:
          WMFGraphics wmfg = new WMFGraphics(wmf);
       

    • Use the Graphics objects methods to draw something (e.g. your standard paint routine):
          paint(wmfg);
          wmfg.drawLine(10, 10, 30, 40);
          ...
       

    • Delete the GDI objects used by the WMFGraphics object:
          wmfg.deleteGDIObjects();


    You can even use additional methods:

    • Set a new line thickness:
          wmfg.setPenWidth(2);
       

    • Set a dotted line style:
          wmfg.setPenStyle(WMF.PS_DOTS);
          wmfg.drawLine(0, 0, 50, 20);
       

    • Fill a shape with a diagonal pattern:
          wmfg.setBrushHatch(HS_FDIAGONAL);
          wmfg.setBrushFillStyle(BS_HATCHED);
          wmfg.fillRect(10, 20, 40, 40);
       

    • Fill a shape with a bitmap pattern:
          Image pattern;
          ...
          wmfg.setBrushPattern(pattern);
          wmfg.setBrushFillStyle(BS_PATTERN);
          wmfg.fillOval(10, 20, 40, 40);
       

    • Wrrite text in 45 degrees:
          wmfg.setFontEscapement(450);
          wmfg.drawString("45 degrees", 10, 10);
       

    • Reset to the default AWT behaviour:
          wmfg.reset();


    Please see the definition of the WMF class for the necessary constants.
     

Copying to the Clipboard

    To copy a Windows Metafile to the Windows clipboard the following steps are necessary:

    1. Create the WMF and store it.

    2. Create a ClipboardCopy instance:

         
        ClipboardCopy cc = new ClipboardCopy();

         

    3. Call the copy method, providing the file name of the WMF, its size and its type (WMF or EMF):

         
        Either provide the size in units of 0.01mm:
        cc.copy("WMFWriterDemo.wmf", 6000, 4000, false);

        or the size in pixel units (using the screen resolution):
        cc.copyWithPixelSize("WMFWriterDemo.wmf", 600, 400, false);

FAQ

When I draw special Unicode characters with Graphics.drawString() they don't appear in the WMF.

In WMFs characters are stored in 8bit ANSI. There is no support for Unicode. There are two solutions:

  1. Don't use the GDI font drawing mode (wmfg2d.setGDIFontDrawing(false)). Then the characters are drawn with polygons.

  2. Use a Windows font which has the special characters in the lower 8bit area (e.g. Symbol for Greek characters).

All characters drawn with polygons look very rough and low quality.

The low quality appearance stems from rounding errors because WMF supports integer coordinates only. You can improve the quality (at least for printing) by drawing your graphics scaled into the WMF.


Is WMFWriter pure Java? What about the JavaClipboard.DLL?

The WMF creation process is pure Java. That means neither WMFGraphics2D.class nor WMF.class need a DLL or any other platform specific code. The JavaClipboard.dll is only necessary to copy WMFs to the Windows clipboard. If you don't need to use that feature you don't need the DLL.




Piet Jonas