#1 2016-04-13 23:02:47

jeanmilost
Member
Registered: 2016-01-21
Posts: 35

Compiling and using the library in c++

Hello,

I'm using the SynPdf in a c++ project. Every time I update to a new version I need to resolve some minor issues inside the generated .hpp files. As these issues are often very simple to resolve, I listed them below, and I added the way I resolve them. It would be possible to correct them once for all in the next library version?

Issue:    The library cannot be compiled if the define USE_UNISCRIBE is not declared
File:       SynPdf.pas
Solution: Change the following function as follow:

function TPdfWrite.AddGlyphs(Glyphs: PWord; GlyphsCount: integer;
  Canvas: TPdfCanvas; AVisAttrsPtr: Pointer): TPdfWrite;
var TTF: TPdfFontTrueType;
    first: boolean;
    glyph: integer;
    {$ifdef USE_UNISCRIBE}
      AVisAttrs: PScriptVisAttr;
    {$endif}
begin
  if (Glyphs<>nil) and (GlyphsCount>0) then begin
    with Canvas.FPage do
      if FFont.FTrueTypeFontsIndex=0 then
        TTF := nil else // mark we don't have an Unicode font, i.e. a TTF
        TTF := TPdfFontTrueType(FFont);
    if TTF<>nil then begin // we need a TTF font
      if (Canvas.FPage.Font<>TTF.UnicodeFont) and (TTF.UnicodeFont=nil) then
        TTF.CreateAssociatedUnicodeFont;
      Canvas.SetPDFFont(TTF.UnicodeFont,Canvas.FPage.FontSize);
      first := true;
      {$ifdef USE_UNISCRIBE}
        AVisAttrs := AVisAttrsPtr;
      {$endif}
      while GlyphsCount>0 do begin
        {$ifdef USE_UNISCRIBE}
          if (AVisAttrs=nil) or
             not(AVisAttrs^.fFlags*[fDiacritic,fZeroWidth]=[fZeroWidth]) then begin
        {$endif}
          glyph := TTF.WinAnsiFont.GetAndMarkGlyphAsUsed(Glyphs^);
          // this font shall by definition contain all needed glyphs
          // -> no Font Fallback is to be implemented here
          if first then begin
            first := false;
            Add('<');
          end;
          AddHex4(glyph);
        {$ifdef USE_UNISCRIBE}
          end;
        {$endif}
        inc(Glyphs);
        dec(GlyphsCount);
        {$ifdef USE_UNISCRIBE}
          if AVisAttrs<>nil then
            inc(AVisAttrs);
        {$endif}
      end;
      if not first then
        Add('> Tj'#10);
    end;
  end;
  result := self;
end;

Issue: The TScriptControlAttr_enum enumerator is conflicting with the VCL
File:       SynPdf
Solution: Declare the enum as follow:

  TScriptControlAttr_enum = (
    fContextDigits,
    fInvertPreBoundDir,
    fInvertPostBoundDir,
    fLinkStringBefore,
    fLinkStringAfter,
    fNeutralOverride,
    fNumericOverride,
    fLegacyBidiClass,
    pdfScr0, pdfScr1, pdfScr2, pdfScr3, pdfScr4, pdfScr5, pdfScr6, pdfScr7);

Issue:     All the properties exposed inside the TSynValidateText class result in the following error: [C++ Error] SynCommons.hpp(2091, 74): E2062 Invalid indirection, and [C++ Error] SynCommons.hpp(2091, 2): E2141 Declaration syntax error
File:        SynCommon.pas
Solution: In case the matching classes are not needed to be exposed, the following defines can be added:

{$NODEFINE TSynValidateTextProps}
{$NODEFINE TSynValidateText}
{$NODEFINE TSynValidatePassWord}

If not, all the properties of type

property MinLength: cardinal read fProps[0] write fProps[0];

should be corrected (NOTE that *$HppEmit may be used in this context)

Issue:    The classes TScriptState, TScriptAnalysis, TScriptItem and TScriptVisAttr result in the following error: [C++ Error] SynPdf.hpp(1799, 4): E2019 'TScriptState:: :: :: ()' cannot be declared in an anonymous union
File:       SynPdf.pas
Solution: In case the matching classes are not needed to be exposed, the following defines can be added:

  {$NODEFINE PScriptState}
  {$NODEFINE TScriptState}
  {$NODEFINE PScriptAnalysis}
  {$NODEFINE TScriptAnalysis}
  {$NODEFINE PScriptItem}
  {$NODEFINE TScriptItem}
  {$NODEFINE PScriptVisAttr}
  {$NODEFINE TScriptVisAttr}

otherwise need to find a way to not declare the above mentioned record members inside an anonymous union (NOTE that *$HppEmit may be used in this context)

Issue: Some declared constants are in conflict with the VCL, e.g. MWT_IDENTITY
File:   SynPdf.pas
Solution: Do not expose these constants in the hpp file using either the  {$NODEFINE MWT_IDENTITY}, or {$EXTERNALSYM MWT_IDENTITY}

Regards

Offline

#2 2016-04-14 07:06:35

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Compiling and using the library in c++

I'm afraid you were using an old version of SynPdf.
The current version in the trunk do set the $NODEFINE your propose.

I've fixed compilation when USE_UNISCRIBE conditional is not defined.
See http://synopse.info/fossil/info/2e5eea3292

Some missing fixes are included in http://synopse.info/fossil/info/178996ce2b

Hope it helps.

Thanks a lot for the detailed feedback!

Online

#3 2016-04-14 13:29:44

jeanmilost
Member
Registered: 2016-01-21
Posts: 35

Re: Compiling and using the library in c++

Hi ab,

Thanks for your reply.

These issues were in relation with the latest stable version ('1.18.1417'), available here: http://synopse.info/files/pdf/synpdf.zip. However I built the latest nighty build version ('1.18.2556'), and you're right, many of the above mentioned issues no longer exist. I apologize for the mistake.

However there remains these issues:
-> In SynPdf.pas, the TScriptControlAttr_enum enumerator is conflicting with the VCL, and I propose the following change:

TScriptControlAttr_enum = (
    fContextDigits,
    fInvertPreBoundDir,
    fInvertPostBoundDir,
    fLinkStringBefore,
    fLinkStringAfter,
    fNeutralOverride,
    fNumericOverride,
    fLegacyBidiClass,
    pdfScr0, pdfScr1, pdfScr2, pdfScr3, pdfScr4, pdfScr5, pdfScr6, pdfScr7);

-> I still cannot compile the project with the NO_USE_UNISCRIBE define activated. I propose the following change:

function TPdfWrite.AddGlyphs(Glyphs: PWord; GlyphsCount: integer;
  Canvas: TPdfCanvas; AVisAttrsPtr: Pointer): TPdfWrite;
var TTF: TPdfFontTrueType;
    first: boolean;
    glyph: integer;
    {$ifdef USE_UNISCRIBE}
      AVisAttrs: PScriptVisAttr;
    {$endif}
begin
  if (Glyphs<>nil) and (GlyphsCount>0) then begin
    with Canvas.FPage do
      if FFont.FTrueTypeFontsIndex=0 then
        TTF := nil else // mark we don't have an Unicode font, i.e. a TTF
        TTF := TPdfFontTrueType(FFont);
    if TTF<>nil then begin // we need a TTF font
      if (Canvas.FPage.Font<>TTF.UnicodeFont) and (TTF.UnicodeFont=nil) then
        TTF.CreateAssociatedUnicodeFont;
      Canvas.SetPDFFont(TTF.UnicodeFont,Canvas.FPage.FontSize);
      first := true;
      {$ifdef USE_UNISCRIBE}
        AVisAttrs := AVisAttrsPtr;
      {$endif}
      while GlyphsCount>0 do begin
        {$ifdef USE_UNISCRIBE}
          if (AVisAttrs=nil) or
             not(AVisAttrs^.fFlags*[fDiacritic,fZeroWidth]=[fZeroWidth]) then begin
        {$endif}
          glyph := TTF.WinAnsiFont.GetAndMarkGlyphAsUsed(Glyphs^);
          // this font shall by definition contain all needed glyphs
          // -> no Font Fallback is to be implemented here
          if first then begin
            first := false;
            Add('<');
          end;
          AddHex4(glyph);
        {$ifdef USE_UNISCRIBE}
          end;
        {$endif}
        inc(Glyphs);
        dec(GlyphsCount);
        {$ifdef USE_UNISCRIBE}
          if AVisAttrs<>nil then
            inc(AVisAttrs);
        {$endif}
      end;
      if not first then
        Add('> Tj'#10);
    end;
  end;
  result := self;
end;

Regards

Last edited by jeanmilost (2016-04-14 13:44:17)

Offline

#4 2016-04-14 15:56:21

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Compiling and using the library in c++

I uploaded the fixes this morning... so they are not available in the nigthly archive of last night!
wink

Wait until tomorrow morning (Paris time), or retrieve it from https://github.com/synopse/mORMot by clicking the "Download ZIP" button.

Online

#5 2016-04-14 19:41:08

jeanmilost
Member
Registered: 2016-01-21
Posts: 35

Re: Compiling and using the library in c++

Hi ab,

Great, thank you very much!

Regards

Offline

Board footer

Powered by FluxBB