#1 Re: PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-28 15:23:54

rvk wrote:
var
  ClipRect: TPdfBox;
//...
      r := pr^;
      // inc(r.Bottom);
      // inc(r.Right);
      ClipRect.Left   := r.Left * Canvas.fDevScaleX;
      ClipRect.Top    := Canvas.fPage.GetPageHeight - (r.Top * Canvas.fDevScaleX);
      ClipRect.Width  := (r.Right - r.Left) * Canvas.fDevScaleX;
      ClipRect.Height := -(r.Bottom - r.Top) * Canvas.fDevScaleY; // Origin is bottom left so reversed
      // with Canvas.BoxI(r, false) do
      with ClipRect do
         Canvas.Rectangle(Left, Top, Width, Height);
      inc(pr);

I can confirm that this patch fixes the clipping problem. @ab could it be added to the official repository ? Would you accept a PR ? If so @rvk would you like to do it as I don't want to "steal" your code.
Thank you.

#2 Re: PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-16 08:29:43

Great! Meanwhile, I've greatly updated the EMF sample generator to produce 84 variations of valid metafiles for testing purposes. It can produce variations with different values for:
- SetWindowOrgEx (on or off)
- SetWorldTransform (including none, normal, scale, translate, rotate, shear, reflect)
- Clipping regions (on or off)

Metafiles are visible in IrfanView: RO714yu.png

Source code: https://gist.github.com/jonjbar/5e32409 … 349c66ff07

Hopefully, this could help test and enhance the SynPDF producer in the future.

#3 Re: PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-15 18:31:33

ab wrote:

AFAIR IrfanView is using the Windows GDI rendering directly.
So if it can't display anything, there is something wrong with the content.

A simple VCL app should be able to display this EMF.

You're right. I could see the result in Illustrator so I though it was good enough for a quick and dirty first test. I'll see if that can be improved.

rvk wrote:

BTW. That test project doesn't create a EMF which contains an offset WinOrg or non-standard scale, like your original code from this topic does.
So it wouldn't detect the regression for which you opened this topic lol

That was just a quick and dirty first try to produce sample EMF files for testing purposes as you said previously: "For that we need more diverse EMF files."
I believe that it would be perfectly possible to generate the WinOrg using something like this at the beginning of the process:

      // Set the window origin
      SetWindowOrgEx(MetaFileDC, XOrigin, YOrigin, nil);

#5 Re: PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-15 16:36:32

This program can be used to create EMF files with various clipping regions operations (RGN_AND, RGN_COPY, RGN_DIFF...). It could be a useful base for testing purposes:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows, SysUtils, Classes, Vcl.Graphics;

procedure CreateEMFWithClipRegion(const FileName: string; Mode: Integer);
var
  DC: HDC;
  MetaFileDC: HDC;
  MetaFile: HENHMETAFILE;
  aRect: TRect;
  RectRgn, TriangleRgn, CombinedRgn: HRGN;
  Brush: HBRUSH;
  Pen: HPEN;
  Points: array[0..2] of TPoint;
begin
  // Create a device context for the screen
  DC := GetDC(0);
  try
    // Define the bounding rectangle for the metafile
    aRect := Rect(0, 0, 300, 300);

    // Create an enhanced metafile device context
    MetaFileDC := CreateEnhMetaFile(DC, PChar(FileName), @aRect, nil);
    try
      // Draw a colored background
      Brush := CreateSolidBrush(RGB(240, 240, 240)); // Light gray background
      Pen := CreatePen(PS_SOLID, 1, RGB(240, 240, 240)); // Light gray pen
      SelectObject(MetaFileDC, Brush);
      SelectObject(MetaFileDC, Pen);
      Rectangle(MetaFileDC, aRect.Left, aRect.Top, aRect.Right, aRect.Bottom);

      // Define a rectangle clipping region in the middle
      RectRgn := CreateRectRgn(75, 75, 225, 225);

      // Define a triangle region
      Points[0] := Point(50, 250);
      Points[1] := Point(150, 50);
      Points[2] := Point(250, 250);
      TriangleRgn := CreatePolygonRgn(Points, Length(Points), WINDING);

      // Combine the rectangle region and the triangle region
      CombinedRgn := CreateRectRgn(0, 0, 0, 0); // Create an empty region
      CombineRgn(CombinedRgn, RectRgn, TriangleRgn, Mode);

      // Select the combined region with the specified mode
      ExtSelectClipRgn(MetaFileDC, CombinedRgn, RGN_COPY);

      // Draw a green rectangle
      Brush := CreateSolidBrush(RGB(0, 255, 0)); // Green brush
      Pen := CreatePen(PS_SOLID, 1, RGB(0, 255, 0)); // Green pen
      SelectObject(MetaFileDC, Brush);
      SelectObject(MetaFileDC, Pen);
      Rectangle(MetaFileDC, 30, 30, 200, 200);

      // Draw a red circle
      Brush := CreateSolidBrush(RGB(255, 0, 0)); // Red brush
      Pen := CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); // Red pen
      SelectObject(MetaFileDC, Brush);
      SelectObject(MetaFileDC, Pen);
      Ellipse(MetaFileDC, 100, 100, 270, 270);

      // Deselect the clipping region
      SelectClipRgn(MetaFileDC, 0);

      // Clean up the brush, pen, and regions
      DeleteObject(Brush);
      DeleteObject(Pen);
      DeleteObject(RectRgn);
      DeleteObject(TriangleRgn);
      DeleteObject(CombinedRgn);

    finally
      // Close the metafile and get the handle
      MetaFile := CloseEnhMetaFile(MetaFileDC);
    end;

    // Save the metafile to a file
    if MetaFile <> 0 then
    begin
      DeleteEnhMetaFile(MetaFile);
    end;
  finally
    // Release the screen device context
    ReleaseDC(0, DC);
  end;
end;


procedure TestCreateEMF;
begin
  CreateEMFWithClipRegion('C:\Tmp\_meta\Metafile_RGN_AND.emf', RGN_AND);
  CreateEMFWithClipRegion('C:\Tmp\_meta\Metafile_RGN_COPY.emf', RGN_COPY);
  CreateEMFWithClipRegion('C:\Tmp\_meta\Metafile_RGN_DIFF.emf', RGN_DIFF);
  CreateEMFWithClipRegion('C:\Tmp\_meta\Metafile_RGN_OR.emf', RGN_OR);
  CreateEMFWithClipRegion('C:\Tmp\_meta\Metafile_RGN_XOR.emf', RGN_XOR);
end;

begin
  TestCreateEMF;
end.

#6 Re: PDF Engine » Automated PDF testing » 2024-05-15 13:42:20

As a starting point, here is a Python script that I've created with the help of ChatGPT and here is what it does:
- It extracts all pages from a reference PDF and a generated PDF as PNG images
- It compares the number of pages and fail if different
- It compares each pages and for each of them, it outputs the difference as both a difference image, and a percentage
- It outputs the final result as a consistent and clear textual content for easy integration with automated tests

So I support we could create multiple small command line programs to produce PDFs using SynPDF and test most parts of the library, including MetaFiles conversion. Those programs generate the PDF in a path specified by arguments, so that they can be used to generate the reference PDFs at first (and update them if needed), and re-generate them in the correct folder during automated tests.
Then the Python script is called for each files in the reference folder and fails based on specific conditions.

Requirements: pip install PyMuPDF Pillow Wand numpy termcolor

Script:

import fitz  # PyMuPDF
from PIL import Image, ImageChops
import numpy as np
import os
import shutil
from termcolor import colored

# Function to clear the content of a folder or create it if it does not exist
def clear_folder(folder):
    if os.path.exists(folder):
        shutil.rmtree(folder)
    os.makedirs(folder)

# Function to convert PDF pages to PNG images and save them in the output folder
def convert_pdf_to_png(pdf_path, output_folder):
    clear_folder(output_folder)
    pdf_document = fitz.open(pdf_path)
    for page_num in range(len(pdf_document)):
        page = pdf_document.load_page(page_num)
        pix = page.get_pixmap()
        output_path = f"{output_folder}/page_{page_num + 1}.png"
        pix.save(output_path)
    pdf_document.close()

# Function to compare two images and save the difference image if specified
def compare_images(img1_path, img2_path, diff_img_path=None):
    img1 = Image.open(img1_path).convert('RGB')
    img2 = Image.open(img2_path).convert('RGB')

    # Check if page sizes match
    if img1.size != img2.size:
        return False, 100.0, "Error: Page sizes do not match"

    diff = ImageChops.difference(img1, img2)
    
    # Save the difference image if a path is provided
    if diff_img_path:
        diff.save(diff_img_path)

    np_diff = np.array(diff)
    diff_count = np.count_nonzero(np_diff)

    total_pixels = np_diff.size / 3  # Divide by 3 for RGB channels
    diff_percentage = (diff_count / total_pixels) * 100

    return diff_count == 0, diff_percentage, None

# Function to display the final result summary
def display_final_result_summary(all_match, total_diff_percentage, num_pages, page_results, error_message=None):
    if error_message:
        final_status = "NOT OK"
        color = 'red'
        avg_diff_percentage = 100.0
    else:
        avg_diff_percentage = total_diff_percentage / num_pages
        final_status = "OK" if all_match else "Partial"
        if any(status == "Error" for _, _, status in page_results):
            final_status = "NOT OK"
            color = 'red'
        else:
            color = 'green' if final_status == "OK" else 'yellow'

    # Output final result summary
    print("\nFinal result summary:")
    print(colored(f"Average difference percentage: {avg_diff_percentage:.2f}%", color))
    print(colored(f"Result: {final_status}", color))
    if error_message:
        print(colored(error_message, 'red'))

# Main function to handle the PDF comparison process
def main(reference_pdf, generated_pdf, output_folder):
    # Check if the reference PDF exists
    if not os.path.exists(reference_pdf):
        error_message = f"Error: Reference PDF '{reference_pdf}' not found."
        print(colored(error_message, 'red'))
        display_final_result_summary(False, 0, 0, [], error_message)
        return

    # Check if the generated PDF exists
    if not os.path.exists(generated_pdf):
        error_message = f"Error: Generated PDF '{generated_pdf}' not found."
        print(colored(error_message, 'red'))
        display_final_result_summary(False, 0, 0, [], error_message)
        return

    # Define folders for reference, generated, and difference images
    reference_folder = f"{output_folder}/reference"
    generated_folder = f"{output_folder}/generated"
    diff_folder = f"{output_folder}/differences"
    
    # Clear or create the folders
    clear_folder(reference_folder)
    clear_folder(generated_folder)
    clear_folder(diff_folder)

    # Convert PDFs to PNG images
    convert_pdf_to_png(reference_pdf, reference_folder)
    convert_pdf_to_png(generated_pdf, generated_folder)

    # Get the list of image files
    reference_files = sorted([f"{reference_folder}/{file}" for file in os.listdir(reference_folder)])
    generated_files = sorted([f"{generated_folder}/{file}" for file in os.listdir(generated_folder)])

    # Check if the number of pages (images) match
    if len(reference_files) != len(generated_files):
        error_message = "Error: PDFs have a different number of pages."
        print(colored(error_message, 'red'))
        print(f"Reference PDF has {len(reference_files)} pages.")
        print(f"Generated PDF has {len(generated_files)} pages.")
        display_final_result_summary(False, 0, 0, [], error_message)
        return

    all_match = True
    total_diff_percentage = 0
    page_results = []

    # Compare each page and collect results
    for i, (ref_img, gen_img) in enumerate(zip(reference_files, generated_files)):
        diff_img_path = f"{diff_folder}/diff_{os.path.basename(ref_img)}"
        match, diff_percentage, error = compare_images(ref_img, gen_img, diff_img_path)
        total_diff_percentage += diff_percentage

        if error:
            print(colored(f"Page {i + 1}: {error}", 'red'))
            all_match = False
            page_results.append((i + 1, diff_percentage, "Error"))
        else:
            page_status = "OK" if match else "Partial"
            page_results.append((i + 1, diff_percentage, page_status))
            if not match:
                all_match = False

    # Output page-by-page results
    print("Page-by-page differences:")
    for page_num, diff_percentage, status in page_results:
        if status == "OK":
            color = 'green'
        elif status == "Partial":
            color = 'yellow'
        else:
            color = 'red'
        print(colored(f"Page {page_num}: {diff_percentage:.2f}% difference - {status}", color))

    # Display final result summary
    display_final_result_summary(all_match, total_diff_percentage, len(reference_files), page_results)

if __name__ == "__main__":
    import sys

    # Ensure the correct number of arguments are provided
    if len(sys.argv) != 4:
        print("Usage: python script.py <reference_pdf> <generated_pdf> <output_folder>")
        sys.exit(1)

    # Get the input arguments
    reference_pdf = sys.argv[1]
    generated_pdf = sys.argv[2]
    output_folder = sys.argv[3]

    # Create the output folder if it does not exist
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    # Run the main function
    main(reference_pdf, generated_pdf, output_folder)

#7 Re: PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-15 09:05:52

Excellent work ? Both of your updates fixes the specific problem for this EMF file.
I'm even more confident that this is the correct fix because LibreOffice also fixed EMR_EXTSELECTCLIPRGN this way: https://github.com/LibreOffice/core/com … 60a101f661
See these lines: https://github.com/LibreOffice/core/blo … r.cxx#L372

@rvk Do you believe that this is good enough for a pull request ?

@ab Would you accept those changes in the main repository ?

#8 Re: PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-14 16:27:01

So I've added debug code to visualize the clipping rectangle and it looks like it is simply offset by the PDF page's margins! Could we simply subtract the margins from there ? How to get them ?
Screenshot: https://snipboard.io/MxHLvX.jpg

Test code:

procedure TPdfEnum.ExtSelectClipRgn(data: PEMRExtSelectClipRgn);
var
  RGNs: PRgnData;
  i: Integer;
  RCT: TRect;
  ClipRect: TPdfBox;
begin
  // see http://www.codeproject.com/Articles/1944/Guide-to-WIN-Regions
  if data^.iMode <> RGN_COPY then exit; // we are handling RGN_COPY (5) only..
  if not DC[nDC].ClipRgnNull then // if current clip then finish
  begin
    Canvas.GRestore;
    Canvas.NewPath;
    Canvas.fNewPath := False;
    DC[nDC].ClipRgnNull := True;
    fFillColor := -1;
  end;
  if Data^.cbRgnData > 0 then
  begin
    Canvas.GSave;
    Canvas.NewPath;
    DC[nDC].ClipRgnNull := False;
    RGNs := @Data^.RgnData;
    for i := 0 to RGNs^.rdh.nCount - 1 do
    begin
      Move(RGNs^.Buffer[i * SizeOf(TRect)], RCT, SizeOf(RCT));
      Inc(RCT.Bottom);
      Inc(RCT.Right);
      ClipRect := Canvas.BoxI(RCT, false);

      // Draw the clipping rectangle for debugging
      Canvas.SetRGBStrokeColor($55FF00FF); // Set a distinct color for the clipping rectangle
      Canvas.Rectangle(ClipRect.Left,ClipRect.Top,ClipRect.Width,ClipRect.Height);
      Canvas.Stroke; // Draw the outline of the rectangle

      // Apply the clipping path
      Canvas.NewPath;
      Canvas.Rectangle(ClipRect.Left, ClipRect.Top, ClipRect.Width, ClipRect.Height);
    end;
    Canvas.Closepath;
    Canvas.Clip;
    Canvas.NewPath;
    Canvas.FNewPath := False;
  end;
end;

#9 PDF Engine » Automated PDF testing » 2024-05-14 16:09:30

jonjbar
Replies: 3

I believe that you briefly mentioned that automated PDF testing would be a great addition in order to avoid regressions with new code. Do you have any specific idea or requirements in mind (such as being compatible with both FPC and Delphi, being cross-platform, not using external tools...) ?

I thought about this a little and here is what I believe could work:
- Create a repository of trusted source to produce PDF documents for various features of SynPDF
- Use a tool such as ImageMagick to extract each of their pages as PNG images
- Automated tests compare the newly generated PNGs with source PNGs and fail if the difference is too big

Any thoughts ? Would you accept such a contribution ?

#10 Re: PDF Engine » CreateRegion and SelectClipRgn support in PDF (EMR_EXTSELECTCLIPRGN) » 2024-05-14 14:36:20

Unfortunately, this commit introduces a new problem as described in that thread: https://synopse.info/forum/viewtopic.php?pid=41447
It includes a screenshot of the problem as well as a sample application to reproduce this.

#11 Re: PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-14 14:34:51

Thank you very much for your help.
I can confirm that this commit introduces the problem: https://github.com/synopse/mORMot2/comm … 928c8b882b
I see that is has been discussed in that thread so I'll post there: https://synopse.info/forum/viewtopic.php?pid=40358

#12 PDF Engine » Regression: simple EMF file is drawn with an overlapping/missing rect » 2024-05-14 13:42:27

jonjbar
Replies: 24

Hi,
The latest version of SynPDF2 seem to have a regression which wasn't present in SynPDF1: a part of the content is not drawn.
Screenshot: https://snipboard.io/a7T6tn.jpg
Sample project with source WMF, generate PDF and screenshot of the problem: https://we.tl/t-bLUC4A84kA
I'm using Delphi 12 in 32/64-bit mode with latest SynPDF2 from Git.
I thought I'd post it here before I open a bug on GitHub but I can do so if you wish.
Thank you for any help.

#14 PDF Engine » Support for named destinations » 2024-05-13 14:04:10

jonjbar
Replies: 2

Hi,

Named destination are useful in PDF documents as they act as bookmarks to access a specific part of the document (e.g. https://site.com/document.pdf#destination)
See: https://evermap.com/Tutorial_ABM_Destinations.asp

I see that SynPDF supports the TPdfDestination object which works fine from hyperlinks, but it looks like this doesn't create any entries in the Acrobat's "Destinations" pane. I suspect that it isn't supported ? Or perhaps I'm missing some kind of options to export them as named destinations ?

Thanks for your help.

#15 Re: PDF Engine » PDFEngine Clipping Implementation + Output stream optimizations » 2022-06-10 07:52:43

ab wrote:

My concern is that almost every time I merge some pull request in SynPdf which pleases some users, there is a regression for others...
So I usually un-merge it a few days later...

Perhaps it would make sense to investigate some kind of PDF testing tool? I suspect, as an example, that it would be possible to use Chromium to produce images out of reference PDF documents, and some kind of image comparison algorithm to compare documents generated by nightly builds with those references.
Or perhaps a similar open source tool already exists in the JavaScript / Go / .net... ecosystem?
What do you think @ab ?

#16 PDF Engine » Setting the PDFA1 property after creation can raise and exception » 2016-05-31 15:55:22

jonjbar
Replies: 0

Hello Arnaud,

After creating an encrypted (and only in that case) TPdfDocument, if the document's PDFA1 property is changed, an exception is raised when the PDF document is saved.
This doesn't happen if the document is not encrypted or if the PDFA1 property is not modified after creation.

I can provide a test project, and open a ticket if needed.

Thanks.

#17 Re: PDF Engine » Hyperlinks in PDF Pages » 2016-05-27 15:22:34

ab wrote:

You could create a new CreateExternalLink method just like TPdfDocument.CreateLink, by following the PDF reference about such external links.

Hello Arnaud,
I've written the following procedure to create external hyperlinks.
Even though I'm not a PDF expert, it looks like it is working even for complex links. Any feedback is welcome.
Hopefully this can be included as-is in SynPDF source code:

function TPDFDocument.CreateExternalLink(const ARect: TPdfRect; const anUrl: RawUTF8;
  BorderStyle: TPdfAnnotationBorder; BorderWidth: integer): TPdfDictionary;
var
  anAction: TPdfDictionary;
begin
  result := CreateAnnotation(asLink, ARect, BorderStyle, BorderWidth);
  anAction := TPdfDictionary.Create(FXRef);
  anAction.AddItem('Type', 'Action');
  anAction.AddItem('S', 'URI');
  anAction.AddItemTextUTF8('URI', anUrl);
  Result.AddItem('A', anAction);
end;

#18 Re: PDF Engine » CreateLink coordinates » 2016-05-04 08:17:56

Great!
Perhaps you should create tickets: http://synopse.info/fossil/reportlist
Those would be great additions indeed.

#19 Re: PDF Engine » CreateLink coordinates » 2016-04-28 08:26:32

From a quick overview of your screenshot, it looks like the Y is simply inverted for the link.
Perhaps the CreateLink's reference point is the bottom left of the document while the rectangle's reference is the top left ? Not sure why.

#20 Re: mORMot 1 » @mORMot.ServiceContext.Factory is nil when method is called from Serve » 2015-06-01 09:47:55

I received the following PM from "douglasmmm" regarding this thread. Unfortunately, I do not recall how this was fixed and do not have access to that test anymore. So I'm posting the message here in case somebody can help him:

douglasmmm wrote:

about you post "@mORMot.ServiceContext.Factory is nil when method is called from Serve" in Synopse forum.

you could implement the solution?
I ask because I could not understand when AB says 'is to inject the TSQLRestServer instance in the interface constructor".

grateful

#21 Re: mORMot 1 » Server Side Validation » 2015-04-08 09:28:11

IMHO any kind of clients (REST included) must be put on a leash as there are plenty of bad things they could do which they shouldn't be allowed to. From the top of my head, I can think about:
- Access resources (rows/fields) without proper permission
- Delete/Update resources without proper permission
- Send invalid data which could result in either data corruption or server crash
- Send malformed (string instead of int, data is too long...) or missing data (required field) which could lead to future problems (data analysis, report generation...)

Where it should be done is another question which should be carefully thought out:
- Invalid access permissions should be checked (at the very least) before returning data to the client. If not before accessing data in the persistence storage
- Invalid modification access should be checked before modifying the persistence storage
- Invalid formated data or missing data should be checked before modifying the persistence storage
- Invalid data resulting in server crash should be handled as soon as it is received (e.g data flood, invalid characters, invalid requests...)
- Invalid data resulting in data corruption should be handled before writing to persistence storage

Regarding table access security, this is great but not enough for most systems: row-level and even field-level security and validation should be handled from the server.
I admit I do not know mORMot enough to say that it is not possible to do so or that it should handle everything.
But as far as I can tell mORMot includes both the data persistence access and REST server with direct interactions between them so it should provide a way to interfere and add safe guards between both.

I hope you'll see those remarks as constructive, not critics wink

#22 Re: mORMot 1 » Server Side Validation » 2015-04-08 06:21:31

ab wrote:

So validation should be done on client side, before sending the data to the server.

Clients must never be trusted!

#23 Re: mORMot 1 » The future of mORMot is BigData » 2015-01-02 12:25:01

Auto-synch between servers and clients would be amazing!
This would be a potential alternative to the very popular and great Firebase recently purchased by Google: https://www.firebase.com/
Happy new year Arnaud and best wishes for you and your rodents smile

#25 Re: mORMot 1 » Custom authorization: where to start ? » 2014-11-25 11:26:19

OK Thanks. Perhaps in a future update.

#26 mORMot 1 » Custom authorization: where to start ? » 2014-11-20 15:51:14

jonjbar
Replies: 2

I'm really confused about authorization in mORMot. I'm using a TSQLHttpServer.
I understand I should use TSQLAuthUser and TSQLAuthGroup to provide per-table restrictions.
However, how to handle more complex scenarios such as for example:

* A user who created a specific TBlogArticleRecord can have CRUD right access for it while other users can only have read access on that record ?
* A user can only receive a list of the TBlogArticleRecord he has the rights to read when calling for example TBlogArticleRecord.CreateAndFillPrepare as server will filter any un-authorized records ?

Thanks for any help.

#27 Re: SyNode » Adding JavaScript support for mORMot framework » 2014-11-20 13:28:41

That's exactly what I wanted. Thank you very much mpv!
Should I take care of freeing the TSMObjects (e.g. blogObj.free) when the engine is freed or are they owned by the engine ?

#28 Re: SyNode » Adding JavaScript support for mORMot framework » 2014-11-19 16:33:47

Is it possible and how to register an object method ? I tried the following:

  Engine.RegisterMethod(Engine.GlobalObj,'blog',dummy_method,0);
  Engine.RegisterMethod(Engine.GlobalObj,'blog.article',dummy_method,0);
  Engine.RegisterMethod(Engine.GlobalObj,'blog.article.create',blog_article_create,1);

But then I get the following error:

> blog.article.create('test');  // <-- Error: blog.article is undefined

I believe both "blog" and "blog.article" should be registered as objects but I do not know how this can be done.
Any help would be greatly appreciated.

#31 mORMot 1 » @mORMot.ServiceContext.Factory is nil when method is called from Serve » 2014-11-03 17:02:09

jonjbar
Replies: 6

Hi,
I'm trying to access an interfaced based service method. It is working fine when called from the client, but when calling from the server, ServiceContext.Factory is always nil:

  aContext := @mORMot.ServiceContext;
  if Assigned(aContext.Factory) then  //  <---- Factory is nil when called from the server
  ...

I'm using this as I need to access the Rest server from that method, to do a DB.BackupBackground.
How can this be handled ? Should I not rely on ServiceContext and use a global instance of my server instead ? This won't be great as this method is shared by both client and server.

Any help would be greatly appreciated.

#32 Re: mORMot 1 » AV SpiderMonkey Mustache rendered failed » 2014-09-22 10:21:59

ab wrote:

BTW, did you try to define the method as such:

procedure JSContext.SetOptions(Value: TJSOptions);

(i.e. without the "const")

Unfortunately this still produces an exception in XE3.

#33 Re: mORMot 1 » AV SpiderMonkey Mustache rendered failed » 2014-09-18 13:17:40

I've tried multiple compilation options without any success. I've also tried disabling IDEFixPack without success.
The new code doesn't change anything either. And indeed, it looks like a wrong value is passer to the method.

So this is what I tried and it fixed the problem is:
- Make JSContext.SetOptions public
- In TSMEngine.Create call it instead of assigning to the property

Not sure how this can be explained.

#34 Re: mORMot 1 » AV SpiderMonkey Mustache rendered failed » 2014-09-18 10:20:19

mpv wrote:

Somebody REALLY need SM for XE3?

No but it's not reassuring that a specific Delphi version crashes wink
Anything we can do to try to debug this issue ?
Also, perhaps this should be prominently written somewhere to avoid people thinking either they got the wrong DLLs or the code is not working at all.

#35 Re: mORMot 1 » AV SpiderMonkey Mustache rendered failed » 2014-09-16 12:49:23

I can confirm the exception for JS_SetOptions on Delphi XE 3 sad

#36 Re: mORMot 1 » Business model and sponsored work » 2012-12-30 13:14:50

Thank you very much for taking the time to answer. I think accepting sponsored work through your company is a great idea and provides additional points for the mORMot project when used for commercial usages.

#37 mORMot 1 » Business model and sponsored work » 2012-12-27 17:03:22

jonjbar
Replies: 4

Hi,

I'm currently evaluating various options for a future rewrite of a big project and I'm really impressed with the quantity of work and dedication Arnaud Bouchez put in the mORMot framework, documentation, web-site and associated projects. Congratulation!
That being said, choosing a framework for a project not only implies making sure it is technically good, but also that is will be supported and enhanced in the long run. Being open source is obviously a great start but this is not a guarantee that this will be updated in the future (See some great TurboPower projects which are hardly maintained anymore). So I wonder what is the business model around the mORMot framework: Is there some paid support or product covering the development costs, or a company sponsoring the work on the framework or... ? OR is it a pure gift to the Delphi community out of Arnaud Bouchez' own time ?
Also, would you consider sponsored work should we need a custom feature/fix/advanced support in the future ?

Thank you for your time and great framework. I will be back on those forums as I'll spend time evaluating the framework wink

Best regards.

Board footer

Powered by FluxBB