eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'HTMLDocumentPainter':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: HTMLDocumentPainter


Inheritance:

   Object
   |
   +--HTMLDocumentInterpreter
      |
      +--HTMLDocumentPainter

Package:
stx:libhtml
Category:
System-Documentation
Version:
rev: 1.380 date: 2019/07/22 07:10:28
user: cg
file: HTMLDocumentPainter.st directory: libhtml
module: stx stc-classLibrary: libhtml
Author:
Claus Gittinger

Description:


This one is responsible to paint a document (a linked list
of HTMLElements) into some drawable.

The major entry points are:
    format:for:resolver:style:
            to scan the list for applets, widgets
            and preformat it.

    reformatDocument
            to reformat the document after a size change of the            
            drawable.

    displayX:y:width:height:on:
            to redraw (part of) the document.

Caveat:
    This was written at a time when machines with 4M of main memory were
    considered as ''big machines''. So the code tries hard to save memory,
    in order to be able to display big documents on such small machines reasonably fast.

    This is done by avoiding an in-memory html dom-tree, but instead reparsing the
    document for redraws, and repeating the layout computations every time we draw. 

    Of course, in order to figure out what to draw when positioning (scrolling),
    we would have to redo all calculations from the start of the document.
    (i.e. parse the whole document for every redraw).
    Which would be a stupid idea, making the thing super slow.
    Therefore, it saves so called sync-points, which contain the captured state 
    (x, y position, font, position in document etc.), after every few pages worth
    of text. So, to update any random page, it has to search for the last sync-point
    before that page, and rerender (parse) from there till the end of the visible page.

    This scheme works quite well for simple documents in those small-memory systems,
    but it is complicated, error prone, and has problems with more complex documents
    (involving style, box models, complex tables etc.). 
    So now, as we have gigabytes of memory, noone would do it that way.
    Meaning: 
        it ought to be rewritten, to implement a proper dom tree, and the drawing
        engine to implement a proper box model.

    However: 
        we are not going into the browser business here and there is no return of 
        investment if we tried.

    The HTMPainter was written for, and should only be used to display simple help texts, 
    online documentation and html tooltips.
    It will also not be enhanced and maintained, except for obvious bugs which
    break rendering the above mentioned use cases.
    
    Anyone in need for such a thing should investigate better renderers 
    (which exist - both written in Smalltalk and as plugins, 
     using common rendering engines or embedded frameworks like CEF).

[pending bugs:]
    these should be fixed, to make the documentation viewing nicer.
    - <nobr> must    collect text and determine if a break should be done at the beginning
    - <pre>...</pre> inserts an extra empty line
    - <table>        is almost useless


Related information:

    HTMLParser
    HTMLDocumentView

Class protocol:

contents
o  headerAsString: anArray depht: depth

** This is an obsolete interface - do not use it (it may vanish in future versions) **

o  headerAsString: anArray depth: depth
returns printable header assigned to array

helpers
o  fontFor: aFont onDevice: aDevice

o  romanStringFor: aNumber
aNumber >= 100 ifTrue:[

usage example(s):

^ 'C' , (self romanStringFor:aNumber - 100)

usage example(s):

^ 'L' , (self romanStringFor:aNumber - 50)

usage example(s):

^ 'X' , (self romanStringFor:aNumber - 10)

usage example(s):

^ 'V' , (self romanStringFor:aNumber - 5)

usage example(s):

^ 'I' , (self romanStringFor:aNumber - 1)

usage example(s):

     HTMLDocumentPainter new romanStringFor:110  
     HTMLDocumentPainter new romanStringFor:99  
     HTMLDocumentPainter new romanStringFor:9   
     HTMLDocumentPainter new romanStringFor:4    
     HTMLDocumentPainter new romanStringFor:5   

image specs
o  bullet1
This resource specification was automatically generated
by the ImageEditor of ST/X.

usage example(s):

     self bullet1 inspect
     ImageEditor openOnClass:self andSelector:#bullet1
     Icon flushCachedIcons

o  bullet2
This resource specification was automatically generated
by the ImageEditor of ST/X.

usage example(s):

     self bullet2 inspect
     ImageEditor openOnClass:self andSelector:#bullet2
     Icon flushCachedIcons

o  bullet3
This resource specification was automatically generated
by the ImageEditor of ST/X.

usage example(s):

     self bullet3 inspect
     ImageEditor openOnClass:self andSelector:#bullet3
     Icon flushCachedIcons

o  bullet4
This resource specification was automatically generated
by the ImageEditor of ST/X.

usage example(s):

     self bullet4 inspect
     ImageEditor openOnClass:self andSelector:#bullet4
     Icon flushCachedIcons

o  bullet5
This resource specification was automatically generated
by the ImageEditor of ST/X.

usage example(s):

     self bullet5 inspect
     ImageEditor openOnClass:self andSelector:#bullet5
     Icon flushCachedIcons

o  bullet6
This resource specification was automatically generated
by the ImageEditor of ST/X.

usage example(s):

     self bullet6 inspect
     ImageEditor openOnClass:self andSelector:#bullet6
     Icon flushCachedIcons

o  bullet7
This resource specification was automatically generated
by the ImageEditor of ST/X.

o  bullet8
This resource specification was automatically generated
by the ImageEditor of ST/X.

usage example(s):

     self bullet8 inspect
     ImageEditor openOnClass:self andSelector:#bullet8
     Icon flushCachedIcons

initialization
o  initialize
self initialize

instance creation
o  new
return an initialized instance


Instance protocol:

accessing
o  applets
return a collection of my applets

o  arrayOfHeaderIndex
returns current header index

o  forms
return a collection of my forms

o  imageResolver: somethingProvidingImagesGivenURL
Modified (format): / 29-06-2018 / 16:35:32 / Claus Gittinger

o  leftMargin

o  leftMargin: something

o  listOfHeaders
returns current list of headers

o  rightMargin

o  rightMargin: something

o  scriptObject
return my scriptObject - if any

o  topMargin

o  topMargin: something

accessing-private
o  currentBGColor

o  currentColIndex

o  currentColor

o  currentElement

o  currentFont

o  currentFontAscent

o  currentFontAvgHeight

o  currentFontHeight

o  currentForm

o  currentIndentOffset

o  currentLeftIndent

o  currentRightIndent

o  currentRowIndex

o  currentTable

o  currentUnderlineColor

o  document: aDocument

o  hBegin

o  haveSpace

o  inBLOCKQUOTE

o  inCenter

o  inDL

o  inKbd

o  inNoBreak

o  inOL

o  inPre

o  inRightAlign

o  inStrikeout

o  inSup

o  inUnderline

o  needSpace

o  previousIsEmpty

o  styleStack

o  ulLevel

o  xPosition

o  yNextLine

o  yPosition

o  yText

applets
o  createAppletFor: element
create the applet

o  defineAppletParameterFor: element
add it to its environment information

o  destroyApplet: appletElement

o  setupAppletElement: element
already present.

checking
o  checkInitialStateAtEndOfDocument
check for correct closing TAGS.
Although, most HTML viewers can handle this case, its usually an
indication of some error and often leads to badly formatted documents

o  printCheckInfoMessage: msg

contents
o  contentsAddHeader: text
assign text to header and store in list of headers

o  printContents
print contents pages

o  printContents: aList pageNumber: initialPageNumber romanPageNumbers: romanPageNumbers
print contents to destination

displaying
o  displayX: xLeft y: yTop width: w height: h on: aGC
self conditionalBreak.

o  pageBreak
(y > self pageBreakLimit and:[self atLeft and:[destination isView not]]) ifTrue:[

o  pageBreakLimit

o  redrawDocument
find a synchronization point

elements-document
o  body
destination defaultViewBackgroundColor

o  head
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  headEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  meta
already handled in parser ...

o  title
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  titleEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

elements-forms
o  anyFormElement: element

o  form
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  formEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  input
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  prescanForm: aFormElement
prescan a form, for its widgets max height.
a kludge - we need the form elements' heights BEFORE
formatting (since the text-elements have no origin knowledge,
which could be backpatched (also, we needed a way to break
MarkupText into multiple individual text items

o  prescanForms
a kludge - we need the form elements' heights BEFORE
formatting - since the text-elements have no origin knowledge,
which could be backpatched (also, we needed a way to break
MarkupText into multiple individual text items)

o  textarea
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  textareaEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

elements-lists
o  blockquote
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  blockquoteEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  dd
self conditionalBreak.

o  dir
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  dirEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  dl
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  dlEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  dt
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  li
this will ignore a followup BR or P

o  li_ol
this will ignore a followup BR or P

o  li_ul
in <ul> ... </ul> - draw a bullet

o  listTypeOfElement: anElement

o  menu
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  menuEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  ol
need to pass this info to </OL> element, for this to work

o  olEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  ul
need to pass this info to </UL> element, for this to work

usage example(s):

indent := element numericParameterFor:'INDENT' default:ULindent.

o  ulEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

elements-pseudo tags
o  internalMathFont
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  internalMathFontEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

elements-special
o  a
Transcript show:'a: '; show:needSpace; show:' '; showCR:anchorElement.

o  aEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  app
backward compatible (now obsolete) applet tag

o  appEnd
backward compatible (now obsolete) applet end-tag

o  applet
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  appletEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  area
self halt.

o  imageFor: urlString now: now

o  img
<IMG
SRC='image-url'
ALT='alternative-text'
WIDTH=w
HEIGHT=h
HSPACE=hSpc
VSPACE=vSpc
BORDER=bw
NOPRINT // deprecated
PRINT=yesOrNo // deprecated
LOWSRC='lowRes-image-url' // not implemented
STYLE='width:w; height:h'
>

o  map
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  mapEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  param
done in preparse - see #defineAppletParameterFor: ...

o  script
the script is now loaded and evaluated by the parser
(to allow it to generate the HTML text ...)
However, we need to remember it, for startup & cleanup message
sends.

o  specialMarkup
currentApplet notNil ifTrue:[

elements-structure
o  br

o  center
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  centerEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  div
w := element numericParameterFor:#'WIDTH' default:nil.

o  h1
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h1End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h2

o  h2End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h3

o  h3End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h4

o  h4End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h5

o  h5End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h6

o  h6End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h7

o  h7End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h8

o  h8End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  h9

o  h9End
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  hr
should come from a config or classVar

o  nobr
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  nobrEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  p
cg: no, a P is a P

usage example(s):

self empty.

o  pEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  pre
self atLeft ifFalse:[ self break. ].

o  preEnd
if the last element was a newLine, remove it

o  tab
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  wbr
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  xmp
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  xmpEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

elements-style
o  acronym
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  acronymEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  address
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  addressEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  b
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  bEnd
inPre ~~ 0 ifTrue:[

o  cite
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  citeEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  code
(element hasParameterFor:'FOO') ifTrue:[self halt].

usage example(s):

codeFGColor notNil ifTrue:[self setColor:codeFGColor].

o  codeEnd
self handlePendingSpaceNeed.

o  dfn
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  dfnEnd
self handlePendingSpaceNeed.

o  em
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  emEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  font
self handlePendingSpaceNeed.

o  fontEnd
inPre ~~ 0 ifTrue:[

o  i
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  iEnd
inPre ~~ 0 ifTrue:[

o  kbd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  kbdEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  s
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  sEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  samp
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  sampEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  strike
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  strikeEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  strong
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  strongEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  sub
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  subEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  sup
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  supEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  tt
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  ttEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  u
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  uEnd
self handlePendingSpaceNeed.

o  var
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  varEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

elements-tables
o  caption
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  drawTable

o  drawTableRow: row
draw one row

o  finishPreviousTableColumn
'HTML [info]: empty table row' infoPrintCR.

o  finishPreviousTableRow: final

o  table
=fontDescent

usage example(s):

allow space for tables border

o  tableEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  tbody
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  tbodyEnd
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  td
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  th
(comment from inherited method)
intentionally left blank - to be redefined by concrete class (if required)

o  th_td_common
'pass1 col: ' print. currentColIndex print. ' x:' print. col x print. ' xT:' print. col xText printCR.

o  tr
allow space for tables leftborder

elements-text
o  addText: txtIn fromElement: element
Transcript show:'T: '; show:needSpace; show:' '; showCR:txtIn.

o  privateDrawString: aString atX: xS y: yS to: xE

formatting
o  flushAnchorColors
anchors notNil ifTrue:[

o  format: docAnchor for: aGC resolver: aResolver style: aStyle
loadedAppletClasses := nil.

o  process: aDocumentAnchor
skip upto applet end

o  reformatDocument
destination width == docWidth ifTrue:[

helpers
o  atLeft

o  atOrLeftOfLeft

o  atTop

o  break

o  conditionalBreak
break line if not already at the beginning

o  conditionalEmpty
add vertical space, but only if there is not already some

o  conditionalHalfEmpty
add vertical space, but only if there is not already some

o  currentElementHasHREF

o  do_needAndNewPage
handle any NEWPAGE and NEED= attributes of the current element,
put only if painting to paper (i.e. ignore if displaying)

o  do_starOfficeStyleBefore
handle
STYLE='page-break-before: always'

o  empty

o  empty: height

o  getFontsFor: aGC

o  halfEmpty

o  handlePendingSpaceNeed

o  header: index font: aFont space: space
don't break for headers within a list

o  headerEnd

o  initialHeaderNumbers

o  needSpace: nVerticalPixel

o  relativeValueFrom: aString with: aNumericValue

initialization
o  initialize

initialization & release
o  release
sent from docView, to release stuff

o  terminateMetaCommands
sent from docView, to release stuff

meta commands
o  processMetaCommands
Transcript showCR:metaCmd , ' -> ' , metaArg.

o  refreshDocument: url

private
o  addSyncPoint

o  displayImagesOn: destinationDevice usingPlayers: players
removeLast.

o  forkImageSequencePlayerFor: entry

o  handleColorAttribute

o  handleColorChange

o  playImageSequence: entry
get device images first ..

o  processFrom: firstElement while: aBlock
process elements starting with firstElement, while aBlock
returns true. Should be called from a saveExcursion block.

o  resyncFrom: syncPoint
fetch the state found there

o  saveExcursion: aBlock
save the current state, perform aBlock and restore the state afterwards

o  saveExcursionFrom: firstElement while: testBlock
remember the current state, process elements starting with firstElement,
while testBlock returns true, finally restore the state

o  setupInitialState
setup some initial state, such as margins, indents,
colors, fonts etc.

o  startImageDisplayProcess
handle two queues in the background; the first
contains images which are to be loaded (i.e. which are
contained in the current document) and have to be
rendered for the device.
The second contains those which are to be displayed.
The displayList is always served first.

o  syncPoint
save my state in a sync point

queries
o  anchorAt: aPoint
given a (click-) point, search for and return the corresponding
anchorElement. Return nil, if there is none

o  elementAt: aPoint
given a (click-) point, search for and return the corresponding
element. Return nil, if there is none

o  elementAt: aPoint type: typeOrNil
given a (click-) point, search for and return the corresponding
element. Return nil, if there is none

o  elementsDo: aBlock
enumerate the html elements

o  elementsWithType: typeOrNil do: aBlock
enumerate the html elements

o  height

o  imageAt: aPoint
given a (click-) point, search for and return the corresponding
imageElement. Return nil, if there is none

o  positionOfAnchor: aLocalAnchor

o  width

style changes
o  currentStyle

o  defaultStyle

o  getFontParameters
extra spacing.

o  normalStyle

o  popStyle
should not happen

o  pushStyle

o  setBGColor: aColor

o  setColor: aColor

o  setFont: aFont
self halt.

o  setStyle: aStyle

o  setUnderlineColor: aColor

widget-actions
o  buttonWidgetPressed: aWidgetElement
"/ pass it to the script object - if any.

o  formResetted: aFormElement from: aWidgetElement
reset forms contents to their original values

o  formSubmitted: aFormElement from: aWidgetElement
submit-button may still have an onClick... (nil if submitted via RETURN)

o  mouseOverAnchor: anElement
pass it to the script object - if any.

widgets
o  createWidgetFor: element inForm: aForm
widget backgroundColor:(destination viewBackground).

o  destroyWidgets

o  fixupForm: aForm
fixup the form: if there is a single inputField,

o  hideAllWidgets
hide any widget

o  hideWidgets
hide any widget which became invisible

o  prescanForm: aForm atIndex: startIndex
prescan a form, for its widgets max height.
a kludge - we need the form elements' heights BEFORE
formatting (since the text-elements have no origin knowledge,
which could be backpatched (also, we needed a way to break
MarkupText into multiple individual text items

o  showWidgets
show any widget which became visible


Private classes:

    PainterState
    TextStyle
    WidgetQuery


ST/X 7.2.0.0; WebServer 1.670 at bd0aa1f87cdd.unknown:8081; Fri, 29 Sep 2023 03:51:46 GMT