News Compendium

 

Introduction

This compendium contains a collection of all technical hints published in our Newsletters since the inception of our Technical Hints series in 2018. Please note that these technical hints are not maintained and subsequent changes to our software may render them out of date and Brainy Data assumes no responsibility for their accuracy. Any use of, or actions taken based upon, any of the information contained in this compendium is done entirely at your own risk.

Contents

Technical Hints published in 2022

oWrite: $newprimeasure

The $curobjdisplay property for kWriObjTypeInfo fields

Technical Hints published in 2021

How to insert list data in an oWrite table cell (November)

New oWrite ‘not-so-basic’ basic examples (July)

Basic merge, print and export classes (July)

Technical Hints published in 2020

Undocumented oWrite constants (December)

jsSignature: pen features (July)

jsSignature: transparency with PDFDevice version 3.4.5.0

jsSignature: to trim or not to trim

OWrite: getting a list of tables in a document (April)

jsoWrite/oWrite: cross-platform document appearance (February)

Technical Hints published in 2019

OWrite: handling page setup data when using $::print (December)

JS-OWrite: changing the ruler colour (October)

PDFDevice: device appearance properties (September)

OWrite Desktop/JS-Client: $papercontinuous (September)

OWrite: the $curobjcontainer property (July)

OWrite: the $isplaintext property (July)

PDFDevice Advanced Options Window (May)

OWrite special paste (March)

PDFDevice Security (March)

JS-OWrite Asynchronicity (February)

Technical Hints published in 2018

JS Browser Caching (December)

 

Technical Hints published in 2022

oWrite: $newprimeasure

It seems that this feature has largely been ignored by developers (we know this because it wasn’t actually working for some time), so we thought we would point out its benefits, now that it is working properly. This article assumes that you will be using oWrite version 5.4.0.0 which includes an important fix and some further improvements. The purpose of this property is to overcome the device dependency of Omnis Studio screen reports.

When oWrite’s $printdpi is set to zero (recommended) or perhaps 600, to closely match some printer devices, oWrite will measure document text at a resolution that is more compatible with high resolution printers and draws text one character at a time on screen, advancing the print position of each character according to the higher resolution. This results in oWrite documents being rendered in what is called the WYSIWYG (what you see is what you get) display mode. In other words how the document is displayed on screen (regardless of screen resolution) is how it will appear on paper when printed or how it is displayed on other high resolution devices by competent renderers, such as Adobe PDF Reader. The problem is that Studio uses the device dependent method of calculating font sizes for rendering to screen and as the rendering is integer based, there is a loss of accuracy resulting in differences of text appearance between device resolutions. When oWrite prints documents to screen, it can result in words either running into each other or large gaps appearing between words as oWrite word measurements would differ to Studio measurements. OWrite has to add a continuous stream of text to the print manager as it would be a huge drain on performance and system resources to add a character at a time. Back in Studio 5.2, we arranged with Omnis Software (back then Raining Data), to add a feature to the Studio print manager that allows the positioning of text on a character basis with measurements being supplied at a resolution of 1000 DPI. Text is still added as a continuous stream of text, but this stream now also is sent with an array of additional measurements that Studio uses for rendering words one character at a time, simulating what oWrite does when it displays documents on screen.

To appreciate the problem on MS Windows, try adding some Times New Roman 8 point bold text to a report, draw a box around it, then print it both to screen and printer. You will see a substantial difference. See images below...

Studio report                         Studio screen report

    

Scan of printed output

You can see how the screen report renders the text too large and how the report class wraps the text differently.

Rendering the same text with oWrite produces identical output within oWrite documents, screen reports and on paper, as long as you turn on $newprimeasure.

Why does Studio get it wrong? Studio screen reports on windows are traditionally rendered at 96 DPI. When specifying font sizes they are specified as points (72 DPI). To render 8 point text to screen on windows, Studio has to multiply 8 by 96 and divide it by 72, which would result in a font size of 10.6666 for 96DPI screen devices, but must choose either a 10 or 11 point font to measure and render text, resulting in the text being drawn slightly larger or smaller depending on whether one rounds up or down. The longer a line of text is, the greater the inaccuracy that will accumulate.

Why does oWrite get it right? OWrite simply measures text at the font’s units per eM (UPM) when $printdpi is zero (the recommended option), which can be as large as 1000 or 2048 UPM, and scales down to the specified point size and screen DPI. To measure an 8 point font, oWrite would simply measure at the font’s UPM and scale down the measurement for each character using floating point variables. The measurement is scaled according to the intended point size and device resolution and the position for each character calculated using floating point accuracy. This at worst results in the odd character exhibiting a partial pixel inaccuracy, where two adjacent characters may slightly crowd or repel each other. On low resolution devices this may be just about noticeable, but negligible producing reasonable WYSIWYG output. On higher resolution screens (i.e. retina screens), this will provide near perfect WYSIWYG output.

Why did we choose 1000 points as the basis for the $newprimeasure? The answer is that it is the standard for providing character widths in PDF and PDF is the most common cross-platform digital document format.

The $curobjdisplay property for kWriObjTypeInfo fields

The current documentation only talks about $curobjdisplay for calculated fields, but this property is also used with info date and time fields. For these info fields it can provide alternative formatting strings for displaying the date and time. Currently, oWrite only supports MS Word style date and time formatting strings using a combination of ‘d’, ‘M’, and ‘y’ characters for date fields and a combination of ‘H’, ‘h’, ‘m’, ‘s’, ‘A’ and ‘a’ characters for time fields. For example the string ”dddd, dd MMM yyyy” displays “Thursday, 15 Dec 2022” and the string “HH:mm.s” displays the time “16:45.20”. The following is a detailed description of MS Word date and time formatting codes:

Date Codes

d     single or two digit date, i.e. ‘7’

dd     two digit date, i.e. ‘07’

ddd     abbreviated name of day, i.e. ‘Tue’

dddd     full name of day, i.e. ‘Tuesday’

M     single or two digit month, i.e. ‘1’

MM     two digit month, i.e. ‘01’

MMM     abbreviated name of month, i.e. ‘Jan’

MMMM     full name of month, i.e. ‘January’

yy     two digit year

yyyy     four digit year

 

Time Codes

H     single or two digit hour, i.e. ‘5’

HH     two digit hour, i.e. ‘05’

m     single digit minute, i.e. ‘2’

mm      two digit minute, i.e. ‘02’

s     two digit seconds

am/pm     lower case am/pm suffix, i.e. ‘am’

AM/PM     upper case am/pm suffix, i.e. ‘AM’

 

Technical Hints published in 2021

How to insert list data in an oWrite table cell (November)

We recently had a query about inserting list data in a table cell which, on the surface, would require the ability to insert a table field in the cell, i.e. nesting of tables. Unfortunately, oWrite does not support the nesting of tables. However, oWrite does support calculated fields that return simple RTF, thus one solution is to return formatted text in some kind of list form, i.e. one paragraph per line of data, and each list column separated by tabs.

For example, you can assign the following calculation to the cell’s $curobjcalc property, or optionally to a calculated field inside the cell, if the cell itself is not calculated.

     $ctask.$evalListAsRTF(LIST_NAME,"Description",0.5,"Due",3.00)

 

The parameters after the list name could specify the title and tab position in inches (or cms) for each column you wish to return (you will need to convert the measurement to twips). The list that is referenced must be contextually available from the method that assign $evalcalcs to evaluate the document.

From the above method you can return basic RTF as text such as

     {\rtf1

     \pard\tx360\tx3240\b1\tab Description\tab Due\b0\par

     \pard\tx360\tx3240\tab Item one description\tab 25 JUL 2022\par

     \pard\tx360\tx3240\tab Item two description\tab 28 JUL 2022\par

     }

which was constructed from your list data and the method parameters (assuming inches). The above RTF may produce the following output if returned for a calculated table cell.

     Description     Due

     Item one description     25 JUL 2022

     Item two description     28 JUL 2022

 

New oWrite ‘not-so-basic’ basic examples (July)

Development of the Document Manager began during the initial development of oWrite and has grown over the years to a complex library that endeavours to demonstrate most of the features supported by oWrite. Although the examples are comprehensive, due to their sheer complexity and history, the examples may not demonstrate a coherent best-method approach. It became apparent some time ago that there is a need for a new basic set of example libraries that focus on narrower aspects of oWrite so that the features in focus are not lost amongst the clatter of history and complexity.

We have completed our first in a line of new basic example libraries. This first library will focus on basic editing, data merging and the output of oWrite documents to all supported output formats. Although this library is designed around a desktop implementation, the main focus of attention is in fact a set of object classes that can equally be used in desktop or JS server implementations. This first library in the series we call OWriteBasicMergePrintExp.lbs.

Basic merge, print and export classes (July)

The example library contains two objects, oWriteMergeData and oWriteOutputDoc. These two objects do all the work in regards to merging, printing and exporting oWrite documents. The object oWriteMergeData inherits the non-visual external object .OWrite.OWriteDoc and oWriteOutputDoc inherits oWriteMergeData. This arrangement of inheritance allows oWriteMergeData to load and merge documents even when no visual editing is taking place and it allows oWriteOutputDoc to merge data prior to printing or exporting documents. A simple interface for editing a document is provided by the classes wOWriteBasic and wOWriteBasicTools. The class wEditCalcDBText implements the main interface for editing an oWrite calculated field and the remaining oSpell and PDFDevice classes are generic classes taken from the Document Manager examples to implement PDF production and spell checking.

Compartmentalising the various functions of oWrite document handling in this way allows the effective separation of interface and function, while allowing the data to drive various interface options. For example, the oWriteMergeData object class provides the pick lists for picking database table names, column names and column types when inserting and editing calculated fields. Using this information the window class wEditCalcDBText presents the user with appropriate choices and creates the appropriate Omnis calculations for data display and interaction.

We hope that this more simple set of example classes provides an easier entry into utilising the power of our oWrite plus suite of components. We will, in due course, produce a more detailed step-by-step set of instructions as technical notes that will accompany these examples.

The new example library and support files can be downloaded from

     https://demos.brainydata.com/software/owrite_basic_merge_print_exp.zip

 

 

 

Technical Hints published in 2020

Undocumented oWrite constants (December)

It has come to our attention that there are undocumented features that were implemented in the recent past. We will add these to our documentation in due course. For now, please find some details below.

We implemented the $watermark property in oWrite version 3.8.5. This property is well documented in the current documentation. However, there is also a set of watermark constants for use in the first column of the watermark list that have largely remained undocumented. These are:

Headers and footers in oWrite can contain special info objects. Traditionally these displayed basic document information such as the date, time, page count and current page number. Such info objects can be inserted using the notation
          $::insert(kWriObjTypeInfo,kWriObjTypeInfoDate)

However, we added additional types to oWrite to allow the display of page count and numbers using roman numerals, and to exclude the first page in the count. The constants that were added are as follows:

 

When we implemented the kWriSaveAsList feature in version 4, we also added a large number of constants to aid with the deciphering of the document list structure, specifically data related to document style settings. There are a huge number of constants and we will not document them here. We will merely draw your attention to their location in the Studio catalog. The additional constants are organised into these groups:

 

jsSignature: pen features (July)

Our signature control is not just about reproducing simple pen strokes as lines or curves. It offers a range of features that facilitate a more natural reproduction of a signature on a range of devices. The sharpness properties ($sigpenstartsharpness and $sigpenendsharpness) and the pen thickness property ($sigpenthickness) together with detection of the speed of the stroke help jsSignature to simulate the natural pressure variants at the beginning and at end of typical signature strokes.

These features are also useful to test and account for differences in device resolutions and accuracy of touch screens. Thus, jsSignature is so much more than just a Javascript signature control.

jsSignature: transparency with PDFDevice version 3.4.5.0

Since version 1.1, jsSignature has supported transparency and with PDFDevice being able to handle transparent PNG images, signatures can be placed over any part of a document. All you need to do is:

  1. Install PDFDevice version 3.4.5.0 or later (or version 4.0 alpha 1 or later)
  2. Set $backalpha of the signature control in your remote form to zero
  3. Ensure your report picture control uses raw PNG as the image format

jsSignature: to trim or not to trim

With the transparency feature in place, jsSignature allows the developer to overlay an entire page with the signature control, so that anywhere on the page is valid to capture the signature thus allowing the client to sign on a digital screen in as large a space as necessary in order to produce natural signature strokes. Then coupled with the trimming feature (see property $trimsignature), the signature area can be extracted and reproduced in the proper place on the document for printing (right image blow).

 

 

 

 

before trim                    after trim

    

Alternatively, reproducing the signature exactly as it was placed on top of the document text is also an option (left image above).

 

OWrite: getting a list of tables in a document (April)

OWrite table and row objects are virtual objects that do not exist as physical objects within the document content. Using $getobjslist to fetch a list of objects will only include a table’s cell objects. You can use the ID of a table cell to change the current selection and then read the table properties (any of the $curtbl... properties) to build a list of table objects in a document.

Example:

; define required columns for objs list

Do ivObjList.$define()

 

; get list of all table cell objects

Do ivOWriteRef.$getobjslist(ivObjList,kWriObjTypeTableCell)

 

; iterate through list of cells to find the tables

Do ivTableList.$define(ivTableIdent,ivTableName)

For ivObjList.$line from 1 to ivObjList.$linecount step 1

     Do ivOWriteRef.$setselection(0,0,ivObjList.Ident)

     If ivTableIdent<>ivOWriteRef.$curtblid

          Calculate ivTableIdent as ivOWriteRef.$curtblid

          Do ivTableList.$add(ivOWriteRef.$curtblid,ivOWriteRef.$curtblname)

     End If

End For

 

jsoWrite/oWrite: cross-platform document appearance (February)

We recently answered a query regarding oWrite documents appearing different on the client compared to the PDF that is produced from it. Subsequently, we decided that we needed to write an additional article on this issue.

With the development of jsoWrite, the cross-platform appearance of oWrite documents has become a major challenge. It turned out that the biggest challenge was indeed line heights. Font line heights are one of the areas where browsers do not agree between different browsers (including in some cases between different versions of the same browser) and there are also inconsistencies between browsers and OWrite server/desktop. We have never been able to find a consistent manner in which to measure font heights to make it compatible with all browsers.

However, we implemented some special features to overcome these challenges in most cases. In 2018 we did some major work on OWrite to resolve (as much as possible) the remaining issues of cross-platform appearance between macOS and winOS, while also tackling cross-browser appearance issues. Please see the release notes for case 1641 in the jsoWrite version 4.1.0 release.

Below we have summarised the points to consider during development of jsoWrite to ensure cross-platform and cross-browser compatibility as much as possible.

  1. Enable cross-platform compatibility mode:
    To enable the new cross-platform compatibility mode, set $printdpi to zero and $screendpi to 96 in the desktop visual components and desktop/server non-visual components. When creating a new jsoWrite client or oWrite desktop control or non-visual object, $printdpi should automatically default to zero.
    WARNING: in previous versions assigning zero to $printdpi would select the platform’s native resolution. This feature has changed and $printdpi must now be set to -1 so the native resolution is used. Zero is now reserved for telling OWrite to use a font’s EM design units for ultimate accuracy in measuring text.
  2. Download a fonts height list from the server for JS-Client:
    The OWrite Document Manager examples show you how to do this. Search for ivFontSizeList in rfOWriteSuper. Ignore matches in other classes (while writing these notes we realised that an identical list exists in a few other places throughout the document manager examples). To optimize jsoWrite, reduce the available fonts. We strongly recommend you use the oWrite font map feature, in conjunction with the $getfontlist feature, to limit the fonts available to the user on the client. For an example on how to use this feature, from the “*** OWrite Plus Examples ***” menu select “OWrite Examples” -> “Edit Font Map”. Clicking the more info button provides further details.
  3. Save the document on the client:
    Save the final document to be printed on the client. This will insert special information that fixes the correct page-breaks as they appeared on the client.
  4. Print the document using $::print():
    Print the document direct using the $::print() method to produce your PDF file. It may be possible to print the document via an Omnis report if $ignorepos is enabled, but we have not tested this.

When developing oWrite desktop implementations and compatibility with screen display is of more importance, please follow one of these additional instructions:

  1. Platform specific display:
    For platform specific display (72dpi on mac and 96 dpi on windows) set $printdpi to -1 and set $screendpi to kWriScrDPIDefault.
  2. Cross-platform display:
    For cross-platform display set $printdpi to 96 and set $screendpi to kWriScrDPI96.

NOTE: Fields that have instructions A) or B) applied, will no longer produce output that is compatible with jsoWrite.

 

 

Technical Hints published in 2019

OWrite: handling page setup data when using $::print (December)

There are certain settings (related to page sizes and orientation) for which OWrite provides its own properties. These properties specify how the document is presented to the user during editing and how the document is formatted during printing. When the page setup dialog is requested during printing using the $::print() method, the assumption is made the user will want to use the page size and orientation as is returned by that dialogue. Consequently, OWrite extracts this information for printing. However, the following problem may arise. The Omnis global page setup data may not be in sync with the way the user designed the OWrite document. One solution is to apply the OWrite page size and orientation to the global page setup data, prior to calling $::print(), so the dialogue presents to the user (at least initially) the page size and orientation that was intended for the document. Omnis also abstracts page sizes and orientation from the binary page setup data for which separate properties are provided and which you can manipulate individually within $root.$prefs.

However, if you are using different binary page setup data to present the user with a fixed set of choices, you may want to abstract the page size and orientation from the page setup binary data and assign them directly to the OWrite object after you have loaded the document and before you call $::print(). See example below.

 

JS-OWrite: changing the ruler colour (October)

The JS-OWrite ruler borders and fill colours are currently hard-coded to display a light blue theme. However, it is very simple to change the border style and colours by editing the files jsowrite_ruler.htm and jsowrite_vruler.htm (see folder html/owrite in the additional files download). Simply edit the canvas tag (see below before and after images) within both files.

 

PDFDevice: device appearance properties (September)

All Omnis printing devices are by default displayed within the Omnis Print Destination window. It is possible to change the appearance and/or visibility of Omnis printing devices by manipulating the device properties within the $root.$devices group. Appearance properties that can be changed are $iconid, $title and $visible.

For example, to change the display name of PDFDevice one would assign $title like so

Do $root.$devices.BrainyPDF.$title.$assign(”Nifty PDF”)

OWrite Desktop/JS-Client: $papercontinuous (September)

Using OWrite as an ad-hoc reporting tool has the advantage that once data is merged with an OWrite document template, end-users can further edit the final document. However, when using OWrite table fields with headers and/or footers to display Omnis list data, OWrite can generate appropriate headers and footers around page boundaries. These headers and footers are not live and if a user was to edit the content further, the headers and footers may become out of sync with the page boundaries for which they were intended. The answer to this problem is to turn on continuous paper if a merged document is to be edited. This will remove the page boundaries and extra headers and footers that were inserted by OWrite. When editing is complete, turning off $papercontinuous will insert new table headers and footers at the new page boundaries.

 

OWrite: the $curobjcontainer property (July)

The OWrite $curobj... properties refer to properties of the current selected OWrite document object. Document objects are Calculated Fields, Pictures, Text boxes, Headers, Footers, Tables, Table Rows and Table Cells. When text is selected inside a container object, such as a Table Cell, the $curobj... properties refer to the container object. However, if an in-line object, such as a Calculated Field, is selected inside a container object, the $curobj... properties now refer to the in-line object and not the container object, which may not be the desired effect. The solution is to set $curobjcontainer to kTrue which will tell OWrite to direct the $curobj... properties to the container object instead.

 

OWrite: the $isplaintext property (July)

The $isplaintext property can be used to track if a user has entered merely plain text or has made style related changes or pasted text other than plain text into the field.

The field can be loaded with a plain text document (see $loaddata) or should be initialised to plain text using the line

Do OWriteRef.$loaddata(””,kWriFmtText)

After initialising the field, $isplaintext should be set to kTrue, and the field is ready to track the input by the user. Any style changes or pasting rich text from other sources will result in the flag being cleared. When you come to save the data, the flag can be tested to determine how to treat the data.

 

PDFDevice Advanced Options Window (May)

It is possible to open the PDFDevice advanced options window from the Omnis print destination dialog. Selecting the ‘Print Destination’ from the Omnis file menu, selecting the Brainy Data PDF device and clicking the ‘Parameters’ tab, will reveal the ‘Advanced’ button. This button can be coded to open any window or perform any other kind of action by assigning the appropriate notation to the PDFDevice parameter kDevPdfAdvanced.

 

For example, executing the following line anywhere during startup

Do $devices.[kDevPdf].$setparam(kDevPdfAdvanced, "$root.$libs.YOUR_LIB.$windows.YOUR_WINDOW.$openonce('PDFOptions',kWindowCenter)")

will link the notation to the “Advanced...” button and when it is clicked the specified notation will be executed.

 

OWrite special paste (March)

At times it is desirable to paste content from the clipboard without any rich-text markup, i.e. converting clipboard content to plain text, thus preserving the current formatting at the insertion point. Since version 4.0 of OWrite it has been possible to drop the markup of clipboard content. Holding down the ‘alt’ key on Macintosh or the ‘ctrl’ key on Windows while picking ‘Paste’ from the edit menu, will paste clipboard content as plain text.

Another clipboard related feature is the ability to paste actual RTF source. This feature has been available for many years and has proven most helpful in tracking down problems related to rich text that had been placed on the clipboard by OWrite or other applications. RTF source can be pasted by holding down the shift-key while selecting paste from the edit menu. The RTF source is injected into the document at the current insertion point as plain text. The image to the right shows RTF source of an OWrite document that was copied to the clipboard as normal and than pasted into a new document using this feature.

 

 

 

PDFDevice Security (March)

With PDFDevice you can prevent recipients from altering or copying content from the PDF files with just a few settings. Simply specifying an owner password and setting the appropriate permissions, Recipients of your PDF documents will only have access to the PDF features that you permit. The permission settings can also be set programmatically by using the $cdevice.$setparam() method.

 

JS-OWrite Asynchronicity (February)

Many operations carried out by JS-OWrite on the client, such as saving data, are asynchronous operations. This means that when one calls $savedata(), for example, any code that follows will be executed prior to the data having been saved.

To help with the asynchronous nature of these operations, many of the client JS-OWrite methods can generate an evAsyncDone event, when the operation has been completed. The methods $savedata(), $loaddata(), $loadautosave(), $search(), $insert(), $tableaction() and $setselection() can all be called with additional parameters specifying your personal async ID and optional async data. When the action triggered by the JS-OWrite method is completed the evAsyncDone event will be generated passing to it the ID and data that you provided. 

For example: saving data for a print request has to be carried out in two distinct asynchronous operations. Calling $savedata(“Print”,“PDF”) will generate the evAsyncDone event once the data has been saved. The event parameters pAsyncId and pAsyncData will contain the parameters you provided. Once you receive the event you can print the saved data to PDF. Additional parameters that are passed by JS-OWrite to the event are pAsyncFunction, pAsyncSuccess, pAsyncResultData. Please refer to the JS-OWrite documentation for a detailed description of the evAsyncDone event and its parameters.

 

 

Technical Hints published in 2018

JS Browser Caching (December)

This article addresses the problem of Browser caching in relation to JavaScript files. While developing JS-OWrite we became aware that many browsers do not automatically refresh javascript files (even though they have changed on the server), especially when the HTML file that references them has not changed. Clicking the refresh button does not solve the problem, but clearing the cache does. However, clearing the cache is not an acceptable solution for end-users. After some research we did discover a solution (thanks to stackoverflow.com). The trick is to add a parameter to the line in the html that references the javascript file. For example

<script type="text/javascript" src="scripts/ctl_owrite.js?version=20181204”></script>

If this parameter is changed every time the script is updated, it achieves two things. Firstly, it modifies the HTML file and secondly (more importantly) it changes the ‘url’ of the javascript file so the browsers can no longer use the cached javascript files. We have tested this solution with a number of mainstream browsers. Using this trick could potentially prevent a support nightmare.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

This document was produced by OWrite and PDFDevice.     Copyright (c) 2022 Brainy Data Limited