canvas does not support drawing

  • Version: wPDF 2 Standard
    Downloaded: 30/4/04
    I am rolling out a survey generation system nationally to primary schools, and it is working fine - (excellent PDF generation, thank you!)
    I am using the canvas property to generate bespoke surveys based on database values, and all was fine BUT on the seventh test site, on an old Pentium II machine, I am getting the above error ("canvas does not support drawing"), followed by exceptions (which may be mine - the software seemed reliable enough not to test for all possibilities).
    All other test sites have been fine.
    Are there minimum system requirements, particulr versions of windows, system DLLs etc or am I doing something wrong?
    Many thanks
    Martin Casey

    • Offizieller Beitrag

    Hi,

    Such a problem is usually caused if you run out of resources. wPDF has been checked for resource leaks and none have been found in V2.43 (which is online since 2 weeks).

    So it is possible that there are some resource consumer in your application, maybe all forms are creatred at once - this is not recommendable on Windoes 9x.

    Julian Ziersch

  • Is it possible to be more specific about resource requirements, in terms of how hungry creating a wPDF is on memory and handles.
    All my forms apart from the app's main form and data module are created/freed on the fly.
    Could you please glance at the code segment below (Delphi - Pascal), and direct me towards any code problems?
    For example, the (approx 800K) embedded font file - does that use a correspondingly larger amount of memory than the (40K) non embedded font PDFs?

    The code I am using is as follows:
    // Some of the PDFs require unusual font: HelveticaNeue-Bold, so
    if (UsingHelveticaNeueBold) then // not likely to be on end user PC
    PDFPrinter.FontMode := wpEmbedSubsetTrueType_UsedChar
    else
    PDFPrinter.FontMode := wpUseTrueTypeFonts;

    PDFPrinter.BeginDoc;
    Res := Screen.PixelsPerInch;

    // For each page: Typically 10 - 30 pages of text, rectangles etc - plus
    // an initial rectangle the full page size to colour it appropriately

    PDFPrinter.StartPage(Round(21/2.54*res), Round(29.7/2.54*res), res,
    hCanvas := PDFPrinter.Canvas;

    // Then body of page, with lots of calls to :
    // hCanvas.TextOut
    // hCanvas.Rectangle
    // hCanvas.RoundRect

    PDFPrinter.EndPage;

    // Finally,
    PDFPrinter.EndDoc;

    • Offizieller Beitrag

    Hi,

    >>For example, the (approx 800K) embedded font file - does that use a correspondingly larger amount of memory than the (40K) non embedded font PDFs? <<

    The font will be requested from windows and then saved to the PDF file. Most of the memory will be freed then (the whole stream).
    But this is a meory problem anyway - if the 'Canvas' is not working we usually have a problem with windows GDI resource which are sparsly used by wPDF at all. It internally does most of the GDI handling on its own, such as image cropping and converting. - esspecially if you use the 'Canvas'.

    It is possible that there is a problem in the drawing code, for example SaveDC/RestoreDC can be dangerous.

    But maybe there is a threading problem - is it possible that the üprcoedure is called more than once ? Are there any Application.Processmessages.

    BTW.: It is a good idea to use a Application.Processmessages after the routine since windows needs this (or appears to) dealocate some stuff, for example file handles.

    Julian Ziersch

  • Hi, and thank you for your last prompt reply.
    I'm sure the problem is likely to be to do with resources, as you say.
    However, it crashes on the first canvas.textout procedure, even with completely stripped down code.
    I have a very simple test harness program - a form with a TWPPDFPrinter (all default properties), and a button which calls the following code:

    //=================================
    procedure TForm1.BitBtn1Click(Sender: TObject);
    var
    res : Integer;
    begin
    WPDF_Start('mycode','myserial');
    with WPPDFPrinter1 do
    begin
    FontMode := wpUseTrueTypeFonts;
    Filename := 'C:\xPDFx.pdf';
    BeginDoc;
    Res := Screen.PixelsPerInch; // returns 96
    StartPage(Round(21/2.54*res), Round(29.7/2.54*res), res, res, 0);
    Canvas.TextOut(100, 100, 'Hello PDF World.');
    // The above statement generates the exception "Canvas does not allow drawing"
    EndPage;
    EndDoc;
    end;
    end;
    //=================================

    The machine this is happening on is a PC purchased in the year 2000, with spec as follows:
    Athlon AMD 800MHz Processor
    200MHz Motherboard
    128MB SDRAM
    Windows Me Millennium Edition 4.90.3000

    The version of wPDF200A.dll is 2.4.0.7

    The Gold Master version of the product needs to be delivered to the Govt Department (DfES) next Friday (18/05/04)!
    Any suggestions?
    Regards
    Martin

    • Offizieller Beitrag

    Hi,

    The DLL actually would not make any difference - the error happens before any PDF is written.
    The Canvas of wPDF is actually a TMetafileCanvas and the metafile is send to the PDF engine in 'CloseCanvas' or 'EndPage'.
    So the error you see happens already in VCL code.

    Maybe there is a problem with the printer (or no printer). Please check if you have set the property CanvasReference to 'Screen'.

    If this does not help I can only suggest to build an example which uses a TMetafileCanvas and test it on this PC.

    meta := TMetafile.Create;
    metafilecanvas := TMetafileCanvas.Create(meta,0);
    metafilecanvas.TextOut(1,1,'Test');
    metafilecanvas.Free;
    meta.SaveToFile('c:\metatest.emf');
    meta.Free;

    Julian

  • Thanks Julian
    The metafile is created fine.
    (I can also textout to the canvas on a printer, even though there is no printer connected to the test machine, but a default printer is
    setup. The textout works, and the printer.enddoc displays then correctly displays the printer device's error dialog).

    The CanvasReference is set to the default wprefScreen.

    Additional info - thinking outloud:
    I think the problem probably only happens with Windows 98 & Me. Thinking about GDI resources, whatever RAM is avail these only have 32MB GDI heap. However, the DC for the metafile, the printer and even a paintbox I tried are all clearly allocated OK.
    SO - I still don't think this is the problem, as it is happening as soon as the first textout statement is encountered.

    So I reckon the device context of the canvas isn't valid for some other reason.

    Any ideas?
    (I'm getting very worried about delivery)
    Regards
    Martin

  • Hi Julian - Update
    I think I have found a solution - it is to do with the initialisation of the FReferenceDC variable in your WPPDFR1 unit's GetCanvas function. I tried doing a DC := Canvas.Handle and this also gave the same error. The error was generated at the
    FCanvas := TMetafileCanvas.Create(FMetafile, FReferenceDC);
    statement, so as the only difference between the GetCanvas function's TMetafileCanvas.Create and the one that worked was the FReferenceDC.
    Setting this to zero then allows canvas drawing. Ureka!

    The altered code in WPPDFR1 is shown below:

    function TWPCustomPDFExport.GetCanvas: TCanvas;
    var
    currX, currY: Integer;
    DC: HDC;
    begin
    if FCanvas = nil then
    begin
    FMetafile := TMetafile.Create;
    FMetafile.MMWidth := Round(FLastWidth / Fpage_xres * 2540); // 1/100 mm !
    FMetafile.MMHeight := Round(FLastHeight / Fpage_yres * 2540);
    FMetafile.Enhanced := TRUE;
    FCanvas := TMetafileCanvas.Create(FMetafile, 0{FReferenceDC}); // Probem here!
    FCanvas.Font.PixelsPerInch := Fpage_yres;
    FCanvas.Brush.Style := bsClear;
    DC := FCanvas.Handle;
    currX := GetDeviceCaps(DC, LOGPIXELSX);
    currY := GetDeviceCaps(DC, LOGPIXELSY);
    SetMapMode(DC, MM_ANISOTROPIC);
    SetWindowExtEx(DC, Fpage_xres, Fpage_yres, nil);
    SetViewPortExtEx(DC, currX, currY, nil);
    SetViewPortOrgEx(DC, 0, 0, nil);
    SetWindowOrgEx(DC, 0, 0, nil);
    end;
    Result := FCanvas;
    end;

    Can you please let me know the implications of changing this value - I have not tested it on multiple page documents etc.
    I would much rather have a fix that you are confident in.

    Thanks,
    Martin

    • Offizieller Beitrag

    Hi,

    Having the reference DC set to 0 is ok - please test with a demo which has a bitmap at the lower end of the page, though.

    But please rather disable this code in 'UpdateReferenceCanvas'

    else try
    ScreenDC := GetDC(0);
    FReferenceDC := CreateCompatibleDC(ScreenDC);
    finally
    ReleaseDC(0,ScreenDC);
    end;

    Please add an option to the app to set the the property CanvasReference to either of both values depending on a INI value.

    Julian