! *viewer/watermark.pvc - Watermark Object
! By Gord Davey
! (c) Copyright 2004-2005 Sage Software Canada Ltd.
! Version:
! Source Code File: $RCSfile: watermark.pvs,v $   Version: $Revision: 1.11 $
!      Last Edited: $Date: 2005/10/14 15:31:18 $   Author: $Author: gordd $
!
! This object contains the logic to create and control watermarks
!
def class "*viewer/watermark" create OnCreate required

    property Version$ = mid(mid("$Revision: 1.11 $",12), 1, len(mid("$Revision: 1.11 $",12)) - 2)
    precision 8

    local This
    local IsWindX, IsWindX$
    local ImageWidthPixels, ImageHeightPixels
    local TextWidthPixels, TextHeightPixels
    local PageWidthPixels, PageHeightPixels
    local TextWidth, TextHeight, TextLength, DrawText$, UseFont$
    local DefaultFont$, DefaultFontSize
    local PageNumberSizing

    property Text$             set SetText ! Text for Watermark
    property TextLocation      ! 0=Centered, 1=Tiled, 2=TopLeft, 3=TopRight, 4=BottomLeft 5=BottomRight
    property Font$             set SetFont ! Font Specification for WatermarkText$ IE: "Times Roman,-168,B"

    property Color$ = Colour$  set SetColour
    property Colour$           set SetColour ! Colour to use for text
    property Rotation          set SetRotation ! Angle of Rotation for Text

    property PageNumbers       ! 1 = Use Dynamic Page Numbers, rather than Text, 0 = Use Text and Image

    property Image$            set SetImage ! Filename of an image to use as a watermark
    property ImageLocation     ! 0=Centered, 1=Tiled, 2=TopLeft, 3=TopRight, 4=BottomLeft 5=BottomRight

    function RenderWaterMark(ChannelNum%, PageNum%, PageWidth, PageHeight, DPI, \
                             MarginLeft, MarginTop, MarginRight, MarginBottom) RenderWaterMark

    function local ResolveFont(FontString$, TypeFace$, Size, Attributes$, Rotation) ResolveFont
    function local GetCenteredCoords( x, y, FontRotation ) GetCenteredCoords

fnend
!
!
OnCreate:
    This = _Obj

    enter (ParametersObject), err=*next

    if ParametersObject then \
    {   ParametersObject'AddVariable("Viewer","WaterMark","Colour","S","","","","RGB:217,217,217")
        ParametersObject'AddVariable("Viewer","WaterMark","Font","S","","","","Times Roman,-200,B")
        ParametersObject'AddVariable("Viewer","WaterMark","DefaultFont","S","","","","Courier New, -10")
        ParametersObject'AddVariable("Viewer","WaterMark","Rotation","N","0","359","","45")
        ParametersObject'AddVariable("Viewer","WaterMark","PageNumbers","B","","","","1")

        ParametersObject'GetParameters("Viewer","WaterMark")
    } else \
    {   PageNumbers = 1
        Colour$ = "RGB:217,217,217"
        Font$ = "Times Roman,-200,B"
        DefaultFont$ = "Courier New, -10"
        Rotation = 45
    }

    read data from DefaultFont$,sep="," to x$,DefaultFontSize
    if DefaultFontSize > 0 \
        then DefaultFontSize = -10

    dim PageNumberSizing [1 : 5, 1 : 3]
    ! 1 to 5 (number of page # characters)
    ! ,1 = FontSize
    ! ,2 = TextWidth
    ! ,3 = TextHeight

    x = pos("," = Font$, 1, 0)
    if x < 3 \
        then Font$ += dim(3 - x, ",")
    x = pos("," = Font$, 1, 3)
    Font$ = mid(Font$, 1, x)
    Font$ += str(Rotation)

    if tcb(88) \
        then IsWindX = 1, IsWindX$ = "[wdx]"

    return
!
!
SetImage:
    enter Image$

    ! First Deal with the image, if it happens to be an icon of some sort
    x = pos("%" = Image$, 1)
    l = len(Image$)
    x$ = ""
    if x then \
    {   for y = x + 1 to l
            if pos("0123456789":mid(Image$, y, 1), 1) \
                then x$ += mid(Image$, y, 1); z = num(x$, err=*proceed) \
                else break
        next y
        ImageWidthPixels = z
        ImageHeightPixels = z
        return Image%
    }

    x = pos("@%," : Image$, 1)
    if x \
        then ImageFile$ = Image$(1, x - 1) \
        else ImageFile$ = Image$

    call IsWindX$ + "*picture;Get_Size_Pixels",err=*proceed, ImageFile$, ImageWidthPixels, ImageHeightPixels
    ! Note, if a size cannot be figured out, then we'll create a square region, about 1/2 the size of the
    ! page and use that for the picture size.

    PageNumbers = 0
    return Image$
!
!
SetText:
    enter Text$

    TextWidth = 0
    TextHeight = 0
    PageNumbers = 0
    return Text$
!
!
SetFont:
    enter Font$

    x = pos("," = Font$, 1, 0)
    if x < 3 \
        then Font$ += dim(3 - x, ",")
    x = pos("," = Font$, 1, 3)
    Font$ = mid(Font$, 1, x)
    Font$ += str(Rotation)

    TextWidth = 0
    TextHeight = 0
    dim PageNumberSizing [1 : 5, 1 : 3]
    return Font$
!
!
SetColour:
    enter Colour$
    return Colour$
!
!
SetRotation:
    enter Rotation

    TextWidth = 0
    TextHeight = 0
    dim PageNumberSizing [1 : 5, 1 : 3]
    return Rotation
!
!
! Method: RenderWaterMark(Channel%)
! Must set Page before calling this method
RenderWaterMark:
    enter (ChannelNum%), (PageNum%), (PageWidth), (PageHeight), (DPI), (MarginLeft), (MarginTop), (MarginRight), (MarginBottom)

    x$ = pth(ChannelNum%)
    if not(pos("*PDF*" = ucs(x$), 1) or pos("*WINPRT*" = ucs(x$), 1) or pos("*BITMAP*" = ucs(x$), 1)) \
        then return 0

    if Text$ = "" and Image$ = "" and PageNumbers = 0 \
        then return 0

    if DPI <= 0 \
        then DPI = 100

    print(ChannelNum%)'black','font'(DefaultFont$),'df','lpi'(6),'cpi'(10),


    f$ = fin(ChannelNum%)

    lines = mxl(ChannelNum%) + 1
    columns = mxc(ChannelNum%) + 1

    PageWidth = PageWidth - (MarginLeft / 1000) - (MarginRight / 1000)
    PageHeight = PageHeight - (MarginTop / 1000) - (MarginBottom / 1000)

    PageWidthPixels = PageWidth * DPI
    PageHeightPixels = PageHeight * DPI

    PixelsPerColumn = PageWidthPixels / columns
    PixelsPerLine = PageHeightPixels / lines

    GUColumns = @x(columns, ChannelNum%)
    GULines = @y(lines, ChannelNum%)

    GUPerColumn = GUColumns / columns
    GUPerLine = GULines / lines

    PixelsPerGUColumn = PixelsPerColumn / GUPerColumn
    PixelsPerGULine = PixelsPerLine / GUPerLine

    if Image$ > "" \
    {
        if ImageWidthPixels = 0 or ImageHeightPixels = 0 then \
        {
            x = min( PageWidthPixels / 2, PageHeightPixels / 2 )
            IWP = x
            IHP = x
        } else \
        {   IWP = ImageWidthPixels * (DPI / 100)
            IHP = ImageHeightPixels * (DPI / 100)
        }

        ImageWidth = IWP / PixelsPerColumn
        ImageHeight = IHP / PixelsPerLine

        switch ImageLocation
            case 1 !=Tiled
                print (ChannelNum%, err=*proceed)'picture'(@x(0), \
                                                           @y(0), \
                                                           @x(columns), \
                                                           @y(lines), \
                                                           Image$,3),
                break

            case 2 !=TopLeft
                print (ChannelNum%, err=*proceed)'picture'(@x(0), \
                                                           @y(0), \
                                                           @x(ImageWidth), \
                                                           @y(Imageheight), \
                                                           Image$,4),
                break

            case 3 !=TopRight
                print (ChannelNum%, err=*proceed)'picture'(@x(columns - ImageWidth), \
                                                           @y(0), \
                                                           @x(columns), \
                                                           @y(Imageheight), \
                                                           Image$,4),
                break

            case 4 !=BottomLeft
                print (ChannelNum%, err=*proceed)'picture'(@x(0), \
                                                           @y(lines - ImageHeight), \
                                                           @x(ImageWidth), \
                                                           @y(lines), \
                                                           Image$,4),
                break

            case 5 !=BottomRight
                print (ChannelNum%, err=*proceed)'picture'(@x(columns - ImageWidth), \
                                                           @y(lines - ImageHeight), \
                                                           @x(columns), \
                                                           @y(lines), \
                                                           Image$,4),
                break

            default ! 0=Centered
                print (ChannelNum%, err=*proceed)'picture'(@x( (columns - ImageWidth) / 2 ), \
                                                           @y( (lines - ImageHeight) / 2 ), \
                                                           @x( (columns - ImageWidth) / 2 + ImageWidth ), \
                                                           @y( (lines - ImageHeight) / 2 + ImageHeight ), \
                                                           Image$,4),
                break

        esac
    }

    This'ResolveFont(Font$,FontName$,FontSize,FontAttrib$,FontRotation)
    if Rotation <> 0 \
        then FontRotation = Rotation
    FontAttrib$ = sub(FontAttrib$, "C", "")
    FontAttrib$ = sub(FontAttrib$, "R", "")

    if TextLocation > 0 \
        then FontRotation = 0

    !
    ! dim PageNumberSizing [1 : 5, 1 : 3]
    ! 1 to 5 (number of page # characters)
    ! ,1 = FontSize
    ! ,2 = TextWidth
    ! ,3 = TextHeight
    ! Load up a static list of sizing characteristics if working with dynamic page numbers
    if PageNumbers and PageNumberSizing[1, 1] = 0 then \
    {
        if not(pos("WIN"=ucs(SYS),1)) and tcb(88) then IsWindX$ = "[WDX]"
        FontFunc = new(IsWindX$ + "*viewer/fontfunctions")

        for x = 1 to 5

            r$ = FontFunc'GetFontSizeForTextToFitRectangle$(msg("TWaterMarkPageNumber", dim(x, "9")), \
                                                            FontName$, FontSize, FontAttrib$, \
                                                            FontRotation, PageWidth, PageHeight, \
                                                            DefaultFont$, DPI, 6, 10)
            read data from r$,sep="," to FontSize, TextWidth, TextHeight

            y = len(dim(x, "9"))
            PageNumberSizing[y, 1] = FontSize
            PageNumberSizing[y, 2] = TextWidth
            PageNumberSizing[y, 3] = TextHeight
        next x

        drop object FontFunc
    }

    if PageNumbers then \
    {
        DrawText$ = stp(msg("TWaterMarkPageNumber", str(PageNum%)),2)
        y = len(str(PageNum%))
        FontSize = PageNumberSizing[y, 1]
        TextWidth = PageNumberSizing[y, 2]
        TextHeight = PageNumberSizing[y, 3]
        UseFont$ = FontName$ + "," + str(FontSize) + "," + FontAttrib$ + "," + str(FontRotation)

    } else \
    {
        if DrawText$ <> Text$ or FontSize = 0 or TextWidth = 0 or TextHeight = 0 then \
        {
            if TextLocation = 1 \
                then DrawText$ = Text$ \
                else DrawText$ = stp(Text$, 2)

            TextLength = len(DrawText$)

            if not(pos("WIN"=ucs(SYS),1)) and tcb(88) then IsWindX$ = "[WDX]"
            FontFunc = new(IsWindX$ + "*viewer/fontfunctions")

            r$ = FontFunc'GetFontSizeForTextToFitRectangle$(DrawText$, \
                                                            FontName$, FontSize, FontAttrib$, \
                                                            FontRotation, PageWidth, PageHeight, \
                                                            DefaultFont$, DPI, 6, 10)
            read data from r$,sep="," to FontSize, TextWidth, TextHeight
            drop object FontFunc
            UseFont$ = FontName$ + "," + str(FontSize) + "," + FontAttrib$ + "," + str(FontRotation)
        }
    }

    if DrawText$ > "" then \
    {
        TextWidthColumns = TextWidth / GUPerColumn
        TextHeightLines = TextHeight / GUPerLine

        TextWidthPixels = TextWidth * PixelsPerGUColumn
        TextHeightPixels = TextHeight * PixelsPerGULine

        switch TextLocation
            case 1 !=Tiled
                x = 0, y = 0
                while y < lines
                        while x < columns
                        print(ChannelNum%, err=*proceed)'font'(UseFont$),'Colour'(Colour$), \
                                          'text'(@x(x),@y(y),DrawText$),
                        x += TextWidthColumns
                    wend
                    x = 0
                    y += TextHeightLines
                wend
                break

            case 2 !=TopLeft
                print(ChannelNum%, err=*proceed)'font'(UseFont$),'Colour'(Colour$), \
                                  'text'(@x(0),@y(0),DrawText$),
                break

            case 3 !=TopRight
                print(ChannelNum%, err=*proceed)'font'(UseFont$),'Colour'(Colour$), \
                                  'text'(@x(columns - TextWidthColumns),@y(0),DrawText$),
                break

            case 4 !=BottomLeft
                print(ChannelNum%, err=*proceed)'font'(UseFont$),'Colour'(Colour$), \
                                  'text'(@x(0),@y(lines - TextHeightLines),DrawText$),
                break

            case 5 !=BottomRight
                print(ChannelNum%, err=*proceed)'font'(UseFont$),'Colour'(Colour$), \
                                  'text'(@x(columns - TextWidthColumns),@y(lines - TextHeightLines),DrawText$),
                break

            default ! 0=Centered
                This'GetCenteredCoords( x, y, FontRotation )
                ! X and Y will come back in pixels
                x = x / PixelsPerColumn
                y = y / PixelsPerLine
                print(ChannelNum%, err=*proceed)'font'(UseFont$),'Colour'(Colour$), \
                                  'text'(@x(x-1),@y(y-2),DrawText$),
                break
        esac
    }


    ! Reset to a default sane value.
    print(ChannelNum%, err=*proceed)'black','font'(DefaultFont$),'df','lpi'(6),'cpi'(10),

    return 0
!
!
ResolveFont:

    enter (FontString$), TypeFace$, Size, Attrib$, Rotat

    if FontString$ = "" \
        then return 0

    read data from FontString$,sep="," to TypeFace$, Size, Attrib$, Rotat

    if Size > 0 \
        then Size = Size * DefaultFontSize

    return 0
!
!
GetCenteredCoords:
    !local TextWidthPixels, TextHeightPixels
    !local PageWidthPixels, PageHeightPixels

    enter x, y, (Angle)
    x = 0, y = 0

    Radian = 57.29577951

    HalfPageWidth = PageWidthPixels / 2
    HalfPageHeight = PageHeightPixels / 2

    HalfTextWidth = TextWidthPixels / 2
    HalfTextHeight = TextHeightPixels / 2

    Angle |= 360

    switch Angle

        case 0
            x = HalfPageWidth - HalfTextWidth
            y = HalfPageHeight - HalfTextHeight
            break

        case < 90
            x = HalfPageWidth
            y = HalfPageHeight

            hyp = HalfTextWidth ! hyp
            x -= (cos(Angle / Radian) * hyp) ! adj
            y += (sin(Angle / Radian) * hyp) ! opp

            hyp = HalfTextHeight ! hyp
            y -= (cos(Angle / Radian) * hyp) ! adj
            x -= (sin(Angle / Radian) * hyp) ! opp
            break

        case 90
            x = HalfPageWidth - HalfTextHeight
            y = HalfPageHeight + HalfTextWidth
            break

        case < 180
            x = HalfPageWidth
            y = HalfPageHeight

            hyp = HalfTextWidth
            x += (sin(Angle | 90 / Radian) * hyp) ! opp
            y += (cos(Angle | 90 / Radian) * hyp) ! adj

            hyp = HalfTextHeight
            x -= (cos(Angle | 90 / Radian) * hyp) ! adj
            y += (sin(Angle | 90 / Radian) * hyp) ! opp
            break

        case 180
            x = HalfPageWidth + HalfTextWidth
            y = HalfPageHeight + HalfTextHeight
            break

        case < 270
            x = HalfPageWidth
            y = HalfPageHeight

            hyp = HalfTextWidth
            y -= (sin(Angle | 180 / Radian) * hyp) ! opp
            x += (cos(Angle | 180 / Radian) * hyp) ! adj

            hyp = HalfTextHeight
            y += (cos(Angle | 180 / Radian) * hyp) ! adj
            x += (sin(Angle | 180 / Radian) * hyp) ! opp
            break

        case 270
            x = HalfPageWidth + HalfTextHeight
            y = HalfPageHeight - HalfTextWidth
            break

        case <360
            x = HalfPageWidth
            y = HalfPageHeight

            hyp = HalfTextWidth
            x -= (sin(Angle | 270 / Radian) * hyp) ! opp
            y -= (cos(Angle | 270 / Radian) * hyp) ! adj

            hyp = HalfTextHeight
            x += (cos(Angle | 270 / Radian) * hyp) ! adj
            y -= (sin(Angle | 270 / Radian) * hyp) ! opp
            break

    esac

    return 0
