Skip to content

Instantly share code, notes, and snippets.

@erg
Created August 24, 2018 18:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erg/2b9f655c3bbc82661573cd3fd93736bb to your computer and use it in GitHub Desktop.
Save erg/2b9f655c3bbc82661573cd3fd93736bb to your computer and use it in GitHub Desktop.
factor-unmaintained
This file has been truncated, but you can view the full file.
! command
! ../factor-master/factor ../factor-master/basis/tools/directory-to-file/directory-to-file.factor .
<GIT-REPOSITORY: github.com/factor/factor-unmaintained
FILE: [[sudokus/summary.txt]] [[graphical sudoku solver]]
FILE: [[sudokus/authors.txt]] [[Sam Anklesaria
]]
FILE: [[sudokus/sudokus.factor]] [[USING: accessors arrays combinators.short-circuit grouping kernel lists
lists.lazy locals math math.functions math.parser math.ranges
models.product monads random sequences sets ui ui.gadgets.controls
ui.gadgets.layout models.combinators ui.gadgets.alerts vectors fry
ui.gadgets.labels shuffle ;
IN: sudokus
: row ( index -- row ) 1 + 9 / ceiling ;
: col ( index -- col ) 9 mod 1 + ;
: sq ( index -- square ) [ row ] [ col ] bi [ 3 / ceiling ] bi@ 2array ;
: near ( a pos -- ? ) { [ [ row ] same? ] [ [ col ] same? ] [ [ sq ] same? ] } 2|| ;
: nth-or-lower ( n seq -- elt ) [ length 1 - 2dup > [ nip ] [ drop ] if ] keep nth ;
:: solutions ( puzzle random? -- solutions )
f puzzle random? [ indices [ f ] [ random? swap nth-or-lower ] if-empty ] [ index ] if
[ :> pos
1 9 [a,b] 80 <iota> [ pos near ] filter [ puzzle nth ] map prune diff
[ 1array puzzle pos cut-slice rest surround ] map >list [ random? solutions ] bind
] [ puzzle list-monad return ] if* ;
: solution ( puzzle random? -- solution ) dupd solutions dup +nil+ = [ drop "Unsolvable" alert* ] [ nip car ] if ;
: hint ( puzzle -- puzzle' ) [ [ f swap indices random dup ] [ f solution ] bi nth ] keep swapd >vector [ set-nth ] keep ;
: create ( difficulty -- puzzle ) 81 [ f ] replicate
40 random solution [ [ f swap [ length random ] keep set-nth ] curry times ] keep ;
: do-sudoku ( -- ) [ [
[
81 [ "" ] replicate <basic> switch-models [ [ <basic> ] map 9 group [ 3 group ] map 3 group
[ [ [ <spacer> [ [ <model-field> ->% 2 [ string>number ] fmap ]
map <spacer> ] map concat ] <hbox> , ] map concat <spacer> ] map concat <product>
[ "Difficulty:" <label> , "1" <basic> <model-field> -> [ string>number 1 or 1 + 10 * ] fmap
"Generate" <model-border-btn> -> updates [ create ] fmap <spacer>
"Hint" <model-border-btn> -> "Solve" <model-border-btn> -> ] <hbox> ,
roll [ swap updates ] curry bi@
[ [ hint ] fmap ] [ [ f solution ] fmap ] bi* 3array merge [ [ [ number>string ] [ "" ] if* ] map ] fmap
] bind
] with-self , ] <vbox> { 280 220 } >>pref-dim
"Sudoku Sleuth" open-window ] with-ui ;
MAIN: do-sudoku
]]
FILE: [[random-weighted/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[random-weighted/random-weighted.factor]] [[
USING: kernel namespaces arrays quotations sequences assocs combinators
mirrors math math.vectors random macros fry ;
IN: random-weighted
: probabilities ( weights -- probabilities ) dup sum v/n ;
: layers ( probabilities -- layers )
dup length 1+ [ head ] with map rest [ sum ] map ;
: random-weighted ( weights -- elt )
probabilities layers [ 1000 * ] map 1000 random [ > ] curry find drop ;
: random-weighted* ( seq -- elt )
dup [ second ] map swap [ first ] map random-weighted swap nth ;
MACRO: call-random-weighted ( exp -- )
[ keys ] [ values <enum> >alist ] bi
'[ _ random-weighted _ case ] ;
]]
FILE: [[ui/offscreen/offscreen-docs.factor]] [[! Copyright (C) 2008 Joe Groff.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel quotations ui.gadgets
images strings ui.gadgets.worlds ;
IN: ui.offscreen
HELP: <offscreen-world>
{ $values
{ "gadget" gadget } { "title" string } { "status" "a boolean" }
{ "world" offscreen-world }
}
{ $description "Constructs an " { $link offscreen-world } " gadget with " { $snippet "gadget" } " as its only child. Generally you should use " { $link open-offscreen } " or " { $link do-offscreen } " instead of calling this word directly." } ;
HELP: close-offscreen
{ $values
{ "world" offscreen-world }
}
{ $description "Releases the resources used by the rendering buffer for " { $snippet "world" } "." } ;
HELP: do-offscreen
{ $values
{ "gadget" gadget } { "quot" quotation }
}
{ $description "Constructs an " { $link offscreen-world } " around " { $snippet "gadget" } " with " { $link open-offscreen } ", calls " { $snippet "quotation" } " with the world on the top of the stack, and cleans up the world with " { $link close-offscreen } " at the end of " { $snippet "quotation" } "." } ;
HELP: gadget>bitmap
{ $values
{ "gadget" gadget }
{ "image" image }
}
{ $description "Renders " { $snippet "gadget" } " to an " { $link offscreen-world } " and creates an " { $link image } " from its contents." } ;
HELP: offscreen-world
{ $class-description "The class of " { $link world } " objects that render to an offscreen buffer." } ;
HELP: offscreen-world>bitmap
{ $values
{ "world" offscreen-world }
{ "image" image }
}
{ $description "Saves a copy of the contents of " { $snippet "world" } " to a " { $link image } " object." } ;
HELP: open-offscreen
{ $values
{ "gadget" gadget }
{ "world" offscreen-world }
}
{ $description "Creates and sets up an " { $link offscreen-world } " with " { $snippet "gadget" } " as its only child." } ;
{ offscreen-world open-offscreen close-offscreen do-offscreen } related-words
ARTICLE: "ui.offscreen" "Offscreen UI rendering"
"The " { $vocab-link "ui.offscreen" } " provides words for rendering gadgets to an offscreen buffer so that bitmaps can be made from their contents."
{ $subsections offscreen-world }
"Opening gadgets offscreen:"
{ $subsections
open-offscreen
close-offscreen
do-offscreen
}
"Creating bitmaps from offscreen buffers:"
{ $subsections
offscreen-world>bitmap
gadget>bitmap
} ;
ABOUT: "ui.offscreen"
]]
FILE: [[ui/offscreen/summary.txt]] [[Offscreen world gadgets for rendering UI elements to bitmaps
]]
FILE: [[ui/offscreen/offscreen.factor]] [[! (c) 2008 Joe Groff, see license for details
USING: accessors alien.c-types continuations images kernel math
sequences ui.gadgets ui.gadgets.private ui.gadgets.worlds
ui.private ui ui.backend destructors locals ;
IN: ui.offscreen
TUPLE: offscreen-world < world ;
M: offscreen-world world-pixel-format-attributes
{ offscreen T{ depth-bits { value 16 } } } ;
: <offscreen-world> ( gadget title status -- world )
offscreen-world new-world ;
M: offscreen-world graft*
(open-offscreen-buffer) ;
M: offscreen-world ungraft*
[ (ungraft-world) ]
[ handle>> (close-offscreen-buffer) ]
[ reset-world ] tri ;
: open-offscreen ( gadget -- world )
"" f <offscreen-world>
[ open-world-window ] [ relayout-1 ] [ ] tri
notify-queued ;
: close-offscreen ( world -- )
ungraft notify-queued ;
:: bgrx>bitmap ( alien w h -- image )
<image>
{ w h } >>dim
alien w h * 4 * memory>byte-array >>bitmap
BGRX >>component-order ;
: offscreen-world>bitmap ( world -- image )
offscreen-pixels bgrx>bitmap ;
: do-offscreen ( gadget quot: ( offscreen-world -- ) -- )
[ open-offscreen ] dip
over [ slip ] [ close-offscreen ] [ ] cleanup ; inline
: gadget>bitmap ( gadget -- image )
[ offscreen-world>bitmap ] do-offscreen ;
]]
FILE: [[ui/offscreen/authors.txt]] [[Joe Groff
]]
FILE: [[ui/offscreen/tags.txt]] [[ui
graphics
]]
FILE: [[ui/gadgets/cartesian/cartesian.factor]] [[
USING: kernel combinators sequences opengl.gl
ui.render ui.gadgets ui.gadgets.slate
accessors ;
IN: ui.gadgets.cartesian
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: cartesian < slate x-min x-max y-min y-max z-min z-max perspective ;
: init-cartesian ( cartesian -- cartesian )
init-slate
-10 >>x-min
10 >>x-max
-10 >>y-min
10 >>y-max
-1 >>z-min
1 >>z-max ;
: <cartesian> ( -- cartesian ) cartesian new init-cartesian ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
M: cartesian establish-coordinate-system ( cartesian -- cartesian )
dup
{
[ x-min>> ] [ x-max>> ]
[ y-min>> ] [ y-max>> ]
[ z-min>> ] [ z-max>> ]
}
cleave
glOrtho ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: x-range ( cartesian range -- cartesian ) first2 [ >>x-min ] [ >>x-max ] bi* ;
: y-range ( cartesian range -- cartesian ) first2 [ >>y-min ] [ >>y-max ] bi* ;
: z-range ( cartesian range -- cartesian ) first2 [ >>z-min ] [ >>z-max ] bi* ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
]]
FILE: [[ui/gadgets/tabs/tabs.factor]] [[! Copyright (C) 2008 William Schlieper
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel fry math math.vectors sequences arrays vectors assocs
hashtables models models.range models.product combinators
ui ui.gadgets ui.gadgets.buttons ui.gadgets.frames ui.gadgets.packs
ui.gadgets.grids ui.gadgets.viewports ui.gadgets.books locals ;
IN: ui.gadgets.tabs
TUPLE: tabbed < frame names toggler content ;
DEFER: (del-page)
:: add-toggle ( n name model toggler -- )
<frame>
n name toggler parent>> '[ drop _ _ _ (del-page) ] "X" swap <bevel-button>
@right grid-add
n model name <toggle-button> @center grid-add
toggler swap add-gadget drop ;
: redo-toggler ( tabbed -- )
[ names>> ] [ model>> ] [ toggler>> ] tri
[ clear-gadget ] keep
[ [ length ] keep ] 2dip
'[ _ _ add-toggle ] 2each ;
: refresh-book ( tabbed -- )
model>> [ ] change-model ;
: (del-page) ( n name tabbed -- )
{ [ [ remove ] change-names redo-toggler ]
[ dupd [ names>> length ] [ model>> ] bi
[ [ = ] keep swap [ 1- ] when
[ < ] keep swap [ 1- ] when ] change-model ]
[ content>> nth-gadget unparent ]
[ refresh-book ]
} cleave ;
: add-page ( page name tabbed -- )
[ names>> push ] 2keep
[ [ names>> length 1 - swap ]
[ model>> ]
[ toggler>> ] tri add-toggle ]
[ content>> swap add-gadget drop ]
[ refresh-book ] tri ;
: del-page ( name tabbed -- )
[ names>> index ] 2keep (del-page) ;
: new-tabbed ( assoc class -- tabbed )
new-frame
0 <model> >>model
<pile> 1 >>fill >>toggler
dup toggler>> @left grid-add
swap
[ keys >vector >>names ]
[ values over model>> <book> >>content dup content>> @center grid-add ]
bi
dup redo-toggler ;
: <tabbed> ( assoc -- tabbed ) tabbed new-tabbed ;
]]
FILE: [[ui/gadgets/tabs/summary.txt]] [[Tabbed windows]]
FILE: [[ui/gadgets/tabs/authors.txt]] [[William Schlieper
]]
FILE: [[ui/gadgets/corners/corners.factor]] [[! Copyright (C) 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel namespaces sequences ui.gadgets.frames
ui.gadgets.grids ui.gadgets.icons ui.gadgets.theme ;
IN: ui.gadgets.corners
CONSTANT: @center { 1 1 }
CONSTANT: @left { 0 1 }
CONSTANT: @right { 2 1 }
CONSTANT: @top { 1 0 }
CONSTANT: @bottom { 1 2 }
CONSTANT: @top-left { 0 0 }
CONSTANT: @top-right { 2 0 }
CONSTANT: @bottom-left { 0 2 }
CONSTANT: @bottom-right { 2 2 }
SYMBOL: name
: corner-image ( name -- image )
[ name get "-" ] dip 3append theme-image ;
: corner-icon ( name -- icon )
corner-image <icon> ;
: /-----\ ( corner -- corner )
"top-left" corner-icon @top-left grid-add
"top-middle" corner-icon @top grid-add
"top-right" corner-icon @top-right grid-add ;
: |-----| ( gadget corner -- corner )
"left-edge" corner-icon @left grid-add
swap @center grid-add
"right-edge" corner-icon @right grid-add ;
: \-----/ ( corner -- corner )
"bottom-left" corner-icon @bottom-left grid-add
"bottom-middle" corner-icon @bottom grid-add
"bottom-right" corner-icon @bottom-right grid-add ;
: make-corners ( class name quot -- corners )
[ [ [ 3 3 ] dip new-frame { 1 1 } >>filled-cell ] dip name ] dip
with-variable ; inline
]]
FILE: [[ui/gadgets/corners/authors.txt]] [[Slava Pestov
]]
FILE: [[ui/gadgets/plot/plot.factor]] [[
USING: kernel quotations arrays sequences math math.ranges fry
opengl opengl.gl ui.render ui.gadgets.cartesian processing.shapes
accessors
help.syntax
easy-help ;
IN: ui.gadgets.plot
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ARTICLE: "ui.gadgets.plot" "Plot Gadget"
Summary:
A simple gadget for ploting two dimentional functions.
Use the arrow keys to move around.
Use 'a' and 'z' keys to zoom in and out. ..
Example:
<plot> [ sin ] add-function gadget. ..
Example:
<plot>
[ sin ] red function boa add-function
[ cos ] blue function boa add-function
gadget. ..
;
ABOUT: "ui.gadgets.plot"
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: plot < cartesian functions points ;
: init-plot ( plot -- plot )
init-cartesian
{ } >>functions
100 >>points ;
: <plot> ( -- plot ) plot new init-plot ;
: step-size ( plot -- step-size )
[ [ x-max>> ] [ x-min>> ] bi - ] [ points>> ] bi / ;
: plot-range ( plot -- range )
[ x-min>> ] [ x-max>> ] [ step-size ] tri <range> ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: function function color ;
GENERIC: plot-function ( plot object -- plot )
M: callable plot-function ( plot quotation -- plot )
[ dup plot-range ] dip '[ dup @ 2array ] map line-strip ;
M: function plot-function ( plot function -- plot )
dup color>> dup [ >stroke-color ] [ drop ] if
[ dup plot-range ] dip function>> '[ dup @ 2array ] map line-strip ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: plot-functions ( plot -- plot ) dup functions>> [ plot-function ] each ;
: draw-axis ( plot -- plot )
dup
[ [ x-min>> ] [ drop 0 ] bi 2array ]
[ [ x-max>> ] [ drop 0 ] bi 2array ] bi line*
dup
[ [ drop 0 ] [ y-min>> ] bi 2array ]
[ [ drop 0 ] [ y-max>> ] bi 2array ] bi line* ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
USING: ui.gadgets.slate ;
M: plot draw-slate ( plot -- plot )
2 glLineWidth
draw-axis
plot-functions
fill-mode
1 glLineWidth ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: add-function ( plot function -- plot )
over functions>> swap suffix >>functions ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: x-span ( plot -- span ) [ x-max>> ] [ x-min>> ] bi - ;
: y-span ( plot -- span ) [ y-max>> ] [ y-min>> ] bi - ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
USING: ui.gestures ui.gadgets ;
: left ( plot -- plot )
dup [ x-min>> ] [ x-span 1/10 * ] bi - >>x-min
dup [ x-max>> ] [ x-span 1/10 * ] bi - >>x-max
dup relayout-1 ;
: right ( plot -- plot )
dup [ x-min>> ] [ x-span 1/10 * ] bi + >>x-min
dup [ x-max>> ] [ x-span 1/10 * ] bi + >>x-max
dup relayout-1 ;
: down ( plot -- plot )
dup [ y-min>> ] [ y-span 1/10 * ] bi - >>y-min
dup [ y-max>> ] [ y-span 1/10 * ] bi - >>y-max
dup relayout-1 ;
: up ( plot -- plot )
dup [ y-min>> ] [ y-span 1/10 * ] bi + >>y-min
dup [ y-max>> ] [ y-span 1/10 * ] bi + >>y-max
dup relayout-1 ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: zoom-in-horizontal ( plot -- plot )
dup [ x-min>> ] [ x-span 1/10 * ] bi + >>x-min
dup [ x-max>> ] [ x-span 1/10 * ] bi - >>x-max ;
: zoom-in-vertical ( plot -- plot )
dup [ y-min>> ] [ y-span 1/10 * ] bi + >>y-min
dup [ y-max>> ] [ y-span 1/10 * ] bi - >>y-max ;
: zoom-in ( plot -- plot )
zoom-in-horizontal
zoom-in-vertical
dup relayout-1 ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: zoom-out-horizontal ( plot -- plot )
dup [ x-min>> ] [ x-span 1/10 * ] bi - >>x-min
dup [ x-max>> ] [ x-span 1/10 * ] bi + >>x-max ;
: zoom-out-vertical ( plot -- plot )
dup [ y-min>> ] [ y-span 1/10 * ] bi - >>y-min
dup [ y-max>> ] [ y-span 1/10 * ] bi + >>y-max ;
: zoom-out ( plot -- plot )
zoom-out-horizontal
zoom-out-vertical
dup relayout-1 ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
plot
H{
{ T{ mouse-enter } [ request-focus ] }
{ T{ key-down f f "LEFT" } [ left drop ] }
{ T{ key-down f f "RIGHT" } [ right drop ] }
{ T{ key-down f f "DOWN" } [ down drop ] }
{ T{ key-down f f "UP" } [ up drop ] }
{ T{ key-down f f "a" } [ zoom-in drop ] }
{ T{ key-down f f "z" } [ zoom-out drop ] }
}
set-gestures
]]
FILE: [[ui/gadgets/poppers/poppers.factor]] [[! Copyright (C) 2009 Sam Anklesaria
! See http://factorcode.org/license.txt for BSD license.
USING: arrays accessors combinators kernel math
models models.combinators namespaces sequences
ui.gadgets ui.gadgets.controls ui.gadgets.layout
ui.gadgets.tracks ui.gestures ui.gadgets.line-support ;
EXCLUDE: ui.gadgets.editors => model-field ;
IN: ui.gadgets.poppers
TUPLE: popped < model-field { fatal? initial: t } ;
TUPLE: popped-editor < multiline-editor ;
: <popped> ( text -- gadget ) <basic> init-field popped-editor popped (new-field) swap >>model* ;
: set-expansion ( popped size -- ) over dup parent>> [ children>> index ] [ sizes>> ] bi set-nth relayout ;
: new-popped ( popped -- ) insertion-point "" <popped>
[ rot 1 + f (track-add-at) ] keep [ relayout ] [ request-focus ] bi ;
: focus-prev ( popped -- ) dup parent>> children>> length 1 =
[ drop ] [
insertion-point [ 1 - dup -1 = [ drop 1 ] when ] [ children>> ] bi* nth
[ request-focus ] [ editor>> end-of-document ] bi
] if ;
: initial-popped ( popper -- ) "" <popped> [ f track-add drop ] keep request-focus ;
TUPLE: popper < track { unfocus-hook initial: [ drop ] } ;
! list of strings is model (make shown objects implement sequence protocol)
: <popper> ( model -- popper ) vertical popper new-track swap >>model ;
M: popped handle-gesture swap {
{ gain-focus [ 1 set-expansion f ] }
{ lose-focus [ dup parent>>
[ [ unfocus-hook>> call( a -- ) ] curry [ f set-expansion ] bi ]
[ drop ] if* f
] }
{ T{ key-up f f "RET" } [ dup editor>> delete-previous-character new-popped f ] }
{ T{ key-up f f "BACKSPACE" } [ dup editor>> editor-string "" =
[ dup fatal?>> [ [ focus-prev ] [ unparent ] bi ] [ t >>fatal? drop ] if ]
[ f >>fatal? drop ] if f
] }
[ swap call-next-method ]
} case ;
M: popper handle-gesture swap T{ button-down f f 1 } =
[ hand-click# get 2 = [ initial-popped ] [ drop ] if ] [ drop ] if f ;
M: popper model-changed
[ children>> [ unparent ] each ]
[ [ value>> [ <popped> ] map ] dip [ f track-add ] reduce request-focus ] bi ;
M: popped pref-dim* editor>> [ pref-dim* first ] [ line-height ] bi 2array ;
M: popper focusable-child* children>> [ t ] [ first ] if-empty ;
]]
FILE: [[ui/gadgets/poppers/authors.txt]] [[Sam Anklesaria
]]
FILE: [[ui/gadgets/layout/layout-docs.factor]] [[USING: help.markup help.syntax models ui.gadgets.tracks ;
IN: ui.gadgets.layout
HELP: ,
{ $values { "item" "a gadget or model" } }
{ $description "Used in a series of gadgets created by a box, accumulating the gadget" } ;
HELP: ,%
{ $syntax "gadget ,% width" }
{ $description "Like ',' but stretches the gadget to always fill a percent of the parent" } ;
HELP: ->
{ $values { "uiitem" "a gadget or model" } { "model" model } }
{ $description "Like ',' but passes its model on for further use." } ;
HELP: ->%
{ $syntax "gadget ,% width" }
{ $description "Like '->' but stretches the gadget to always fill a percent of the parent" } ;
HELP: <spacer>
{ $description "Grows to fill any empty space in a box" } ;
HELP: <hbox>
{ $values { "gadgets" "a list of gadgets" } { "track" track } }
{ $syntax "[ gadget , gadget , ... ] <hbox>" }
{ $description "Creates an horizontal track containing the gadgets listed in the quotation" } ;
HELP: <vbox>
{ $values { "gadgets" "a list of gadgets" } { "track" track } }
{ $syntax "[ gadget , gadget , ... ] <hbox>" }
{ $description "Creates an vertical track containing the gadgets listed in the quotation" } ;
HELP: $
{ $syntax "$ PLACEHOLDER-NAME $" }
{ $description "Defines an insertion point in a template named PLACEHOLDER-NAME which can be used by calling its name" } ;
HELP: with-interface
{ $values { "quot" "quotation that builds a template and inserts into it" } }
{ $description "Create templates, used with " { $link POSTPONE: $ } } ;
ARTICLE: "ui.gadgets.layout" "GUI Layout"
"Laying out GUIs works the same way as building lists with " { $vocab-link "make" }
". Gadgets are layed out using " { $vocab-link "ui.gadgets.tracks" } " through " { $link <hbox> } " and " { $link <vbox> } ", which allow both fixed and percentage widths. "
{ $link , } " and " { $link -> } " add a model or gadget to the gadget you're building. "
"Also, books can be made with " { $link <book> } ". "
{ $link <spacer> } "s add flexable space between items. " $nl
"Using " { $link with-interface } ", one can pre-build templates to add items to later: "
"Like in the StringTemplate framework for java, placeholders are defined using $ PLACERHOLDER-NAME $ "
"Using PLACEHOLDER-NAME again sets it as the current insertion point. "
"For examples using normal layout, see the " { $vocab-link "sudokus" } " demo. "
"For examples of templating, see the " { $vocab-link "recipes" } " demo." ;
ABOUT: "ui.gadgets.layout"
]]
FILE: [[ui/gadgets/layout/summary.txt]] [[Syntax for easily building GUIs and using templates]]
FILE: [[ui/gadgets/layout/layout.factor]] [[USING: accessors assocs arrays fry kernel lexer make math.parser
models monads namespaces parser sequences
sequences.extras models.combinators ui.gadgets
ui.gadgets.tracks words ui.gadgets.controls ;
QUALIFIED: make
QUALIFIED-WITH: ui.gadgets.books book
IN: ui.gadgets.layout
SYMBOL: templates
TUPLE: layout gadget size ; C: <layout> layout
TUPLE: placeholder < gadget members ;
: <placeholder> ( -- placeholder ) placeholder new V{ } clone >>members ;
: (remove-members) ( placeholder members -- ) [ [ model? ] filter swap parent>> model>> [ remove-connection ] curry each ]
[ nip [ gadget? ] filter [ unparent ] each ] 2bi ;
: remove-members ( placeholder -- ) dup members>> [ drop ] [ [ (remove-members) ] keep delete-all ] if-empty ;
: add-member ( obj placeholder -- ) over layout? [ [ gadget>> ] dip ] when members>> push ;
: , ( item -- ) make:, ;
: make* ( quot -- list ) { } make ; inline
! Just take the previous mentioned placeholder and use it
! If there is no previously mentioned placeholder, we're probably making a box, and will create the placeholder ourselves
DEFER: with-interface
: insertion-quot ( quot -- quot' )
make:building get [ [ placeholder? ] find-last nip [ <placeholder> dup , ] unless*
[ templates get ] 2dip swap '[ [ _ templates set _ , @ ] with-interface ] ] when* ;
SYNTAX: ,% scan string>number [ <layout> , ] curry append! ;
SYNTAX: ->% scan string>number '[ [ _ <layout> , ] [ output-model ] bi ] append! ;
GENERIC: -> ( uiitem -- model )
M: gadget -> dup , output-model ;
M: model -> dup , ;
: <spacer> ( -- ) <gadget> 1 <layout> , ;
: add-layout ( track layout -- track ) [ gadget>> ] [ size>> ] bi track-add ;
: layouts ( sized? gadgets -- layouts ) [ [ gadget? ] [ layout? ] bi or ] filter swap
[ [ dup layout? [ f <layout> ] unless ] map ]
[ [ dup gadget? [ gadget>> ] unless ] map ] if ;
: make-layout ( building sized? -- models layouts ) [ swap layouts ] curry
[ make* [ [ model? ] filter ] ] dip bi ; inline
: <box> ( gadgets type -- track )
[ t make-layout ] dip <track>
swap [ add-layout ] each
swap [ <collection> >>model ] unless-empty ; inline
: <hbox> ( gadgets -- track ) horizontal <box> ; inline
: <vbox> ( gadgets -- track ) vertical <box> ; inline
: make-book ( models gadgets model -- book ) book:<book> swap [ "No models in books" throw ] unless-empty ;
: <book> ( quot: ( -- model ) -- book ) f make-layout rot 0 >>value make-book ; inline
: <book*> ( quot -- book ) f make-layout f make-book ; inline
ERROR: not-in-template word ;
SYNTAX: $ scan-new-word dup
[ [ dup templates get at [ nip , ] [ not-in-template ] if* ] curry ( -- ) define-declared "$" expect ]
[ [ <placeholder> [ swap templates get set-at ] keep , ] curry ] bi append! ;
: insert-gadget ( number parent gadget -- ) -rot [ but-last insert-nth ] change-children drop ;
: insert-size ( number parent size -- ) -rot [ but-last insert-nth ] change-sizes drop ;
: insertion-point ( placeholder -- number parent ) dup parent>> [ children>> index ] keep ;
GENERIC: >layout ( gadget -- layout )
M: gadget >layout f <layout> ;
M: layout >layout ;
GENERIC#: (add-gadget-at) 2 ( parent item n -- )
M: gadget (add-gadget-at) -rot [ add-gadget ] keep insert-gadget ;
M: track (add-gadget-at) -rot >layout [ add-layout ] keep [ gadget>> insert-gadget ] [ size>> insert-size ] 3bi ;
GENERIC#: add-gadget-at 1 ( item location -- )
M: object add-gadget-at insertion-point -rot (add-gadget-at) ;
M: model add-gadget-at parent>> dup book:book? [ "No models in books" throw ]
[ dup model>> dup collection? [ nip swap add-connection ] [ drop [ 1array <collection> ] dip model<< ] if ] if ;
: track-add-at ( item location size -- ) swap [ <layout> ] dip add-gadget-at ;
: (track-add-at) ( parent item n size -- ) swap [ <layout> ] dip (add-gadget-at) ;
: insert-item ( item location -- ) [ dup get [ drop ] [ remove-members ] if ] [ on ] [ ] tri
[ add-member ] 2keep add-gadget-at ;
: insert-items ( makelist -- ) t swap [ dup placeholder? [ nip ] [ over insert-item ] if ] each drop ;
: with-interface ( quot -- ) [ make* ] curry H{ } clone templates rot with-variable [ insert-items ] with-scope ; inline
M: model >>= [ swap insertion-quot <action> ] curry ;
M: model fmap insertion-quot <mapped> ;
M: model $> insertion-quot side-effect-model new-mapped-model ;
M: model <$ insertion-quot quot-model new-mapped-model ;
]]
FILE: [[ui/gadgets/layout/authors.txt]] [[Sam Anklesaria
]]
FILE: [[ui/gadgets/alerts/alerts.factor]] [[USING: accessors models monads macros generalizations kernel
ui ui.gadgets.controls models.combinators ui.gadgets.layout ui.gadgets
ui.gadgets.labels ui.gadgets.editors ui.gadgets.buttons
ui.gadgets.packs locals sequences fonts io.styles
wrap.strings ;
IN: ui.gadgets.alerts
:: alert ( quot string -- ) <pile> { 10 10 } >>gap 1 >>align
string 22 wrap-lines <label> T{ font { name "sans-serif" } { size 18 } } >>font { 200 100 } >>pref-dim add-gadget
"okay" [ close-window ] quot append <border-button> add-gadget "" open-window ;
: alert* ( str -- ) [ ] swap alert ;
:: ask-user ( string -- model' )
[
string <label> T{ font { name "sans-serif" } { size 14 } } >>font dup , :> lbl
<model-field*> ->% 1 :> fldm
"okay" <model-border-btn> :> btn
btn -> [ fldm swap updates ]
[ [ drop lbl close-window ] $> , ] bi
] <vbox> { 161 86 } >>pref-dim "" open-window ;
MACRO: ask-buttons ( buttons -- quot ) dup length [
[ swap
[ 22 wrap-lines <label> T{ font { name "sans-serif" } { size 18 } } >>font ,
[ [ <model-border-btn> [ close-window ] >>hook -> ] map ] <hbox> , ] <vbox>
"" open-window
] dip firstn
] 2curry ;
]]
FILE: [[ui/gadgets/alerts/summary.txt]] [[Really simple dialog boxes]]
FILE: [[ui/gadgets/alerts/authors.txt]] [[Sam Anklesaria
]]
FILE: [[ui/gadgets/controls/controls.factor]] [[USING: accessors assocs arrays kernel models monads sequences
models.combinators ui.gadgets ui.gadgets.borders ui.gadgets.buttons
ui.gadgets.buttons.private ui.gadgets.editors ui.gadgets.editors.private
words images.loader ui.gadgets.scrollers ui.images vocabs.parser lexer
models.range ui.gadgets.sliders ;
QUALIFIED-WITH: ui.gadgets.sliders slider
QUALIFIED-WITH: ui.gadgets.tables tbl
EXCLUDE: ui.gadgets.editors => model-field ;
IN: ui.gadgets.controls
TUPLE: model-btn < button hook value ;
: <model-btn> ( gadget -- button ) [
[ dup hook>> [ call( button -- ) ] [ drop ] if* ]
[ [ [ value>> ] [ ] bi or ] keep set-control-value ]
[ model>> f swap value<< ] tri
] model-btn new-button f <basic> >>model ;
: <model-border-btn> ( text -- button ) <model-btn> border-button-theme ;
TUPLE: table < tbl:table { quot initial: [ ] } { val-quot initial: [ ] } color-quot column-titles column-alignment actions ;
M: table tbl:column-titles column-titles>> ;
M: table tbl:column-alignment column-alignment>> ;
M: table tbl:row-columns quot>> [ call( a -- b ) ] [ drop f ] if* ;
M: table tbl:row-value val-quot>> [ call( a -- b ) ] [ drop f ] if* ;
M: table tbl:row-color color-quot>> [ call( a -- b ) ] [ drop f ] if* ;
: new-table ( model class -- table ) f swap tbl:new-table dup >>renderer
f <basic> >>actions dup actions>> [ set-model ] curry >>action ;
: <table> ( model -- table ) table new-table ;
: <table*> ( -- table ) V{ } clone <model> <table> ;
: <list> ( column-model -- table ) <table> [ 1array ] >>quot ;
: <list*> ( -- table ) V{ } clone <model> <list> ;
: indexed ( table -- table ) f >>val-quot ;
TUPLE: model-field < field model* ;
: init-field ( model -- model' ) [ [ ] [ "" ] if* ] change-value ;
: <model-field> ( model -- gadget ) model-field new-field swap init-field >>model* ;
M: model-field graft*
[ [ model*>> value>> ] [ editor>> ] bi set-editor-string ]
[ dup editor>> model>> add-connection ]
[ dup model*>> add-connection ] tri ;
M: model-field ungraft*
[ dup editor>> model>> remove-connection ]
[ dup model*>> remove-connection ] bi ;
M: model-field model-changed 2dup model*>> =
[ [ value>> ] [ editor>> ] bi* set-editor-string ]
[ nip [ editor>> editor-string ] [ model*>> ] bi set-model ] if ;
: (new-field) ( editor field -- gadget ) [ new-editor ] dip new-border dup gadget-child >>editor
field-theme { 1 0 } >>align ; inline
: <model-field*> ( -- field ) "" <model> <model-field> ;
: <empty-field> ( model -- field ) "" <model> switch-models <model-field> ;
: <model-editor> ( model -- gadget ) multiline-editor model-field (new-field) swap init-field >>model* ;
: <model-editor*> ( -- editor ) "" <model> <model-editor> ;
: <empty-editor> ( model -- editor ) "" <model> switch-models <model-editor> ;
: <model-action-field> ( -- field ) f <action-field> dup [ set-control-value ] curry >>quot
f <model> >>model ;
: <slider> ( init page min max step -- slider ) <range> horizontal slider:<slider> ;
: image-prep ( -- image ) scan current-vocab name>> "vocab:" "/icons/" surround ".tiff" surround <image-name> dup cached-image drop ;
SYNTAX: IMG-MODEL-BTN: image-prep [ <model-btn> ] curry append! ;
SYNTAX: IMG-BTN: image-prep [ swap <button> ] curry append! ;
GENERIC: output-model ( gadget -- model )
M: gadget output-model model>> ;
M: table output-model dup val-quot>> [ selection>> ] [ selection-index>> ] if ;
M: model-field output-model model*>> ;
M: scroller output-model viewport>> children>> first output-model ;
M: slider output-model model>> range-model ;
IN: accessors
M: model-btn text>> children>> first text>> ;
IN: ui.gadgets.controls
SINGLETON: gadget-monad
INSTANCE: gadget-monad monad
INSTANCE: gadget monad
M: gadget monad-of drop gadget-monad ;
M: gadget-monad return drop <gadget> swap >>model ;
M: gadget >>= output-model [ swap call( x -- y ) ] curry ;
]]
FILE: [[ui/gadgets/controls/controls-docs.factor]] [[USING: accessors help.markup help.syntax ui.gadgets.buttons
ui.gadgets.editors models ui.gadgets ;
IN: ui.gadgets.controls
HELP: <model-btn>
{ $values { "gadget" "the button's label" } { "button" button } }
{ $description "Creates an button whose signal updates on clicks. " } ;
HELP: <model-border-btn>
{ $values { "text" "the button's label" } { "button" button } }
{ $description "Creates an button whose signal updates on clicks. " } ;
HELP: <table>
{ $values { "model" "values the table is to display" } { "table" table } }
{ $description "Creates an " { $link table } } ;
HELP: <table*>
{ $values { "table" table } }
{ $description "Creates an " { $link table } " with no initial values to display" } ;
HELP: <list>
{ $values { "column-model" "values the table is to display" } { "table" table } }
{ $description "Creates an " { $link table } " with a val-quot that renders each element as its own row" } ;
HELP: <list*>
{ $values { "table" table } }
{ $description "Creates an model-list with no initial values to display" } ;
HELP: indexed
{ $values { "table" table } }
{ $description "Sets the output model of an table to the selected-index, rather than the selected-value" } ;
HELP: <model-field>
{ $values { "model" model } { "gadget" model-field } }
{ $description "Creates a field with an initial value" } ;
HELP: <model-field*>
{ $values { "field" model-field } }
{ $description "Creates a field with an empty initial value" } ;
HELP: <empty-field>
{ $values { "model" model } { "field" model-field } }
{ $description "Creates a field with an empty initial value that switches to another signal on its update" } ;
HELP: <model-editor>
{ $values { "model" model } { "gadget" model-field } }
{ $description "Creates an editor with an initial value" } ;
HELP: <model-editor*>
{ $values { "editor" "an editor" } }
{ $description "Creates a editor with an empty initial value" } ;
HELP: <empty-editor>
{ $values { "model" model } { "editor" "an editor" } }
{ $description "Creates a field with an empty initial value that switches to another signal on its update" } ;
HELP: <model-action-field>
{ $values { "field" action-field } }
{ $description "Field that updates its model with its contents when the user hits the return key" } ;
HELP: IMG-MODEL-BTN:
{ $syntax "IMAGE-MODEL-BTN: filename" }
{ $description "Creates a button using a tiff image named as specified found in the icons subdirectory of the vocabulary path" } ;
HELP: IMG-BTN:
{ $syntax "[ do-something ] IMAGE-BTN: filename" }
{ $description "Creates a button using a tiff image named as specified found in the icons subdirectory of the vocabulary path, calling the specified quotation on click" } ;
HELP: output-model
{ $values { "gadget" gadget } { "model" model } }
{ $description "Returns the model a gadget uses for output. Often the same as " { $link model>> } } ;
]]
FILE: [[ui/gadgets/controls/summary.txt]] [[Gadgets with expanded model usage]]
FILE: [[ui/gadgets/controls/authors.txt]] [[Sam Anklesaria
]]
FILE: [[ui/gadgets/comboboxes/comboboxes.factor]] [[USING: accessors arrays kernel math.rectangles sequences
ui.gadgets.controls models.combinators ui.gadgets ui.gadgets.glass
ui.gadgets.labels ui.gestures ;
QUALIFIED-WITH: ui.gadgets.tables tbl
IN: ui.gadgets.comboboxes
TUPLE: combo-table < table spawner ;
M: combo-table handle-gesture [ call-next-method drop ] 2keep swap
T{ button-up } = [
[ spawner>> ]
[ tbl:selected-row [ swap set-control-value ] [ 2drop ] if ]
[ hide-glass ] tri
] [ drop ] if t ;
TUPLE: combobox < label-control table ;
combobox H{
{ T{ button-down } [ dup table>> over >>spawner <zero-rect> show-glass ] }
} set-gestures
: <combobox> ( options -- combobox ) [ first [ combobox new-label ] keep <basic> >>model ] keep
<basic> combo-table new-table [ 1array ] >>quot >>table ;
]]
FILE: [[ui/gadgets/comboboxes/summary.txt]] [[Combo boxes have a model choosen from a list of options]]
FILE: [[ui/gadgets/comboboxes/authors.txt]] [[Sam Anklesaria
]]
FILE: [[ui/gadgets/tiling/tiling.factor]] [[
USING: kernel sequences math math.order
ui.gadgets ui.gadgets.tracks ui.gestures accessors fry
help.syntax
easy-help ;
IN: ui.gadgets.tiling
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ARTICLE: "ui.gadgets.tiling" "Tiling Layout Gadgets"
Summary:
A gadget which tiles it's children.
A tiling gadget may contain any number of children, but only a
fixed number is displayed at one time. How many are displayed can
be controlled via Control-[ and Control-].
The focus may be switched with Alt-Left and Alt-Right.
The focused child may be moved via Shift-Alt-Left and
Shift-Alt-Right. ..
Example:
<tiling-shelf>
"resource:" directory-files
[ [ drop ] <bevel-button> tiling-add ]
each
"Files" open-window ..
;
ABOUT: "ui.gadgets.tiling"
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: tiling < track gadgets tiles first focused ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init-tiling ( tiling -- tiling )
init-track
{ 1 0 } >>orientation
V{ } clone >>gadgets
2 >>tiles
0 >>first
0 >>focused ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: <tiling> ( -- gadget ) tiling new init-tiling ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: bounded-subseq ( seq a b -- seq )
[ 0 max ] dip
pick length [ min ] curry bi@
rot
subseq ;
: tiling-gadgets-to-map ( tiling -- gadgets )
[ gadgets>> ]
[ first>> ]
[ [ first>> ] [ tiles>> ] bi + ]
tri
bounded-subseq ;
: tiling-map-gadgets ( tiling -- tiling )
dup clear-track
dup tiling-gadgets-to-map [ 1 track-add ] each ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: tiling-add ( tiling gadget -- tiling )
over gadgets>> push
tiling-map-gadgets ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: first-gadget ( tiling -- index ) drop 0 ;
: last-gadget ( tiling -- index ) gadgets>> length 1 - ;
: first-viewable ( tiling -- index ) first>> ;
: last-viewable ( tiling -- index ) [ first>> ] [ tiles>> ] bi + 1 - ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: make-focused-mapped ( tiling -- tiling )
dup [ focused>> ] [ first>> ] bi <
[ dup first>> 1 - >>first ]
[ ]
if
dup [ last-viewable ] [ focused>> ] bi <
[ dup first>> 1 + >>first ]
[ ]
if ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: check-focused-bounds ( tiling -- tiling )
dup focused>> 0 max over gadgets>> length 1 - min >>focused ;
: focus-prev ( tiling -- tiling )
dup focused>> 1 - >>focused
check-focused-bounds
make-focused-mapped
tiling-map-gadgets
dup request-focus ;
: focus-next ( tiling -- tiling )
dup focused>> 1 + >>focused
check-focused-bounds
make-focused-mapped
tiling-map-gadgets
dup request-focus ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: exchanged! ( seq a b -- )
[ 0 max ] bi@
pick length 1 - '[ _ min ] bi@
rot exchange ;
: move-prev ( tiling -- tiling )
dup [ gadgets>> ] [ focused>> 1 - ] [ focused>> ] tri exchanged!
focus-prev ;
: move-next ( tiling -- tiling )
dup [ gadgets>> ] [ focused>> ] [ focused>> 1 + ] tri exchanged!
focus-next ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: add-tile ( tiling -- tiling )
dup tiles>> 1 + >>tiles
tiling-map-gadgets ;
: del-tile ( tiling -- tiling )
dup tiles>> 1 - 1 max >>tiles
tiling-map-gadgets ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
M: tiling focusable-child* ( tiling -- child/t )
[ focused>> ] [ gadgets>> ] bi nth ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: tiling-shelf < tiling ;
TUPLE: tiling-pile < tiling ;
: <tiling-shelf> ( -- gadget )
tiling-shelf new init-tiling { 1 0 } >>orientation ;
: <tiling-pile> ( -- gadget )
tiling-pile new init-tiling { 0 1 } >>orientation ;
tiling-shelf
H{
{ T{ key-down f { A+ } "LEFT" } [ focus-prev drop ] }
{ T{ key-down f { A+ } "RIGHT" } [ focus-next drop ] }
{ T{ key-down f { S+ A+ } "LEFT" } [ move-prev drop ] }
{ T{ key-down f { S+ A+ } "RIGHT" } [ move-next drop ] }
{ T{ key-down f { C+ } "[" } [ del-tile drop ] }
{ T{ key-down f { C+ } "]" } [ add-tile drop ] }
}
set-gestures
tiling-pile
H{
{ T{ key-down f { A+ } "UP" } [ focus-prev drop ] }
{ T{ key-down f { A+ } "DOWN" } [ focus-next drop ] }
{ T{ key-down f { S+ A+ } "UP" } [ move-prev drop ] }
{ T{ key-down f { S+ A+ } "DOWN" } [ move-next drop ] }
{ T{ key-down f { C+ } "[" } [ del-tile drop ] }
{ T{ key-down f { C+ } "]" } [ add-tile drop ] }
}
set-gestures
]]
FILE: [[webapps/numbers/authors.txt]] [[Chris Double
]]
FILE: [[webapps/numbers/numbers.factor]] [[! cont-number-guess
!
! Copyright (C) 2004 Chris Double.
!
! Redistribution and use in source and binary forms, with or without
! modification, are permitted provided that the following conditions are met:
!
! 1. Redistributions of source code must retain the above copyright notice,
! this list of conditions and the following disclaimer.
!
! 2. Redistributions in binary form must reproduce the above copyright notice,
! this list of conditions and the following disclaimer in the documentation
! and/or other materials provided with the distribution.
!
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
!
! This example modifies the console based 'numbers-game' example
! in a very minimal way to demonstrate conversion of a console
! program to a web based application.
!
! All that was required was changing the input and output functions
! to use HTML. The remaining code was untouched.
!
! The result is not that pretty but it shows the basic idea.
USING: kernel math parser html html.elements io namespaces
math.parser random webapps.continuation ;
IN: webapps.numbers
: web-print ( str -- )
! Display the string in a web page.
[
swap dup
"<!DOCTYPE html>" print
<html>
<head> <title> write </title> </head>
<body>
<p> write </p>
<p> <a =href a> "Press to continue" write </a> </p>
</body>
</html>
] show 2drop ;
: read-number ( -- )
[
"<!DOCTYPE html>" print
<html>
<head> <title> "Enter a number" write </title> </head>
<body>
<form =action "post" =method form>
<p>
"Enter a number:" write
<input "text" =type "num" =name "20" =size input/>
<input "submit" =type "Press to continue" =value input/>
</p>
</form>
</body>
</html>
] show [ "num" get ] bind string>number ;
: guess-banner
"I'm thinking of a number between 0 and 100." web-print ;
: guess-prompt ;
: too-high "Too high" web-print ;
: too-low "Too low" web-print ;
: correct "Correct - you win!" web-print ;
: inexact-guess ( actual guess -- )
< [ too-high ] [ too-low ] if ;
: judge-guess ( actual guess -- ? )
2dup = [
2drop correct f
] [
inexact-guess t
] if ;
: number-to-guess ( -- n ) 100 random ;
: numbers-game-loop ( actual -- )
dup guess-prompt read-number judge-guess [
numbers-game-loop
] [
drop
] if ;
: numbers-game number-to-guess numbers-game-loop ;
"numbers-game" [ numbers-game ] install-cont-responder
]]
FILE: [[javascriptcore/javascriptcore.factor]] [[! Copyright (C) 2010 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.c-types alien.data byte-arrays continuations fry
io.encodings.string io.encodings.utf8 io.files
javascriptcore.ffi javascriptcore.ffi.hack kernel namespaces
sequences ;
IN: javascriptcore
ERROR: javascriptcore-error error ;
SYMBOL: js-context
: with-global-context ( quot -- )
[
[ f JSGlobalContextCreate dup js-context set ] dip
[ nip '[ @ ] ]
[ drop '[ _ JSGlobalContextRelease ] ] 2bi
[ ] cleanup
] with-scope ; inline
: with-javascriptcore ( quot -- )
set-callstack-bounds
with-global-context ; inline
: JSString>string ( JSString -- string )
dup JSStringGetMaximumUTF8CStringSize [ <byte-array> ] keep
[ JSStringGetUTF8CString drop ] [ drop ] 2bi
utf8 decode [ 0 = ] trim-tail ;
: JSValueRef>string ( ctx JSValueRef/f -- string/f )
[
f JSValueToStringCopy
[ JSString>string ] [ JSStringRelease ] bi
] [
drop f
] if* ;
: eval-js ( string -- result-string )
[ js-context get dup ] dip
JSStringCreateWithUTF8CString f f 0
{ { void* initial: f } } [ JSEvaluateScript ] with-out-parameters
dup [ nip JSValueRef>string javascriptcore-error ] [ drop JSValueRef>string ] if ;
: eval-js-standalone ( string -- result-string )
'[ _ eval-js ] with-javascriptcore ;
: eval-js-path-standalone ( path -- result-string ) utf8 file-contents eval-js-standalone ;
]]
FILE: [[javascriptcore/core-foundation/platforms.txt]] [[macosx
]]
FILE: [[javascriptcore/core-foundation/authors.txt]] [[Doug Coleman
]]
FILE: [[javascriptcore/core-foundation/core-foundation.factor]] [[! Copyright (C) 2010 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.syntax core-foundation core-foundation.strings
javascriptcore.ffi ;
IN: javascriptcore.core-foundation
FUNCTION: JSStringRef JSStringCreateWithCFString ( CFStringRef string ) ;
FUNCTION: CFStringRef JSStringCopyCFString ( CFAllocatorRef alloc, JSStringRef string ) ;
]]
FILE: [[javascriptcore/platforms.txt]] [[macosx
]]
FILE: [[javascriptcore/javascriptcore-tests.factor]] [[! Copyright (C) 2010 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors javascriptcore kernel tools.test ;
IN: javascriptcore.tests
[ "2" ] [ "1+1" eval-js-standalone ] unit-test
[ "1+shoes" eval-js-standalone ]
[ error>> "ReferenceError: Can't find variable: shoes" = ] must-fail-with
]]
FILE: [[javascriptcore/ffi/platforms.txt]] [[macosx
]]
FILE: [[javascriptcore/ffi/hack/platforms.txt]] [[macosx
]]
FILE: [[javascriptcore/ffi/hack/hack.factor]] [[! Copyright (C) 2010 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.accessors alien.c-types alien.syntax kernel
kernel.private math system ;
IN: javascriptcore.ffi.hack
HOOK: set-callstack-bounds os ( -- )
HOOK: macosx-callstack-start-offset cpu ( -- address )
HOOK: macosx-callstack-size-offset cpu ( -- address )
M: ppc macosx-callstack-start-offset 0x188 ;
M: ppc macosx-callstack-size-offset 0x18c ;
M: x86.32 macosx-callstack-start-offset 0xc48 ;
M: x86.32 macosx-callstack-size-offset 0xc4c ;
M: x86.64 macosx-callstack-start-offset 0x1860 ;
M: x86.64 macosx-callstack-size-offset 0x1868 ;
M: object set-callstack-bounds ;
FUNCTION: void* pthread_self ( ) ;
M: macosx set-callstack-bounds
callstack-bounds over [ alien-address ] bi@ -
pthread_self
[ macosx-callstack-size-offset set-alien-unsigned-cell ]
[ macosx-callstack-start-offset set-alien-cell ] bi ;
]]
FILE: [[javascriptcore/ffi/hack/authors.txt]] [[Doug Coleman
]]
FILE: [[javascriptcore/ffi/ffi.factor]] [[! Copyright (C) 2010 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.libraries alien.syntax
classes.struct combinators io.encodings.utf16n
io.encodings.utf8 kernel system ;
IN: javascriptcore.ffi
<<
"javascriptcore" {
{ [ os macosx? ] [
"/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/JavaScriptCore" cdecl add-library
] }
! { [ os windows? ] [ "javascriptcore.dll" ] }
! { [ os unix? ] [ "libsqlite3.so" ] }
[ drop ]
} cond
>>
LIBRARY: javascriptcore
TYPEDEF: void* JSContextGroupRef
TYPEDEF: void* JSContextRef
TYPEDEF: void* JSGlobalContextRef
TYPEDEF: void* JSStringRef
TYPEDEF: void* JSClassRef
TYPEDEF: void* JSPropertyNameArrayRef
TYPEDEF: void* JSPropertyNameAccumulatorRef
TYPEDEF: void* JSValueRef
TYPEDEF: void* JSObjectRef
TYPEDEF: void* JSObjectInitializeCallback
TYPEDEF: void* JSObjectFinalizeCallback
TYPEDEF: void* JSObjectHasPropertyCallback
TYPEDEF: void* JSObjectGetPropertyCallback
TYPEDEF: void* JSObjectSetPropertyCallback
TYPEDEF: void* JSObjectDeletePropertyCallback
TYPEDEF: void* JSObjectGetPropertyNamesCallback
TYPEDEF: void* JSObjectCallAsFunctionCallback
TYPEDEF: void* JSObjectCallAsConstructorCallback
TYPEDEF: void* JSObjectHasInstanceCallback
TYPEDEF: void* JSObjectConvertToTypeCallback
TYPEDEF: uint unsigned
TYPEDEF: ushort JSChar
ENUM: JSPropertyAttributes
{ kJSPropertyAttributeNone 0 }
{ kJSPropertyAttributeReadOnly 2 }
{ kJSPropertyAttributeDontEnum 4 }
{ kJSPropertyAttributeDontDelete 8 } ;
ENUM: JSClassAttributes
{ kJSClassAttributeNone 0 }
{ kJSClassAttributeNoAutomaticPrototype 2 } ;
ENUM: JSType
kJSTypeUndefined,
kJSTypeNull,
kJSTypeBoolean,
kJSTypeNumber,
kJSTypeString,
kJSTypeObject ;
STRUCT: JSStaticValue
{ name c-string }
{ getProperty JSObjectGetPropertyCallback }
{ setProperty JSObjectSetPropertyCallback }
{ attributes JSPropertyAttributes } ;
STRUCT: JSStaticFunction
{ name c-string }
{ callAsFunction JSObjectCallAsFunctionCallback } ;
STRUCT: JSClassDefinition
{ version int }
{ attributes JSClassAttributes }
{ className c-string }
{ parentClass JSClassRef }
{ staticValues JSStaticValue* }
{ staticFunctions JSStaticFunction* }
{ initialize JSObjectInitializeCallback }
{ finalize JSObjectFinalizeCallback }
{ hasProperty JSObjectHasPropertyCallback }
{ getProperty JSObjectGetPropertyCallback }
{ setProperty JSObjectSetPropertyCallback }
{ deleteProperty JSObjectDeletePropertyCallback }
{ getPropertyNames JSObjectGetPropertyNamesCallback }
{ callAsFunction JSObjectCallAsFunctionCallback }
{ callAsConstructor JSObjectCallAsConstructorCallback }
{ hasInstance JSObjectHasInstanceCallback }
{ convertToType JSObjectConvertToTypeCallback } ;
ALIAS: kJSClassDefinitionEmpty JSClassDefinition
FUNCTION: JSValueRef JSEvaluateScript (
JSContextRef ctx,
JSStringRef script,
JSObjectRef thisObject,
JSStringRef sourceURL,
int startingLineNumber,
JSValueRef* exception ) ;
FUNCTION: bool JSCheckScriptSyntax (
JSContextRef ctx,
JSStringRef script,
JSStringRef sourceURL,
int startingLineNumber,
JSValueRef* exception ) ;
FUNCTION: void JSGarbageCollect
( JSContextRef ctx ) ;
FUNCTION: JSContextGroupRef JSContextGroupCreate
( ) ;
FUNCTION: JSContextGroupRef JSContextGroupRetain
( JSContextGroupRef group ) ;
FUNCTION: void JSContextGroupRelease
( JSContextGroupRef group ) ;
FUNCTION: JSGlobalContextRef JSGlobalContextCreate
( JSClassRef globalObjectClass ) ;
FUNCTION: JSGlobalContextRef JSGlobalContextCreateInGroup (
JSContextGroupRef group,
JSClassRef globalObjectClass ) ;
FUNCTION: JSGlobalContextRef JSGlobalContextRetain
( JSGlobalContextRef ctx ) ;
FUNCTION: void JSGlobalContextRelease
( JSGlobalContextRef ctx ) ;
FUNCTION: JSObjectRef JSContextGetGlobalObject
( JSContextRef ctx ) ;
FUNCTION: JSContextGroupRef JSContextGetGroup
( JSContextRef ctx ) ;
FUNCTION: JSClassRef JSClassCreate
( JSClassDefinition* definition ) ;
FUNCTION: JSClassRef JSClassRetain
( JSClassRef jsClass ) ;
FUNCTION: void JSClassRelease
( JSClassRef jsClass ) ;
FUNCTION: JSObjectRef JSObjectMake
( JSContextRef ctx,
JSClassRef jsClass, void* data ) ;
FUNCTION: JSObjectRef JSObjectMakeFunctionWithCallback ( JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction ) ;
FUNCTION: JSObjectRef JSObjectMakeConstructor ( JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor ) ;
FUNCTION: JSObjectRef JSObjectMakeArray ( JSContextRef ctx, size_t argumentCount, JSValueRef arguments[], JSValueRef* exception ) ;
FUNCTION: JSObjectRef JSObjectMakeDate ( JSContextRef ctx, size_t argumentCount, JSValueRef arguments[], JSValueRef* exception ) ;
FUNCTION: JSObjectRef JSObjectMakeError ( JSContextRef ctx, size_t argumentCount, JSValueRef arguments[], JSValueRef* exception ) ;
FUNCTION: JSObjectRef JSObjectMakeRegExp ( JSContextRef ctx, size_t argumentCount, JSValueRef arguments[], JSValueRef* exception ) ;
FUNCTION: JSObjectRef JSObjectMakeFunction ( JSContextRef ctx, JSStringRef name, unsigned parameterCount, JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception ) ;
FUNCTION: JSValueRef JSObjectGetPrototype ( JSContextRef ctx, JSObjectRef object ) ;
FUNCTION: void JSObjectSetPrototype ( JSContextRef ctx, JSObjectRef object, JSValueRef value ) ;
FUNCTION: bool JSObjectHasProperty ( JSContextRef ctx, JSObjectRef object, JSStringRef propertyName ) ;
FUNCTION: JSValueRef JSObjectGetProperty ( JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception ) ;
FUNCTION: void JSObjectSetProperty ( JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception ) ;
FUNCTION: bool JSObjectDeleteProperty ( JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception ) ;
FUNCTION: JSValueRef JSObjectGetPropertyAtIndex ( JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception ) ;
FUNCTION: void JSObjectSetPropertyAtIndex ( JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception ) ;
FUNCTION: void* JSObjectGetPrivate ( JSObjectRef object ) ;
FUNCTION: bool JSObjectSetPrivate ( JSObjectRef object, void* data ) ;
FUNCTION: bool JSObjectIsFunction ( JSContextRef ctx, JSObjectRef object ) ;
FUNCTION: JSValueRef JSObjectCallAsFunction ( JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, JSValueRef arguments[], JSValueRef* exception ) ;
FUNCTION: bool JSObjectIsConstructor ( JSContextRef ctx, JSObjectRef object ) ;
FUNCTION: JSObjectRef JSObjectCallAsConstructor ( JSContextRef ctx, JSObjectRef object, size_t argumentCount, JSValueRef arguments[], JSValueRef* exception ) ;
FUNCTION: JSPropertyNameArrayRef JSObjectCopyPropertyNames ( JSContextRef ctx, JSObjectRef object ) ;
FUNCTION: JSPropertyNameArrayRef JSPropertyNameArrayRetain ( JSPropertyNameArrayRef array ) ;
FUNCTION: void JSPropertyNameArrayRelease ( JSPropertyNameArrayRef array ) ;
FUNCTION: size_t JSPropertyNameArrayGetCount ( JSPropertyNameArrayRef array ) ;
FUNCTION: JSStringRef JSPropertyNameArrayGetNameAtIndex ( JSPropertyNameArrayRef array, size_t index ) ;
FUNCTION: void JSPropertyNameAccumulatorAddName ( JSPropertyNameAccumulatorRef accumulator, JSStringRef propertyName ) ;
FUNCTION: JSStringRef JSStringCreateWithCharacters ( JSChar* chars, size_t numChars ) ;
FUNCTION: JSStringRef JSStringCreateWithUTF8CString ( c-string string ) ;
FUNCTION: JSStringRef JSStringRetain ( JSStringRef string ) ;
FUNCTION: void JSStringRelease ( JSStringRef string ) ;
FUNCTION: size_t JSStringGetLength ( JSStringRef string ) ;
FUNCTION: JSChar* JSStringGetCharactersPtr ( JSStringRef string ) ;
FUNCTION: size_t JSStringGetMaximumUTF8CStringSize ( JSStringRef string ) ;
FUNCTION: size_t JSStringGetUTF8CString ( JSStringRef string, char* buffer, size_t bufferSize ) ;
FUNCTION: bool JSStringIsEqual ( JSStringRef a, JSStringRef b ) ;
FUNCTION: bool JSStringIsEqualToUTF8CString ( JSStringRef a, char* b ) ;
FUNCTION: JSType JSValueGetType ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: bool JSValueIsUndefined ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: bool JSValueIsNull ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: bool JSValueIsBoolean ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: bool JSValueIsNumber ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: bool JSValueIsString ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: bool JSValueIsObject ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: bool JSValueIsObjectOfClass ( JSContextRef ctx, JSValueRef value, JSClassRef jsClass ) ;
FUNCTION: bool JSValueIsEqual ( JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception ) ;
FUNCTION: bool JSValueIsStrictEqual ( JSContextRef ctx, JSValueRef a, JSValueRef b ) ;
FUNCTION: bool JSValueIsInstanceOfConstructor ( JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception ) ;
FUNCTION: JSValueRef JSValueMakeUndefined ( JSContextRef ctx ) ;
FUNCTION: JSValueRef JSValueMakeNull ( JSContextRef ctx ) ;
FUNCTION: JSValueRef JSValueMakeBoolean ( JSContextRef ctx, bool boolean ) ;
FUNCTION: JSValueRef JSValueMakeNumber ( JSContextRef ctx, double number ) ;
FUNCTION: JSValueRef JSValueMakeString ( JSContextRef ctx, JSStringRef string ) ;
FUNCTION: bool JSValueToBoolean ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: double JSValueToNumber ( JSContextRef ctx, JSValueRef value, JSValueRef* exception ) ;
FUNCTION: JSStringRef JSValueToStringCopy ( JSContextRef ctx, JSValueRef value, JSValueRef* exception ) ;
FUNCTION: JSObjectRef JSValueToObject ( JSContextRef ctx, JSValueRef value, JSValueRef* exception ) ;
FUNCTION: void JSValueProtect ( JSContextRef ctx, JSValueRef value ) ;
FUNCTION: void JSValueUnprotect ( JSContextRef ctx, JSValueRef value ) ;
]]
FILE: [[javascriptcore/ffi/authors.txt]] [[Doug Coleman
]]
FILE: [[javascriptcore/authors.txt]] [[Doug Coleman
]]
FILE: [[ogg/player/player.factor]] [[! Copyright (C) 2007 Chris Double.
! See http://factorcode.org/license.txt for BSD license.
!
! TODO:
! based on number of channels in file.
! - End of decoding is indicated by an exception when reading the stream.
! How to work around this? C player example uses feof but streams don't
! have that in Factor.
! - Work out openal buffer method that plays nicely with streaming over
! slow connections.
! - Have start/stop/seek methods on the player object.
!
USING: kernel alien ogg ogg.vorbis ogg.theora io byte-arrays
sequences libc shuffle alien.c-types system openal math
namespaces threads shuffle opengl arrays ui.gadgets.worlds
combinators math.parser ui.gadgets ui.render opengl.gl ui
continuations io.files hints combinators.lib sequences.lib
io.encodings.binary debugger math.order accessors ;
IN: ogg.player
: audio-buffer-size ( -- number ) 128 1024 * ; inline
TUPLE: player stream temp-state
op oy og
vo vi vd vb vc vorbis
to ti tc td yuv rgb theora video-ready? video-time video-granulepos
source buffers buffer-indexes start-time
playing? audio-full? audio-index audio-buffer audio-granulepos
gadget ;
: init-vorbis ( player -- )
dup oy>> ogg_sync_init drop
dup vi>> vorbis_info_init
vc>> vorbis_comment_init ;
: init-theora ( player -- )
dup ti>> theora_info_init
tc>> theora_comment_init ;
: init-sound ( player -- )
init-openal check-error
1 gen-buffers check-error >>buffers
2 uint <c-array> >>buffer-indexes
1 gen-sources check-error first >>source drop ;
: <player> ( stream -- player )
player new
swap >>stream
0 >>vorbis
0 >>theora
0 >>video-time
0 >>video-granulepos
f >>video-ready?
f >>audio-full?
0 >>audio-index
0 >>start-time
audio-buffer-size "short" <c-array> >>audio-buffer
0 >>audio-granulepos
f >>playing?
ogg_packet malloc-struct >>op
ogg_sync_state malloc-struct >>oy
ogg_page malloc-struct >>og
ogg_stream_state malloc-struct >>vo
vorbis_info malloc-struct >>vi
vorbis_dsp_state malloc-struct >>vd
vorbis_block malloc-struct >>vb
vorbis_comment malloc-struct >>vc
ogg_stream_state malloc-struct >>to
theora_info malloc-struct >>ti
theora_comment malloc-struct >>tc
theora_state malloc-struct >>td
yuv_buffer <struct> >>yuv
ogg_stream_state <struct> >>temp-state
dup init-sound
dup init-vorbis
dup init-theora ;
: num-channels ( player -- channels )
vi>> vorbis_info-channels ;
: al-channel-format ( player -- format )
num-channels 1 = AL_FORMAT_MONO16 AL_FORMAT_STEREO16 ? ;
: get-time ( player -- time )
dup start-time>> zero? [
millis >>start-time
] when
start-time>> millis swap - 1000.0 /f ;
: clamp ( n -- n )
255 min 0 max ; inline
: stride ( line yuv -- uvy yy )
[ uv_stride>> >fixnum swap 2/ * ] 2keep
y_stride>> >fixnum * >fixnum ; inline
: each-with4 ( obj obj obj obj seq quot -- )
4 each-withn ; inline
: compute-y ( yuv uvy yy x -- y )
+ >fixnum nip swap y>> uchar-nth 16 - ; inline
: compute-v ( yuv uvy yy x -- v )
nip 2/ + >fixnum swap u>> uchar-nth 128 - ; inline
: compute-u ( yuv uvy yy x -- v )
nip 2/ + >fixnum swap v>> uchar-nth 128 - ; inline
: compute-yuv ( yuv uvy yy x -- y u v )
[ compute-y ] 4keep [ compute-u ] 4keep compute-v ; inline
: compute-blue ( y u v -- b )
drop 516 * 128 + swap 298 * + -8 shift clamp ; inline
: compute-green ( y u v -- g )
>r >r 298 * r> 100 * - r> 208 * - 128 + -8 shift clamp ;
inline
: compute-red ( y u v -- g )
nip 409 * swap 298 * + 128 + -8 shift clamp ; inline
: compute-rgb ( y u v -- b g r )
[ compute-blue ] 3keep [ compute-green ] 3keep compute-red ;
inline
: store-rgb ( index rgb b g r -- index )
>r
>r pick 0 + >fixnum pick set-uchar-nth
r> pick 1 + >fixnum pick set-uchar-nth
r> pick 2 + >fixnum pick set-uchar-nth
drop ; inline
: yuv>rgb-pixel ( index rgb yuv uvy yy x -- index )
compute-yuv compute-rgb store-rgb 3 + >fixnum ; inline
: yuv>rgb-row ( index rgb yuv y -- index )
over stride
pick y_width>> >fixnum
[ yuv>rgb-pixel ] each-with4 ; inline
: yuv>rgb ( rgb yuv -- )
0 -rot
dup y_height>> >fixnum
[ yuv>rgb-row ] each-with2
drop ;
HINTS: yuv>rgb byte-array byte-array ;
: process-video ( player -- player )
dup gadget>> [
{
[ [ td>> ] [ yuv>> ] bi theora_decode_YUVout drop ]
[ [ rgb>> ] [ yuv>> ] bi yuv>rgb ]
[ gadget>> relayout-1 yield ]
[ ]
} cleave
] when ;
: num-audio-buffers-processed ( player -- player n )
dup source>> AL_BUFFERS_PROCESSED 0 uint <ref>
[ alGetSourcei check-error ] keep uint deref ;
: append-new-audio-buffer ( player -- player )
dup buffers>> 1 gen-buffers append >>buffers
[ [ buffers>> second ] keep al-channel-format ] keep
[ audio-buffer>> dup length ] keep
[ vi>> rate>> alBufferData check-error ] keep
[ source>> 1 ] keep
[ buffers>> second uint <ref> alSourceQueueBuffers check-error ] keep ;
: fill-processed-audio-buffer ( player n -- player )
! n is the number of audio buffers processed
over >r >r dup source>> r> pick buffer-indexes>>
[ alSourceUnqueueBuffers check-error ] keep
uint deref dup r> swap >r al-channel-format rot
[ audio-buffer>> dup length ] keep
[ vi>> rate>> alBufferData check-error ] keep
[ source>> 1 ] keep
r> uint <ref> swap >r alSourceQueueBuffers check-error r> ;
: append-audio ( player -- player bool )
num-audio-buffers-processed {
{ [ over buffers>> length 1 = over zero? and ] [ drop append-new-audio-buffer t ] }
{ [ over buffers>> length 2 = over zero? and ] [ yield drop f ] }
[ fill-processed-audio-buffer t ]
} cond ;
: start-audio ( player -- player bool )
[ [ buffers>> first ] keep al-channel-format ] keep
[ audio-buffer>> dup length ] keep
[ vi>> rate>> alBufferData check-error ] keep
[ source>> 1 ] keep
[ buffers>> first uint <ref> alSourceQueueBuffers check-error ] keep
[ source>> alSourcePlay check-error ] keep
t >>playing? t ;
: process-audio ( player -- player bool )
dup playing?>> [ append-audio ] [ start-audio ] if ;
: read-bytes-into ( dest size stream -- len )
! Read the given number of bytes from a stream
! and store them in the destination byte array.
stream-read >byte-array dup length [ memcpy ] keep ;
: check-not-negative ( int -- )
0 < [ "Word result was a negative number." throw ] when ;
: buffer-size ( -- number )
4096 ; inline
: sync-buffer ( player -- buffer size player )
[ oy>> buffer-size ogg_sync_buffer buffer-size ] keep ;
: stream-into-buffer ( buffer size player -- len player )
[ stream>> read-bytes-into ] keep ;
: confirm-buffer ( len player -- player eof? )
[ oy>> swap ogg_sync_wrote check-not-negative ] 2keep swap zero? ;
: buffer-data ( player -- player eof? )
! Take some compressed bitstream data and sync it for
! page extraction.
sync-buffer stream-into-buffer confirm-buffer ;
: queue-page ( player -- player )
! Push a page into the stream for packetization
[ [ vo>> ] [ og>> ] bi ogg_stream_pagein drop ]
[ [ to>> ] [ og>> ] bi ogg_stream_pagein drop ]
[ ] tri ;
: retrieve-page ( player -- player bool )
! Sync the streams and get a page. Return true if a page was
! successfully retrieved.
dup [ oy>> ] [ og>> ] bi ogg_sync_pageout 0 > ;
: standard-initial-header? ( player -- player bool )
dup og>> ogg_page_bos zero? not ;
: ogg-stream-init ( player -- state player )
! Init the encode/decode logical stream state
[ temp-state>> ] keep
[ og>> ogg_page_serialno ogg_stream_init check-not-negative ] 2keep ;
: ogg-stream-pagein ( state player -- state player )
! Add the incoming page to the stream state
[ og>> ogg_stream_pagein drop ] 2keep ;
: ogg-stream-packetout ( state player -- state player )
[ op>> ogg_stream_packetout drop ] 2keep ;
: decode-packet ( player -- state player )
ogg-stream-init ogg-stream-pagein ogg-stream-packetout ;
: theora-header? ( player -- player bool )
! Is the current page a theora header?
dup [ ti>> ] [ tc>> ] [ op>> ] tri theora_decode_header 0 >= ;
: is-theora-packet? ( player -- player bool )
dup theora>> zero? [ theora-header? ] [ f ] if ;
: copy-to-theora-state ( state player -- player )
! Copy the state to the theora state structure in the player
[ to>> swap dup length memcpy ] keep ;
: handle-initial-theora-header ( state player -- player )
copy-to-theora-state 1 >>theora ;
: vorbis-header? ( player -- player bool )
! Is the current page a vorbis header?
dup [ vi>> ] [ vc>> ] [ op>> ] tri vorbis_synthesis_headerin 0 >= ;
: is-vorbis-packet? ( player -- player bool )
dup vorbis>> zero? [ vorbis-header? ] [ f ] if ;
: copy-to-vorbis-state ( state player -- player )
! Copy the state to the vorbis state structure in the player
[ vo>> swap dup length memcpy ] keep ;
: handle-initial-vorbis-header ( state player -- player )
copy-to-vorbis-state 1 >>vorbis ;
: handle-initial-unknown-header ( state player -- player )
swap ogg_stream_clear drop ;
: process-initial-header ( player -- player bool )
! Is this a standard initial header? If not, stop parsing
standard-initial-header? [
decode-packet {
{ [ is-vorbis-packet? ] [ handle-initial-vorbis-header ] }
{ [ is-theora-packet? ] [ handle-initial-theora-header ] }
[ handle-initial-unknown-header ]
} cond t
] [
f
] if ;
: parse-initial-headers ( player -- player )
! Parse Vorbis headers, ignoring any other type stored
! in the Ogg container.
retrieve-page [
process-initial-header [
parse-initial-headers
] [
! Don't leak the page, get it into the appropriate stream
queue-page
] if
] [
buffer-data not [ parse-initial-headers ] when
] if ;
: have-required-vorbis-headers? ( player -- player bool )
! Return true if we need to decode vorbis due to there being
! vorbis headers read from the stream but we don't have them all
! yet.
dup vorbis>> 1 2 between? not ;
: have-required-theora-headers? ( player -- player bool )
! Return true if we need to decode theora due to there being
! theora headers read from the stream but we don't have them all
! yet.
dup theora>> 1 2 between? not ;
: get-remaining-vorbis-header-packet ( player -- player bool )
dup [ vo>> ] [ op>> ] bi ogg_stream_packetout {
{ [ dup 0 < ] [ "Error parsing vorbis stream; corrupt stream?" throw ] }
{ [ dup zero? ] [ drop f ] }
{ [ t ] [ drop t ] }
} cond ;
: get-remaining-theora-header-packet ( player -- player bool )
dup [ to>> ] [ op>> ] bi ogg_stream_packetout {
{ [ dup 0 < ] [ "Error parsing theora stream; corrupt stream?" throw ] }
{ [ dup zero? ] [ drop f ] }
{ [ t ] [ drop t ] }
} cond ;
: decode-remaining-vorbis-header-packet ( player -- player )
dup [ vi>> ] [ vc>> ] [ op>> ] tri vorbis_synthesis_headerin zero? [
"Error parsing vorbis stream; corrupt stream?" throw
] unless ;
: decode-remaining-theora-header-packet ( player -- player )
dup [ ti>> ] [ tc>> ] [ op>> ] tri theora_decode_header zero? [
"Error parsing theora stream; corrupt stream?" throw
] unless ;
: increment-vorbis-header-count ( player -- player )
[ 1+ ] change-vorbis ;
: increment-theora-header-count ( player -- player )
[ 1+ ] change-theora ;
: parse-remaining-vorbis-headers ( player -- player )
have-required-vorbis-headers? not [
get-remaining-vorbis-header-packet [
decode-remaining-vorbis-header-packet
increment-vorbis-header-count
parse-remaining-vorbis-headers
] when
] when ;
: parse-remaining-theora-headers ( player -- player )
have-required-theora-headers? not [
get-remaining-theora-header-packet [
decode-remaining-theora-header-packet
increment-theora-header-count
parse-remaining-theora-headers
] when
] when ;
: get-more-header-data ( player -- player )
buffer-data drop ;
: parse-remaining-headers ( player -- player )
have-required-vorbis-headers? not swap have-required-theora-headers? not swapd or [
parse-remaining-vorbis-headers
parse-remaining-theora-headers
retrieve-page [ queue-page ] [ get-more-header-data ] if
parse-remaining-headers
] when ;
: tear-down-vorbis ( player -- player )
dup vi>> vorbis_info_clear
dup vc>> vorbis_comment_clear ;
: tear-down-theora ( player -- player )
dup ti>> theora_info_clear
dup tc>> theora_comment_clear ;
: init-vorbis-codec ( player -- player )
dup [ vd>> ] [ vi>> ] bi vorbis_synthesis_init drop
dup [ vd>> ] [ vb>> ] bi vorbis_block_init drop ;
: init-theora-codec ( player -- player )
dup [ td>> ] [ ti>> ] bi theora_decode_init drop
dup ti>> frame_width>> over ti>> frame_height>>
4 * * <byte-array> >>rgb ;
: display-vorbis-details ( player -- player )
[
"Ogg logical stream " %
dup vo>> serialno>> #
" is Vorbis " %
dup vi>> channels>> #
" channel " %
dup vi>> rate>> #
" Hz audio." %
] "" make print ;
: display-theora-details ( player -- player )
[
"Ogg logical stream " %
dup to>> serialno>> #
" is Theora " %
dup ti>> width>> #
"x" %
dup ti>> height>> #
" " %
dup ti>> fps_numerator>>
over ti>> fps_denominator>> /f #
" fps video" %
] "" make print ;
: initialize-decoder ( player -- player )
dup vorbis>> zero? [ tear-down-vorbis ] [ init-vorbis-codec display-vorbis-details ] if
dup theora>> zero? [ tear-down-theora ] [ init-theora-codec display-theora-details ] if ;
: sync-pages ( player -- player )
retrieve-page [
queue-page sync-pages
] when ;
: audio-buffer-not-ready? ( player -- player bool )
dup vorbis>> zero? not over audio-full?>> not and ;
: pending-decoded-audio? ( player -- player pcm len bool )
f <void*> 2dup >r vd>> r> vorbis_synthesis_pcmout dup 0 > ;
: buffer-space-available ( player -- available )
audio-buffer-size swap audio-index>> - ;
: samples-to-read ( player available len -- numread )
>r swap num-channels / r> min ;
: each-with3 ( obj obj obj seq quot -- ) 3 each-withn ; inline
: add-to-buffer ( player val -- )
over audio-index>> pick audio-buffer>> set-short-nth
[ 1+ ] change-audio-index drop ;
: get-audio-value ( pcm sample channel -- value )
rot *void* void*-nth float-nth ;
: process-channels ( player pcm sample channel -- )
get-audio-value 32767.0 * >fixnum 32767 min -32768 max add-to-buffer ;
: (process-sample) ( player pcm sample -- )
pick num-channels [ process-channels ] each-with3 ;
: process-samples ( player pcm numread -- )
[ (process-sample) ] each-with2 ;
: decode-pending-audio ( player pcm result -- player )
! [ "ret = " % dup # ] "" make write
pick [ buffer-space-available swap ] keep -rot samples-to-read
pick over >r >r process-samples r> r> swap
! numread player
dup audio-index>> audio-buffer-size = [
t >>audio-full?
] when
dup vd>> granulepos>> dup 0 >= [
! numtoread player granulepos
! This is wrong: fix
pick - >>audio-granulepos
] [
! numtoread player granulepos
pick + >>audio-granulepos
] if
[ vd>> swap vorbis_synthesis_read drop ] keep ;
: no-pending-audio ( player -- player bool )
! No pending audio. Is there a pending packet to decode.
dup [ vo>> ] [ op>> ] bi ogg_stream_packetout 0 > [
dup [ vb>> ] [ op>> ] bi vorbis_synthesis 0 = [
dup [ vd>> ] [ vb>> ] bi vorbis_synthesis_blockin drop
] when
t
] [
! Need more data. Break out to suck in another page.
f
] if ;
: decode-audio ( player -- player )
audio-buffer-not-ready? [
! If there's pending decoded audio, grab it
pending-decoded-audio? [
decode-pending-audio decode-audio
] [
2drop no-pending-audio [ decode-audio ] when
] if
] when ;
: video-buffer-not-ready? ( player -- player bool )
dup theora>> zero? not over video-ready?>> not and ;
: decode-video ( player -- player )
video-buffer-not-ready? [
dup [ to>> ] [ op>> ] bi ogg_stream_packetout 0 > [
dup [ td>> ] [ op>> ] bi theora_decode_packetin drop
dup td>> granulepos>> >>video-granulepos
dup [ td>> ] [ video-granulepos>> ] bi theora_granule_time
>>video-time
t >>video-ready?
decode-video
] when
] when ;
: decode ( player -- player )
get-more-header-data sync-pages
decode-audio
decode-video
dup audio-full?>> [
process-audio [
f >>audio-full?
0 >>audio-index
] when
] when
dup video-ready?>> [
dup video-time>> over get-time - dup 0.0 < [
-0.1 > [ process-video ] when
f >>video-ready?
] [
drop
] if
] when
decode ;
: free-malloced-objects ( player -- player )
{
[ op>> free ]
[ oy>> free ]
[ og>> free ]
[ vo>> free ]
[ vi>> free ]
[ vd>> free ]
[ vb>> free ]
[ vc>> free ]
[ to>> free ]
[ ti>> free ]
[ tc>> free ]
[ td>> free ]
[ ]
} cleave ;
: unqueue-openal-buffers ( player -- player )
[
num-audio-buffers-processed over source>> rot buffer-indexes>> swapd
alSourceUnqueueBuffers check-error
] keep ;
: delete-openal-buffers ( player -- player )
[
buffers>> [
1 swap uint <ref> alDeleteBuffers check-error
] each
] keep ;
: delete-openal-source ( player -- player )
[ source>> 1 swap uint <ref> alDeleteSources check-error ] keep ;
: cleanup ( player -- player )
free-malloced-objects
unqueue-openal-buffers
delete-openal-buffers
delete-openal-source ;
: wait-for-sound ( player -- player )
! Waits for the openal to finish playing remaining sounds
dup source>> AL_SOURCE_STATE 0 <int> [ alGetSourcei check-error ] keep
*int AL_PLAYING = [
100 sleep
wait-for-sound
] when ;
TUPLE: theora-gadget < gadget player ;
: <theora-gadget> ( player -- gadget )
theora-gadget new-gadget
swap >>player ;
M: theora-gadget pref-dim*
player>>
ti>> dup width>> swap height>> 2array ;
M: theora-gadget draw-gadget* ( gadget -- )
0 0 glRasterPos2i
1.0 -1.0 glPixelZoom
GL_UNPACK_ALIGNMENT 1 glPixelStorei
[ pref-dim* first2 GL_RGB GL_UNSIGNED_BYTE ] keep
player>> rgb>> glDrawPixels ;
: initialize-gui ( gadget -- )
"Theora Player" open-window ;
: play-ogg ( player -- )
parse-initial-headers
parse-remaining-headers
initialize-decoder
dup gadget>> [ initialize-gui ] when*
[ decode ] try
wait-for-sound
cleanup
drop ;
: play-vorbis-stream ( stream -- )
<player> play-ogg ;
: play-vorbis-file ( filename -- )
binary <file-reader> play-vorbis-stream ;
: play-theora-stream ( stream -- )
<player>
dup <theora-gadget> >>gadget
play-ogg ;
: play-theora-file ( filename -- )
binary <file-reader> play-theora-stream ;
]]
FILE: [[ogg/player/summary.txt]] [[Ogg vorbis and theora media player
]]
FILE: [[ogg/player/authors.txt]] [[Chris Double
]]
FILE: [[ogg/player/tags.txt]] [[audio
video
]]
FILE: [[furnace/callbacks/callbacks.factor]] [[! Copyright (C) 2004 Chris Double.
! Copyright (C) 2006, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: http http.server io kernel math namespaces
continuations calendar sequences assocs hashtables
accessors arrays alarms quotations combinators fry
http.server.redirection furnace assocs.lib urls ;
IN: furnace.callbacks
SYMBOL: responder
TUPLE: callback-responder responder callbacks ;
: <callback-responder> ( responder -- responder' )
H{ } clone callback-responder boa ;
TUPLE: callback cont quot expires alarm responder ;
: timeout 20 minutes ;
: timeout-callback ( callback -- )
[ alarm>> cancel-alarm ]
[ dup responder>> callbacks>> delete-at ]
bi ;
: touch-callback ( callback -- )
dup expires>> [
dup alarm>> [ cancel-alarm ] when*
dup '[ , timeout-callback ] timeout later >>alarm
] when drop ;
: <callback> ( cont quot expires? -- callback )
f callback-responder get callback boa
dup touch-callback ;
: invoke-callback ( callback -- response )
[ touch-callback ]
[ quot>> request get exit-continuation get 3array ]
[ cont>> continue-with ]
tri ;
: register-callback ( cont quot expires? -- id )
<callback> callback-responder get callbacks>> set-at-unique ;
: forward-to-url ( url -- * )
! When executed inside a 'show' call, this will force a
! HTTP 302 to occur to instruct the browser to forward to
! the request URL.
<temporary-redirect> exit-with ;
: cont-id "factorcontid" ;
: forward-to-id ( id -- * )
! When executed inside a 'show' call, this will force a
! HTTP 302 to occur to instruct the browser to forward to
! the request URL.
<url>
swap cont-id set-query-param forward-to-url ;
: restore-request ( pair -- )
first3 exit-continuation set request set call ;
SYMBOL: post-refresh-get?
: redirect-to-here ( -- )
! Force a redirect to the client browser so that the browser
! goes to the current point in the code. This forces an URL
! change on the browser so that refreshing that URL will
! immediately run from this code point. This prevents the
! "this request will issue a POST" warning from the browser
! and prevents re-running the previous POST logic. This is
! known as the 'post-refresh-get' pattern.
post-refresh-get? get [
[
[ ] t register-callback forward-to-id
] callcc1 restore-request
] [
post-refresh-get? on
] if ;
SYMBOL: current-show
: store-current-show ( -- )
! Store the current continuation in the variable 'current-show'
! so it can be returned to later by 'quot-id'. Note that it
! recalls itself when the continuation is called to ensure that
! it resets its value back to the most recent show call.
[ current-show set f ] callcc1
[ restore-request store-current-show ] when* ;
: show-final ( quot -- * )
[ redirect-to-here store-current-show ] dip
call exit-with ; inline
: resuming-callback ( responder request -- id )
url>> cont-id query-param swap callbacks>> at ;
M: callback-responder call-responder* ( path responder -- response )
'[
, ,
[ callback-responder set ]
[ request get resuming-callback ] bi
[
invoke-callback
] [
callback-responder get responder>> call-responder
] ?if
] with-exit-continuation ;
: show-page ( quot -- )
[ redirect-to-here store-current-show ] dip
[
[ ] t register-callback swap call exit-with
] callcc1 restore-request ; inline
: quot-id ( quot -- id )
current-show get swap t register-callback ;
: quot-url ( quot -- url )
quot-id f swap cont-id associate derive-url ;
]]
FILE: [[furnace/callbacks/callbacks-tests.factor]] [[USING: furnace furnace.actions furnace.callbacks accessors
http http.server http.server.responses tools.test
namespaces io fry sequences
splitting kernel hashtables continuations ;
IN: furnace.callbacks.tests
[ 123 ] [
[
<request> "GET" >>method init-request
[
exit-continuation set
{ }
<action> [ [ "hello" print 123 ] show-final ] >>display
<callback-responder>
call-responder
] callcc1
] with-scope
] unit-test
[
<action> [
[
"hello" print
<html-content>
] show-page
"byebye" print
[ 123 ] show-final
] >>display
<callback-responder> "r" set
[ 123 ] [
<request> init-request
[
exit-continuation set
<request> "GET" >>method init-request
{ } "r" get call-responder
] callcc1
body>> first
<request>
"GET" >>method
dup url>> rot cont-id associate >>query drop
dup url>> "/" >>path drop
init-request
[
exit-continuation set
{ }
"r" get call-responder
] callcc1
! get-post-get
<request>
"GET" >>method
dup url>> rot "location" header query>> >>query drop
dup url>> "/" >>path drop
init-request
[
exit-continuation set
{ }
"r" get call-responder
] callcc1
] unit-test
] with-scope
]]
FILE: [[sniffer/io/bsd/bsd.factor]] [[! Copyright (C) 2007 Elie Chaftari, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.c-types alien.syntax destructors hexdump io
io.buffers io.nonblocking io.sockets
io.unix.backend io.unix.files kernel libc locals math qualified
sequences io.sniffer.backend ;
QUALIFIED: unix
IN: io.sniffer.bsd
M: unix-io destruct-handle ( obj -- ) unix:close ;
C-UNION: ifreq_props "sockaddr-in" "short" "int" "caddr_t" ;
C-STRUCT: ifreq { { "char" 16 } "name" } { "ifreq_props" "props" } ;
TUPLE: sniffer-spec path ifname ;
C: <sniffer-spec> sniffer-spec
: IOCPARM_MASK 0x1fff ; inline
: IOCPARM_MAX IOCPARM_MASK 1+ ; inline
: IOC_VOID 0x20000000 ; inline
: IOC_OUT 0x40000000 ; inline
: IOC_IN 0x80000000 ; inline
: IOC_INOUT IOC_IN IOC_OUT bitor ; inline
: IOC_DIRMASK 0xe0000000 ; inline
:: ioc ( inout group num len -- n )
group first 8 shift num bitor
len IOCPARM_MASK bitand 16 shift bitor
inout bitor ;
: io-len ( type -- n )
dup zero? [ heap-size ] unless ;
: io ( group num -- n )
IOC_VOID -rot 0 io-len ioc ;
: ior ( group num type -- n )
IOC_OUT -roll io-len ioc ;
: iow ( group num type -- n )
IOC_IN -roll io-len ioc ;
: iowr ( group num type -- n )
IOC_INOUT -roll io-len ioc ;
: BIOCGBLEN ( -- n ) "B" 102 "uint" ior ; inline
: BIOCSETIF ( -- n ) "B" 108 "ifreq" iow ; inline
: BIOCPROMISC ( -- n ) "B" 105 io ; inline
: BIOCIMMEDIATE ( -- n ) "B" 112 "uint" iow ; inline
: make-ifreq-props ( ifname -- ifreq )
"ifreq" <c-object>
12 <short> 16 0 pad-right over set-ifreq-props
swap malloc-char-string dup free-always
over set-ifreq-name ;
: make-ioctl-buffer ( fd -- buffer )
BIOCGBLEN "char*" <c-object>
[ unix:ioctl io-error ] keep
*int <buffer> ;
: ioctl-BIOSETIF ( fd ifreq -- )
>r BIOCSETIF r> unix:ioctl io-error ;
: ioctl-BIOPROMISC ( fd -- )
BIOCPROMISC f unix:ioctl io-error ;
: ioctl-BIOCIMMEDIATE
BIOCIMMEDIATE 1 <int> unix:ioctl io-error ;
: ioctl-sniffer-fd ( fd ifname -- )
dupd make-ifreq-props ioctl-BIOSETIF
dup ioctl-BIOPROMISC
ioctl-BIOCIMMEDIATE ;
M: unix-io <sniffer> ( obj -- sniffer )
[
[
sniffer-spec-path
open-read
dup close-later
] keep
dupd sniffer-spec-ifname ioctl-sniffer-fd
dup make-ioctl-buffer
input-port <port> <line-reader>
\ sniffer construct-delegate
] with-destructors ;
]]
FILE: [[sniffer/io/bsd/authors.txt]] [[Doug Coleman
Elie Chaftari
]]
FILE: [[sniffer/io/backend/backend.factor]] [[USING: io.backend kernel system vocabs.loader ;
IN: io.sniffer.backend
SYMBOL: sniffer-type
TUPLE: sniffer ;
HOOK: <sniffer> io-backend ( obj -- sniffer )
]]
FILE: [[sniffer/io/backend/authors.txt]] [[Doug Coleman
Elie Chaftari
]]
FILE: [[sniffer/io/filter/bsd/bsd.factor]] [[USING: alien.c-types hexdump io io.backend io.sockets.headers
io.sockets.headers.bsd kernel io.sniffer io.sniffer.bsd
io.streams.string io.unix.backend math
sequences system byte-arrays io.sniffer.filter.backend
io.sniffer.filter.backend io.sniffer.backend ;
IN: io.sniffer.filter.bsd
! http://www.iana.org/assignments/ethernet-numbers
: bpf-align ( n -- n' )
! Align to next higher word size
"long" heap-size align ;
M: unix-io packet. ( string -- )
18 cut swap >byte-array bpfh.
(packet.) ;
M: unix-io sniffer-loop ( stream -- )
nl nl
4096 over stream-read-partial
dup hexdump.
packet.
sniffer-loop ;
! Mac
: sniff-wired ( -- )
"/dev/bpf0" "en0" <sniffer-spec> <sniffer> sniffer-loop ;
! Macbook
: sniff-wireless ( -- )
"/dev/bpf0" "en1" <sniffer-spec> <sniffer> sniffer-loop ;
]]
FILE: [[sniffer/io/filter/bsd/authors.txt]] [[Doug Coleman
Elie Chaftari
]]
FILE: [[sniffer/io/filter/backend/backend.factor]] [[USING: byte-arrays combinators io io.backend
io.sockets.headers io.sniffer.backend kernel
prettyprint sequences ;
IN: io.sniffer.filter.backend
HOOK: sniffer-loop io-backend ( stream -- )
HOOK: packet. io-backend ( string -- )
: (packet.) ( string -- )
dup 14 head >byte-array
"--Ethernet Header--" print
dup etherneth.
dup etherneth-type {
! 0x800 [ ] ! IP
! 0x806 [ ] ! ARP
[ "Unknown type: " write .h ]
} case 2drop ;
]]
FILE: [[sniffer/io/filter/backend/authors.txt]] [[Doug Coleman
Elie Chaftari
]]
FILE: [[sniffer/io/filter/authors.txt]] [[Doug Coleman
Elie Chaftari
]]
FILE: [[sniffer/io/filter/filter.factor]] [[USING: alien.c-types byte-arrays combinators hexdump io
io.backend io.streams.string io.sockets.headers kernel math
prettyprint io.sniffer sequences system vocabs.loader
io.sniffer.filter.backend ;
IN: io.sniffer.filter
bsd? [ "io.sniffer.filter.bsd" require ] when
]]
FILE: [[sniffer/io/sniffer.factor]] [[USING: io.backend kernel system vocabs.loader ;
IN: io.sniffer
bsd? [ "io.sniffer.bsd" require ] when
]]
FILE: [[sniffer/io/authors.txt]] [[Doug Coleman
Elie Chaftari
]]
FILE: [[sniffer/channels/bsd/bsd.factor]] [[! Copyright (C) 2007 Chris Double. All Rights Reserved.
! See http://factorcode.org/license.txt for BSD license.
!
! Wrap a sniffer in a channel
USING: kernel channels channels.sniffer.backend
threads io io.sniffer.backend io.sniffer.bsd
io.unix.backend ;
IN: channels.sniffer.bsd
M: unix-io sniff-channel ( -- channel )
"/dev/bpf0" "en1" <sniffer-spec> <sniffer> <channel> [
[
(sniff-channel)
] 3curry spawn drop
] keep ;
]]
FILE: [[sniffer/channels/backend/backend.factor]] [[USING: io.backend ;
HOOK: sniff-channel io-backend ( -- channel )
]]
FILE: [[sniffer/channels/sniffer.factor]] [[! Copyright (C) 2007 Chris Double. All Rights Reserved.
! See http://factorcode.org/license.txt for BSD license.
!
! Wrap a sniffer in a channel
USING: kernel channels io io.backend io.sniffer
io.sniffer.backend system vocabs.loader ;
: (sniff-channel) ( stream channel -- )
4096 pick stream-read-partial over to (sniff-channel) ;
bsd? [ "channels.sniffer.bsd" require ] when
]]
FILE: [[automata/ui/ui.factor]] [[
USING: kernel namespaces math quotations arrays hashtables sequences threads
opengl
opengl.gl
colors
ui
ui.gestures
ui.gadgets
ui.gadgets.slate
ui.gadgets.labels
ui.gadgets.buttons
ui.gadgets.frames
ui.gadgets.packs
ui.gadgets.grids
ui.gadgets.theme
ui.gadgets.handler
accessors
vars fry
rewrite-closures automata math.geometry.rect newfx ;
IN: automata.ui
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: draw-point ( y x value -- ) 1 = [ swap glVertex2i ] [ 2drop ] if ;
: draw-line ( y line -- ) 0 swap [ [ 2dup ] dip draw-point 1+ ] each 2drop ;
: (draw-bitmap) ( bitmap -- ) 0 swap [ [ dup ] dip draw-line 1+ ] each drop ;
: draw-bitmap ( bitmap -- ) GL_POINTS glBegin (draw-bitmap) glEnd ;
: display ( -- ) black gl-color bitmap> draw-bitmap ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VAR: slate
! Call a 'model' quotation with the current 'view'.
: with-view ( quot -- )
slate> rect-dim first >width
slate> rect-dim second >height
call
slate> relayout-1 ;
! Create a quotation that is appropriate for buttons and gesture handler.
: view-action ( quot -- quot ) '[ drop _ with-view ] closed-quot ;
: view-button ( label quot -- button ) [ <label> ] dip view-action <bevel-button> ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Helper word to make things less verbose
: random-rule ( -- ) set-interesting start-center ;
DEFER: automata-window
: automata-window* ( -- )
init-rule
set-interesting
<frame>
<shelf>
"1 - Center" [ start-center ] view-button add-gadget
"2 - Random" [ start-random ] view-button add-gadget
"3 - Continue" [ run-rule ] view-button add-gadget
"5 - Random Rule" [ random-rule ] view-button add-gadget
"n - New" [ automata-window ] view-button add-gadget
@top grid-add
C[ display ] <slate>
{ 400 400 } >>pdim
dup >slate
@center grid-add
<handler>
H{ }
T{ key-down f f "1" } [ start-center ] view-action is
T{ key-down f f "2" } [ start-random ] view-action is
T{ key-down f f "3" } [ run-rule ] view-action is
T{ key-down f f "5" } [ random-rule ] view-action is
T{ key-down f f "n" } [ automata-window ] view-action is
>>table
"Automata" open-window ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: automata-window ( -- ) [ [ automata-window* ] with-scope ] with-ui ;
MAIN: automata-window
]]
FILE: [[automata/ui/deploy.factor]] [[USING: tools.deploy.config ;
V{
{ deploy-ui? t }
{ deploy-io 1 }
{ deploy-reflection 1 }
{ deploy-compiler? t }
{ deploy-math? t }
{ deploy-word-props? f }
{ deploy-c-types? f }
{ "stop-after-last-window?" t }
{ deploy-name "Cellular Automata" }
}
]]
FILE: [[automata/ui/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[automata/ui/tags.txt]] [[demos
]]
FILE: [[automata/automata.factor]] [[
USING: kernel math math.parser random arrays hashtables assocs sequences
grouping vars ;
IN: automata
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! set-rule
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VAR: rule VAR: rule-number
: init-rule ( -- ) 8 <hashtable> >rule ;
: rule-keys ( -- array )
{ { 1 1 1 }
{ 1 1 0 }
{ 1 0 1 }
{ 1 0 0 }
{ 0 1 1 }
{ 0 1 0 }
{ 0 0 1 }
{ 0 0 0 } } ;
: rule-values ( n -- seq ) >bin 8 CHAR: 0 pad-head string>digits ;
: set-rule ( n -- )
dup >rule-number rule-values rule-keys [ rule> set-at ] 2each ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! step-capped-line
! step-wrapped-line
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: pattern>state ( {_a_b_c_} -- state ) rule> at ;
: cap-line ( line -- 0-line-0 ) { 0 } prepend { 0 } append ;
: wrap-line ( a-line-z -- za-line-za )
dup peek 1array swap dup first 1array append append ;
: step-line ( line -- new-line ) 3 <clumps> [ pattern>state ] map ;
: step-capped-line ( line -- new-line ) cap-line step-line ;
: step-wrapped-line ( line -- new-line ) wrap-line step-line ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VARS: width height ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: random-line ( -- line ) width> [ drop 2 random ] map ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: center-i ( -- i ) width> 2 / >fixnum ;
: center-line ( -- line ) center-i width> [ = 1 0 ? ] with map ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: interesting ( -- seq )
{ 18 22 26 30 41 45 54 60 73 75 82 86 89 90 97 101 102 105 106 107 109
110 120 121 122 124 126 129 137 146 147 149 150 151 153 154 161 165 } ;
: mild ( -- seq ) { 6 9 11 57 62 74 118 } ;
: set-interesting ( -- ) interesting random set-rule ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VAR: bitmap
VAR: last-line
: run-rule ( -- )
last-line> height> [ drop step-capped-line dup ] map >bitmap >last-line ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: start-random ( -- ) random-line >last-line run-rule ;
: start-center ( -- ) center-line >last-line run-rule ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! VAR: loop-flag
! DEFER: loop
! : (loop) ( -- ) run-rule 3000 sleep loop ;
! : loop ( -- ) loop-flag> [ (loop) ] [ ] if ;
! : start-loop ( -- ) t >loop-flag [ loop ] in-thread ;
! : stop-loop ( -- ) f >loop-flag ;
]]
FILE: [[automata/summary.txt]] [[Cellular Automata Explorer (one dimensional, two state)
]]
FILE: [[automata/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[LICENSE]] [[Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
]]
FILE: [[update/util/util.factor]] [[
USING: kernel classes strings quotations words math math.parser arrays
combinators.smart
accessors
system prettyprint splitting
sequences combinators sequences.deep
io
io.launcher
io.encodings.utf8
calendar
calendar.format ;
IN: update.util
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
DEFER: to-strings
: to-string ( obj -- str )
dup class-of
{
{ \ string [ ] }
{ \ quotation [ call( -- string ) ] }
{ \ word [ execute( -- string ) ] }
{ \ fixnum [ number>string ] }
{ \ array [ to-strings concat ] }
}
case ;
: to-strings ( seq -- str )
dup [ string? ] all?
[ ]
[ [ to-string ] map flatten ]
if ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: cpu- ( -- cpu ) cpu unparse "." split "-" join ;
: platform ( -- string ) { [ os unparse ] cpu- } to-strings "-" join ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: branch-name ( -- string ) "clean-" platform append ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: gnu-make ( -- string )
"make" ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: git-id ( -- id )
{ "git" "show" } utf8 [ readln ] with-process-reader
" " split second ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: datestamp ( -- string )
now
[ { [ year>> ] [ month>> ] [ day>> ] [ hour>> ] [ minute>> ] } cleave ] output>array
[ pad-00 ] map "-" join ;
]]
FILE: [[update/update.factor]] [[USING: kernel system sequences io.files io.directories
io.pathnames io.launcher bootstrap.image http.client update.util ;
IN: update
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: run-command ( cmd -- ) to-strings try-process ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: git-pull-clean ( -- )
image-path parent-directory [
{ "git" "pull" "git://factorcode.org/git/factor.git" branch-name }
run-command
] with-directory ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: remote-clean-image ( -- url )
{ "http://factorcode.org/images/clean/" platform "/" my-boot-image-name }
to-string ;
: download-clean-image ( -- ) remote-clean-image download ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: make-clean ( -- ) { gnu-make "clean" } run-command ;
: make ( -- ) { gnu-make } run-command ;
: boot ( -- ) { "./factor" { "-i=" my-boot-image-name } } run-command ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: rebuild ( -- )
image-path parent-directory [
download-clean-image
make-clean
make
boot
] with-directory ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: update ( -- )
image-path parent-directory [
git-id
git-pull-clean
git-id
= not
[ rebuild ]
when
] with-directory ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
MAIN: update
]]
FILE: [[update/latest/latest.factor]] [[USING: kernel namespaces system io.files io.pathnames io.directories
bootstrap.image http.client update update.backup update.util ;
IN: update.latest
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: git-pull-master ( -- )
image-path parent-directory
[
{ "git" "pull" "git://factorcode.org/git/factor.git" "master" }
run-command
]
with-directory ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: remote-latest-image ( -- url )
{ "http://factorcode.org/images/latest/" my-boot-image-name } to-string ;
: download-latest-image ( -- ) remote-latest-image download ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: rebuild-latest ( -- )
image-path parent-directory
[
backup
download-latest-image
make-clean
make
boot
]
with-directory ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: update-latest ( -- )
image-path parent-directory
[
git-id
git-pull-master
git-id
= not
[ rebuild-latest ]
when
]
with-directory ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
MAIN: update-latest
]]
FILE: [[update/backup/backup.factor]] [[USING: namespaces debugger io.files io.directories
bootstrap.image update.util ;
IN: update.backup
: backup-boot-image ( -- )
my-boot-image-name
{ "boot." my-arch-name "-" [ "datestamp" get ] ".image" } to-string
move-file ;
: backup-image ( -- )
"factor.image"
{ "factor" "-" [ "datestamp" get ] ".image" } to-string
move-file ;
: backup-vm ( -- )
"factor"
{ "factor" "-" [ "datestamp" get ] } to-string
move-file ;
: backup ( -- )
datestamp "datestamp" set
[
backup-boot-image
backup-image
backup-vm
]
try ;
]]
FILE: [[adsoda/tools/tools.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING:
kernel
sequences
math
accessors
adsoda
math.vectors
math.matrices
bunny.model
io.encodings.ascii
io.files
sequences.deep
combinators
adsoda.combinators
fry
io.files.temp
grouping
;
IN: adsoda.tools
! ---------------------------------
: coord-min ( x array -- array ) swap suffix ;
: coord-max ( x array -- array ) swap neg suffix ;
: 4cube ( array name -- solid )
! array : xmin xmax ymin ymax zmin zmax wmin wmax
<solid>
4 >>dimension
swap >>name
swap
{
[ { 1 0 0 0 } coord-min ] [ { -1 0 0 0 } coord-max ]
[ { 0 1 0 0 } coord-min ] [ { 0 -1 0 0 } coord-max ]
[ { 0 0 1 0 } coord-min ] [ { 0 0 -1 0 } coord-max ]
[ { 0 0 0 1 } coord-min ] [ { 0 0 0 -1 } coord-max ]
}
[ curry call ] 2map
[ cut-solid ] each
ensure-adjacencies
; inline
: 3cube ( array name -- solid )
! array : xmin xmax ymin ymax zmin zmax wmin wmax
<solid>
3 >>dimension
swap >>name
swap
{
[ { 1 0 0 } coord-min ] [ { -1 0 0 } coord-max ]
[ { 0 1 0 } coord-min ] [ { 0 -1 0 } coord-max ]
[ { 0 0 1 } coord-min ] [ { 0 0 -1 } coord-max ]
}
[ curry call ] 2map
[ cut-solid ] each
ensure-adjacencies
; inline
: equation-system-for-normal ( points -- matrix )
unclip [ v- 0 suffix ] curry map
dup first [ drop 1 ] map suffix
;
: normal-vector ( points -- v )
equation-system-for-normal
intersect-hyperplanes ;
: points-to-hyperplane ( points -- hyperplane )
[ normal-vector 0 suffix ] [ first ] bi
translate ;
: refs-to-points ( points faces -- faces )
[ swap [ nth 10 v*n { 100 100 100 } v+ ] curry map ]
with map
;
! V{ { 0.1 0.2 } { 1.1 1.3 } } V{ { 1 0 } { 0 1 } }
! V{ { { 1.1 1.3 } { 0.1 0.2 } } { { 0.1 0.2 } { 1.1 1.3 } } }
: ply-model-path ( -- path )
! "bun_zipper.ply"
"screw2.ply"
temp-file
;
: read-bunny-model ( -- v )
ply-model-path ascii [ parse-model ] with-file-reader
refs-to-points
;
: 3points-to-normal ( seq -- v )
unclip [ v- ] curry map first2 cross normalize
;
: 2-faces-to-prism ( seq seq -- seq )
2dup
[ do-cycle 2 clump ] bi@ concat-nth
! 3 faces rectangulaires
swap prefix
swap prefix
;
: Xpoints-to-prisme ( seq height -- cube )
! from 3 points gives a list of faces representing
! a cube of height "height"
! and of based on the three points
! a face is a group of 3 or mode points.
[ dup dup 3points-to-normal ] dip
v*n [ v+ ] curry map ! 2 eme face triangulaire
2-faces-to-prism
! [ dup number? [ 1 + ] when ] deep-map
! dup keep
;
: Xpoints-to-plane4D ( seq x y -- 4Dplane )
! from 3 points gives a list of faces representing
! a cube in 4th dim
! from x to y (height = y-x)
! and of based on the X points
! a face is a group of 3 or mode points.
'[ [ [ _ suffix ] map ] [ [ _ suffix ] map ] bi ] call
2-faces-to-prism
;
: 3pointsfaces-to-3Dsolidfaces ( seq -- seq )
[ 1 Xpoints-to-prisme [ 100
110 Xpoints-to-plane4D ] map concat ] map
;
: test-figure ( -- solid )
<solid>
2 >>dimension
{ 1 -1 -5 } cut-solid
{ -1 -1 -21 } cut-solid
{ -1 0 -12 } cut-solid
{ 1 2 16 } cut-solid
;
]]
FILE: [[adsoda/tools/tools-docs.factor]] [[! Copyright (C) 2008 Jeff Bigot.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays help.markup help.syntax kernel sequences ;
IN: adsoda.tools
HELP: 3cube
{ $values
{ "array" "array" } { "name" "name" }
{ "solid" "solid" }
}
{ $description "array : xmin xmax ymin ymax zmin zmax"
"returns a 3D solid with given limits"
} ;
HELP: 4cube
{ $values
{ "array" "array" } { "name" "name" }
{ "solid" "solid" }
}
{ $description "array : xmin xmax ymin ymax zmin zmax wmin wmax"
"returns a 4D solid with given limits"
} ;
HELP: equation-system-for-normal
{ $values
{ "points" "a list of n points" }
{ "matrix" "matrix" }
}
{ $description "From a list of points, return the matrix"
"to solve in order to find the vector normal to the plan defined by the points" }
;
HELP: normal-vector
{ $values
{ "points" "a list of n points" }
{ "v" "a vector" }
}
{ $description "From a list of points, returns the vector normal to the plan defined by the points"
"With n points, creates n-1 vectors and then find a vector orthogonal to every others"
"returns { f } if a normal vector can not be found" }
;
HELP: points-to-hyperplane
{ $values
{ "points" "a list of n points" }
{ "hyperplane" "an hyperplane equation" }
}
{ $description "From a list of points, returns the equation of the hyperplan"
"Finds a normal vector and then translate it so that it includes one of the points"
}
;
ARTICLE: "adsoda.tools" "Tools"
{ $vocab-link "adsoda.tools" }
"Tools to help in building an " { $vocab-link "adsoda" } "-space"
;
ABOUT: "adsoda.tools"
]]
FILE: [[adsoda/tools/authors.txt]] [[Jeff Bigot
]]
FILE: [[adsoda/tools/tools-tests.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING:
adsoda.tools
tools.test
;
IN: adsoda.tools.tests
[ { 1 0 } ] [ { { 0 0 } { 0 1 } } normal-vector ] unit-test
[ f ] [ { { 0 0 } { 0 0 } } normal-vector ] unit-test
[ { 1/2 1/2 1+1/2 } ] [ { { 1 2 } { 2 1 } } points-to-hyperplane ] unit-test
]]
FILE: [[adsoda/adsoda.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING: accessors
arrays
assocs
combinators
kernel
fry
math
math.constants
math.functions
math.libm
math.order
math.vectors
math.matrices
math.parser
namespaces
prettyprint
sequences
sequences.deep
sets
slots
sorting
tools.time
vars
continuations
words
opengl
opengl.gl
colors
adsoda.solution2
adsoda.combinators
opengl.demo-support
values
tools.walker
;
IN: adsoda
DEFER: combinations
VAR: pv
! -------------------------------------------------------------
! global values
VALUE: remove-hidden-solids?
VALUE: VERY-SMALL-NUM
VALUE: ZERO-VALUE
VALUE: MAX-FACE-PER-CORNER
t \ remove-hidden-solids? set-value
0.0000001 \ VERY-SMALL-NUM set-value
0.0000001 \ ZERO-VALUE set-value
4 \ MAX-FACE-PER-CORNER set-value
! -------------------------------------------------------------
! sequence complement
: with-pv ( i quot -- ) [ swap >pv call ] with-scope ; inline
: dimension ( array -- x ) length 1 - ; inline
: change-last ( seq quot -- )
[ [ dimension ] keep ] dip change-nth ; inline
! -------------------------------------------------------------
! light
! -------------------------------------------------------------
TUPLE: light name { direction array } color ;
: <light> ( -- tuple ) light new ;
! -------------------------------------------------------------
! halfspace manipulation
! -------------------------------------------------------------
: constant+ ( v x -- w ) '[ [ _ + ] change-last ] keep ;
: translate ( u v -- w ) dupd v* sum constant+ ;
: transform ( u matrix -- w )
[ swap m.v ] 2keep ! compute new normal vector
[
[ [ abs ZERO-VALUE > ] find ] keep
! find a point on the frontier
! be sure it's not null vector
last ! get constant
swap /f neg swap ! intercept value
] dip
flip
nth
[ * ] with map ! apply intercep value
over v*
sum neg
suffix ! add value as constant at the end of equation
;
: position-point ( halfspace v -- x )
-1 suffix v* sum ; inline
: point-inside-halfspace? ( halfspace v -- ? )
position-point VERY-SMALL-NUM > ;
: point-inside-or-on-halfspace? ( halfspace v -- ? )
position-point VERY-SMALL-NUM neg > ;
: project-vector ( seq -- seq )
pv> [ head ] [ 1 + tail ] 2bi append ;
: get-intersection ( matrice -- seq )
[ 1 tail* ] map flip first ;
: islenght=? ( seq n -- seq n ? ) 2dup [ length ] [ = ] bi* ;
: compare-nleft-to-identity-matrix ( seq n -- ? )
[ [ head ] curry map ] keep identity-matrix m-
flatten
[ abs ZERO-VALUE < ] all?
;
: valid-solution? ( matrice n -- ? )
islenght=?
[ compare-nleft-to-identity-matrix ]
[ 2drop f ] if ; inline
: intersect-hyperplanes ( matrice -- seq )
[ solution dup ] [ first dimension ] bi
valid-solution? [ get-intersection ] [ drop f ] if ;
! -------------------------------------------------------------
! faces
! -------------------------------------------------------------
TUPLE: face { halfspace array }
touching-corners adjacent-faces ;
: <face> ( v -- tuple ) face new swap >>halfspace ;
: flip-face ( face -- face ) [ vneg ] change-halfspace ;
: erase-face-touching-corners ( face -- face )
f >>touching-corners ;
: erase-face-adjacent-faces ( face -- face )
f >>adjacent-faces ;
: faces-intersection ( faces -- v )
[ halfspace>> ] map intersect-hyperplanes ;
: face-translate ( face v -- face )
[ translate ] curry change-halfspace ; inline
: face-transform ( face m -- face )
[ transform ] curry change-halfspace ; inline
: face-orientation ( face -- x ) pv> swap halfspace>> nth sgn ;
: backface? ( face -- face ? ) dup face-orientation 0 <= ;
: pv-factor ( face -- f face )
halfspace>> [ pv> swap nth [ * ] curry ] keep ; inline
: suffix-touching-corner ( face corner -- face )
[ suffix ] curry change-touching-corners ; inline
: real-face? ( face -- ? )
[ touching-corners>> length ]
[ halfspace>> dimension ] bi >= ;
: (add-to-adjacent-faces) ( face face -- face )
over adjacent-faces>> 2dup member?
[ 2drop ] [ swap suffix >>adjacent-faces ] if ;
: add-to-adjacent-faces ( face face -- face )
2dup = [ drop ] [ (add-to-adjacent-faces) ] if ;
: update-adjacent-faces ( faces corner -- )
'[ [ _ suffix-touching-corner drop ] each ] keep
2 among [
[ first ] keep second
[ add-to-adjacent-faces drop ] 2keep
swap add-to-adjacent-faces drop
] each ; inline
: face-project-dim ( face -- x ) halfspace>> length 2 - ;
: apply-light ( color light normal -- u )
over direction>> v.
neg dup 0 >
[
[ color>> swap ] dip
[ * ] curry map v+
[ 1 min ] map
]
[ 2drop ]
if
;
: enlight-projection ( array face -- color )
! array = lights + ambient color
[ [ third ] [ second ] [ first ] tri ]
[ halfspace>> project-vector normalize ] bi*
[ apply-light ] curry each
v*
;
: (intersection-into-face) ( face-init face-adja quot -- face )
[
[ [ pv-factor ] bi@
roll
[ map ] 2bi@
v-
] 2keep
[ touching-corners>> ] bi@
[ swap [ = ] curry find nip f = ] curry find nip
] dip over
[
call
dupd
point-inside-halfspace? [ vneg ] unless
<face>
] [ 3drop f ] if
; inline
: intersection-into-face ( face-init face-adja -- face )
[ [ project-vector ] bi@ ] (intersection-into-face) ;
: intersection-into-silhouette-face ( face-init face-adja -- face )
[ ] (intersection-into-face) ;
: intersections-into-faces ( face -- faces )
clone dup
adjacent-faces>> [ intersection-into-face ] with map
sift ;
: (face-silhouette) ( face -- faces )
clone dup adjacent-faces>>
[ backface?
[ intersection-into-silhouette-face ] [ 2drop f ] if
] with map
sift
; inline
: face-silhouette ( face -- faces )
backface? [ drop f ] [ (face-silhouette) ] if ;
! --------------------------------
! solid
! -------------------------------------------------------------
TUPLE: solid dimension silhouettes
faces corners adjacencies-valid color name ;
: <solid> ( -- tuple ) solid new ;
: suffix-silhouettes ( solid silhouette -- solid )
[ suffix ] curry change-silhouettes ;
: suffix-face ( solid face -- solid )
[ suffix ] curry change-faces ;
: suffix-corner ( solid corner -- solid )
[ suffix ] curry change-corners ;
: erase-solid-corners ( solid -- solid ) f >>corners ;
: erase-silhouettes ( solid -- solid )
dup dimension>> f <array> >>silhouettes ;
: filter-real-faces ( solid -- solid )
[ [ real-face? ] filter ] change-faces ;
: initiate-solid-from-face ( face -- solid )
face-project-dim <solid> swap >>dimension ;
: erase-old-adjacencies ( solid -- solid )
erase-solid-corners
[ dup [ erase-face-touching-corners
erase-face-adjacent-faces drop ] each ]
change-faces ;
: point-inside-or-on-face? ( face v -- ? )
[ halfspace>> ] dip point-inside-or-on-halfspace? ;
: point-inside-face? ( face v -- ? )
[ halfspace>> ] dip point-inside-halfspace? ;
: point-inside-solid? ( solid point -- ? )
[ faces>> ] dip [ point-inside-face? ] curry all? ; inline
: point-inside-or-on-solid? ( solid point -- ? )
[ faces>> ] dip
[ point-inside-or-on-face? ] curry all? ; inline
: unvalid-adjacencies ( solid -- solid )
erase-old-adjacencies f >>adjacencies-valid
erase-silhouettes ;
: add-face ( solid face -- solid )
suffix-face unvalid-adjacencies ;
: cut-solid ( solid halfspace -- solid ) <face> add-face ;
: slice-solid ( solid face -- solid1 solid2 )
[ [ clone ] bi@ flip-face add-face
[ "/outer/" append ] change-name ] 2keep
add-face [ "/inner/" append ] change-name ;
! -------------
: add-silhouette ( solid -- solid )
dup
! find-adjacencies
faces>> { }
[ face-silhouette append ] reduce
sift
<solid>
swap >>faces
over dimension>> >>dimension
over name>> " silhouette " append
pv> number>string append
>>name
! ensure-adjacencies
suffix-silhouettes ; inline
: find-silhouettes ( solid -- solid )
{ } >>silhouettes
dup dimension>> [ [ add-silhouette ] with-pv ] each ;
: ensure-silhouettes ( solid -- solid )
dup silhouettes>> [ f = ] all?
[ find-silhouettes ] when ;
! ------------
: corner-added? ( solid corner -- ? )
! add corner to solid if it is inside solid
[ ]
[ point-inside-or-on-solid? ]
[ swap corners>> member? not ]
2tri and
[ suffix-corner drop t ] [ 2drop f ] if ;
: process-corner ( solid faces corner -- )
swapd
[ corner-added? ] keep swap ! test if corner is inside solid
[ update-adjacent-faces ]
[ 2drop ]
if ;
: compute-intersection ( solid faces -- )
dup faces-intersection
dup f = [ 3drop ] [ process-corner ] if ;
: test-faces-combinaisons ( solid n -- )
[ dup faces>> ] dip among
[ compute-intersection ] with each ;
: compute-adjacencies ( solid -- solid )
dup dimension>> [ >= ] curry
[ keep swap ] curry MAX-FACE-PER-CORNER swap
[ [ test-faces-combinaisons ] 2keep 1 - ] while drop ;
: find-adjacencies ( solid -- solid )
erase-old-adjacencies
compute-adjacencies
filter-real-faces
t >>adjacencies-valid ;
: ensure-adjacencies ( solid -- solid )
dup adjacencies-valid>>
[ find-adjacencies ] unless
ensure-silhouettes
;
: (non-empty-solid?) ( solid -- ? )
[ dimension>> ] [ corners>> length ] bi < ;
: non-empty-solid? ( solid -- ? )
ensure-adjacencies (non-empty-solid?) ;
: compare-corners-roughly ( corner corner -- ? )
2drop t ;
! : remove-inner-faces ( -- ) ;
: face-project ( array face -- seq )
backface?
[ 2drop f ]
[ [ enlight-projection ]
[ initiate-solid-from-face ]
[ intersections-into-faces ] tri
>>faces
swap >>color
] if ;
: solid-project ( lights ambient solid -- solids )
ensure-adjacencies
[ color>> ] [ faces>> ] bi [ 3array ] dip
[ face-project ] with map
sift
[ ensure-adjacencies ] map
;
: (solid-move) ( solid v move -- solid )
curry [ map ] curry
[ dup faces>> ] dip call drop
unvalid-adjacencies ; inline
: solid-translate ( solid v -- solid )
[ face-translate ] (solid-move) ;
: solid-transform ( solid m -- solid )
[ face-transform ] (solid-move) ;
: find-corner-in-silhouette ( s1 s2 -- elt bool )
pv> swap silhouettes>> nth
swap corners>>
[ point-inside-solid? ] with find swap ;
: valid-face-for-order ( solid point -- face )
[ point-inside-face? not ]
[ drop face-orientation 0 = not ] 2bi and ;
: check-orientation ( s1 s2 pt -- int )
[ nip faces>> ] dip
[ valid-face-for-order ] curry find swap
[ face-orientation ] [ drop f ] if ;
: (order-solid) ( s1 s2 -- int )
2dup find-corner-in-silhouette
[ check-orientation ] [ 3drop f ] if ;
: order-solid ( solid solid -- i )
2dup (order-solid)
[ 2nip ]
[ swap (order-solid)
[ neg ] [ f ] if*
] if* ;
: subtract ( solid1 solid2 -- solids )
faces>> swap clone ensure-adjacencies ensure-silhouettes
[ swap slice-solid drop ] curry map
[ non-empty-solid? ] filter
[ ensure-adjacencies ] map
; inline
! -------------------------------------------------------------
! space
! -------------------------------------------------------------
TUPLE: space name dimension solids ambient-color lights ;
: <space> ( -- space ) space new ;
: suffix-solids ( space solid -- space )
[ suffix ] curry change-solids ; inline
: suffix-lights ( space light -- space )
[ suffix ] curry change-lights ; inline
: clear-space-solids ( space -- space ) f >>solids ;
: space-ensure-solids ( space -- space )
[ [ ensure-adjacencies ] map ] change-solids ;
: eliminate-empty-solids ( space -- space )
[ [ non-empty-solid? ] filter ] change-solids ;
: projected-space ( space solids -- space )
swap dimension>> 1 - <space>
swap >>dimension swap >>solids ;
: get-silhouette ( solid -- silhouette )
silhouettes>> pv> swap nth ;
: solid= ( solid solid -- ? ) [ corners>> ] same? ;
: space-apply ( space m quot -- space )
curry [ map ] curry [ dup solids>> ] dip
[ call ] [ 2drop ] recover drop ; inline
: space-transform ( space m -- space )
[ solid-transform ] space-apply ;
: space-translate ( space v -- space )
[ solid-translate ] space-apply ;
: describe-space ( space -- )
solids>>
[ [ corners>> [ pprint ] each ] [ name>> . ] bi ] each ;
: clip-solid ( solid solid -- solids )
[ ]
[ solid= not ]
[ order-solid -1 = ] 2tri
and
[ get-silhouette subtract ]
[ drop 1array ]
if
;
: (solids-silhouette-subtract) ( solids solid -- solids )
[ clip-solid append ] curry { } -rot each ; inline
: solids-silhouette-subtract ( solids i solid -- solids )
! solids is an array of 1 solid arrays
[ (solids-silhouette-subtract) ] curry map-but
; inline
: remove-hidden-solids ( space -- space )
! We must include each solid in a sequence because
! during substration
! a solid can be divided in more than on solid
[
[ [ 1array ] map ]
[ length ]
[ ]
tri
[ solids-silhouette-subtract ] 2each
{ } [ append ] reduce
] change-solids
eliminate-empty-solids ! TODO include into change-solids
;
: space-project ( space i -- space )
[
[ clone
remove-hidden-solids? [ remove-hidden-solids ] when
dup
[ solids>> ]
[ lights>> ]
[ ambient-color>> ] tri
[ rot solid-project ] 2curry
map
[ append ] { } -rot each
! TODO project lights
projected-space
! remove-inner-faces
!
eliminate-empty-solids
] with-pv
] [ 3drop <space> ] recover
; inline
: middle-of-space ( space -- point )
solids>> [ corners>> ] map concat
[ [ ] [ v+ ] map-reduce ] [ length ] bi v/n
;
! -------------------------------------------------------------
! 3D rendering
! -------------------------------------------------------------
: face-reference ( face -- halfspace point vect )
[ halfspace>> ]
[ touching-corners>> first ]
[ touching-corners>> second ] tri
over v-
;
: theta ( v halfspace point vect -- v x )
[ [ over ] dip v- ] dip
[ cross dup norm >float ]
[ v. >float ]
2bi
fatan2
-rot v.
0 < [ neg ] when
;
: ordered-face-points ( face -- corners )
[ touching-corners>> 1 head ]
[ touching-corners>> 1 tail ]
[ face-reference [ theta ] 3curry ] tri
{ } map>assoc sort-values keys
append
; inline
: point->GL ( point -- ) gl-vertex ;
: points->GL ( array -- ) do-cycle [ point->GL ] each ;
: face->GL ( face color -- )
[ ordered-face-points ] dip
[ first3 1.0 glColor4d GL_POLYGON
[ [ point->GL ] each ] do-state ] curry
[ 0 0 0 1 glColor4d GL_LINE_LOOP
[ [ point->GL ] each ] do-state ]
bi
; inline
: solid->GL ( solid -- )
[ faces>> ]
[ color>> ] bi
[ face->GL ] curry each ; inline
: space->GL ( space -- )
solids>>
[ solid->GL ] each ;
]]
FILE: [[adsoda/combinators/combinators.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING: kernel arrays sequences fry math combinators ;
IN: adsoda.combinators
! : (combinations) ( seq -- seq ) [ 1 tail ] dip combinations ;
! : prefix-each [ prefix ] curry map ; inline
! : combinations ( seq n -- seqs )
! {
! { [ dup 0 = ] [ 2drop { { } } ] }
! { [ over empty? ] [ 2drop { } ] }
! { [ t ] [
! [ [ 1 - (combinations) ] [ drop first ] 2bi prefix-each ]
! [ (combinations) ] 2bi append
! ] }
! } cond ;
: columnize ( array -- array ) [ 1array ] map ; inline
: among ( array n -- array )
2dup swap length
{
{ [ over 1 = ] [ 3drop columnize ] }
{ [ over 0 = ] [ 4drop { } ] }
{ [ 2dup < ] [ 2drop [ 1 cut ] dip
[ 1 - among [ append ] with map ]
[ among append ] 2bi
] }
{ [ 2dup = ] [ 3drop 1array ] }
{ [ 2dup > ] [ 4drop { } ] }
} cond
;
: concat-nth ( seq1 seq2 -- seq )
[ nth append ] curry map-index ;
: do-cycle ( array -- array ) dup first suffix ;
: map-but ( seq i quot -- seq )
! quot : ( seq x -- seq )
'[ _ = [ @ ] unless ] map-index ; inline
]]
FILE: [[adsoda/combinators/combinators-tests.factor]] [[USING: adsoda.combinators
sequences
tools.test
;
IN: adsoda.combinators.tests
[ { "atoto" "b" "ctoto" } ] [ { "a" "b" "c" } 1 [ "toto" append ] map-but ]
unit-test
]]
FILE: [[adsoda/combinators/authors.txt]] [[JF Bigot, after Greg Ferrar]]
FILE: [[adsoda/combinators/combinators-docs.factor]] [[! Copyright (C) 2008 Jeff Bigot.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays help.markup help.syntax kernel sequences ;
IN: adsoda.combinators
HELP: among
{ $values
{ "array" array } { "n" "number of value to select" }
{ "array" array }
}
{ $description "returns an array containings every possibilities of n choices among a given sequence" } ;
HELP: columnize
{ $values
{ "array" array }
{ "array" array }
}
{ $description "flip a sequence into a sequence of 1 element sequences" } ;
HELP: concat-nth
{ $values
{ "seq1" sequence } { "seq2" sequence }
{ "seq" sequence }
}
{ $description "merges 2 sequences of sequences appending corresponding elements" } ;
HELP: do-cycle
{ $values
{ "array" array }
{ "array" array }
}
{ $description "Copy the first element at the end of the sequence in order to close the cycle." } ;
ARTICLE: "adsoda.combinators" "Combinators"
{ $vocab-link "adsoda.combinators" }
;
ABOUT: "adsoda.combinators"
]]
FILE: [[adsoda/adsoda-docs.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax ;
IN: adsoda
! --------------------------------------------------------------
! faces
! --------------------------------------------------------------
ARTICLE: "face-page" "Face in ADSODA"
"explanation of faces"
$nl
"link to functions" $nl
"what is an halfspace" $nl
"halfspace touching-corners adjacent-faces" $nl
"touching-corners list of pointers to the corners which touch this face" $nl
"adjacent-faces list of pointers to the faces which touch this face"
{ $subsections
face
<face>
}
"test relative position"
{ $subsections
point-inside-or-on-face?
point-inside-face?
}
"handling face"
{ $subsections
flip-face
face-translate
face-transform
}
;
HELP: face
{ $class-description "a face is defined by"
{ $list "halfspace equation" }
{ $list "list of touching corners" }
{ $list "list of adjacent faces" }
$nl
"Touching corners and adjacent faces are defined by algorithm thanks to other faces of the solid"
}
;
HELP: <face>
{ $values { "v" "an halfspace equation" } { "tuple" "a face" } } ;
HELP: flip-face
{ $values { "face" "a face" } { "face" "flipped face" } }
{ $description "change the orientation of a face" }
;
HELP: face-translate
{ $values { "face" "a face" } { "v" "a vector" } }
{ $description
"translate a face following a vector"
$nl
"a translation of an halfspace doesn't change the normal vector. this word just compute the new constant term" }
;
HELP: face-transform
{ $values { "face" "a face" } { "m" "a transformation matrix" } }
{ $description "compute the transformation of a face using a transformation matrix" }
;
! --------------------------------
! solid
! --------------------------------------------------------------
ARTICLE: "solid-page" "Solid in ADSODA"
"explanation of solids"
$nl
"link to functions"
{ $subsections
solid
<solid>
}
"test relative position"
{ $subsections
point-inside-solid?
point-inside-or-on-solid?
}
"playing with faces and solids"
{ $subsections
add-face
cut-solid
slice-solid
}
"solid handling"
{ $subsections
solid-project
solid-translate
solid-transform
subtract
get-silhouette
solid=
}
;
HELP: solid
{ $class-description "dimension" $nl "silhouettes" $nl "faces" $nl "corners" $nl "adjacencies-valid" $nl "color" $nl "name"
}
;
HELP: add-face
{ $values { "solid" "a solid" } { "face" "a face" } }
{ $description "reshape a solid with a face. The face truncate the solid." } ;
HELP: cut-solid
{ $values { "solid" "a solid" } { "halfspace" "an halfspace" } }
{ $description "like add-face but just with halfspace equation" } ;
HELP: slice-solid
{ $values { "solid" "a solid" } { "face" "a face" } { "solid1" "the outer part of the former solid" } { "solid2" "the inner part of the former solid" } }
{ $description "cut a solid into two parts. The face acts like a knife"
} ;
HELP: solid-project
{ $values { "lights" "lights" } { "ambient" "ambient" } { "solid" "solid" } { "solids" "projection of solid" } }
{ $description "Project the solid using pv vector"
$nl
"TODO: explain how to use lights"
} ;
HELP: solid-translate
{ $values { "solid" "a solid" } { "v" "translating vector" } }
{ $description "Translate a solid using a vector"
$nl
"v and solid must have the same dimension "
} ;
HELP: solid-transform
{ $values { "solid" "a solid" } { "m" "transformation matrix" } }
{ $description "Transform a solid using a matrix"
$nl
"v and solid must have the same dimension "
} ;
HELP: subtract
{ $values { "solid1" "initial shape" } { "solid2" "shape to remove" } { "solids" "resulting shape" } }
{ $description "Substract solid2 from solid1" } ;
! --------------------------------------------------------------
! space
! --------------------------------------------------------------
ARTICLE: "space-page" "Space in ADSODA"
"A space is a collection of solids and lights."
$nl
"link to functions"
$nl
"Defining words"
{ $subsections
space
<space>
suffix-solids
suffix-lights
clear-space-solids
describe-space
}
"Handling space"
{ $subsections
space-ensure-solids
eliminate-empty-solids
space-transform
space-translate
remove-hidden-solids
space-project
}
;
HELP: space
{ $class-description
"dimension" $nl " solids" $nl " ambient-color" $nl "lights"
}
;
HELP: suffix-solids
"( space solid -- space )"
{ $values { "space" "a space" } { "solid" "a solid to add" } }
{ $description "Add solid to space definition" } ;
HELP: suffix-lights
"( space light -- space ) "
{ $values { "space" "a space" } { "light" "a light to add" } }
{ $description "Add a light to space definition" } ;
HELP: clear-space-solids
"( space -- space )"
{ $values { "space" "a space" } }
{ $description "remove all solids in space" } ;
HELP: space-ensure-solids
{ $values { "space" "a space" } }
{ $description "rebuild corners of all solids in space" } ;
HELP: space-transform
{ $values { "space" "a space" } { "m" "a matrix" } }
{ $description "Transform a space using a matrix" } ;
HELP: space-translate
{ $values { "space" "a space" } { "v" "a vector" } }
{ $description "Translate a space following a vector" } ;
HELP: describe-space
{ $values { "space" "a space" } }
{ $description "return a description of space" } ;
HELP: space-project
{ $values { "space" "a space" } { "i" "an integer" } }
{ $description "Project a space along ith coordinate" } ;
! --------------------------------------------------------------
! 3D rendering
! --------------------------------------------------------------
ARTICLE: "3D-rendering-page" "The 3D rendering in ADSODA"
"explanation of 3D rendering"
$nl
"link to functions"
{ $subsections
face->GL
solid->GL
space->GL
}
;
HELP: face->GL
{ $values { "face" "a face" } { "color" "3 3 values array" } }
{ $description "display a face" } ;
HELP: solid->GL
{ $values { "solid" "a solid" } }
{ $description "display a solid" } ;
HELP: space->GL
{ $values { "space" "a space" } }
{ $description "display a space" } ;
! --------------------------------------------------------------
! light
! --------------------------------------------------------------
ARTICLE: "light-page" "Light in ADSODA"
"explanation of light"
$nl
"link to functions"
;
ARTICLE: { "adsoda" "light" } "ADSODA : lights"
{ $code """
! HELP: light position color
! <light> ( -- tuple ) light new ;
! light est un vecteur avec 3 variables pour les couleurs\n
void Light::Apply(Vector& normal, double &cRed, double &cGreen, double &cBlue)\n
{ \n
// Dot the light direction with the normalized normal of Face.
register double intensity = -(normal * (*this));
// Face is a backface, from light's perspective
if (intensity < 0)
return;
// Add the intensity componentwise
cRed += red * intensity;
cGreen += green * intensity;
cBlue += blue * intensity;
// Clip to unit range
if (cRed > 1.0) cRed = 1.0;
if (cGreen > 1.0) cGreen = 1.0;
if (cBlue > 1.0) cBlue = 1.0;
""" }
;
ARTICLE: { "adsoda" "halfspace" } "ADSODA : halfspace"
" defined by the concatenation of the normal vector and a constant"
;
ARTICLE: "adsoda-main-page" "ADSODA : Arbitrary-Dimensional Solid Object Display Algorithm"
"multidimensional handler :"
$nl
"design a solid using face delimitations. Only works on convex shapes"
$nl
{ $emphasis "written in C++ by Greg Ferrar" }
$nl
"full explanation on adsoda page at " { $url "http://www.flowerfire.com/ADSODA/" }
$nl
"Useful words are describe on the following pages: "
{ $subsections
"face-page"
"solid-page"
"space-page"
"light-page"
"3D-rendering-page"
} ;
ABOUT: "adsoda-main-page"
]]
FILE: [[adsoda/summary.txt]] [[ADSODA : Arbitrary-Dimensional Solid Object Display Algorithm]]
FILE: [[adsoda/adsoda-tests.factor]] [[USING: adsoda
kernel
math
accessors
sequences
adsoda.solution2
fry
tools.test
arrays ;
IN: adsoda.tests
: s1 ( -- solid )
<solid>
2 >>dimension
"s1" >>name
{ 1 1 1 } >>color
{ 1 -1 -5 } cut-solid
{ -1 -1 -21 } cut-solid
{ -1 0 -12 } cut-solid
{ 1 2 16 } cut-solid
;
: solid1 ( -- solid )
<solid>
2 >>dimension
"solid1" >>name
{ 1 -1 -5 } cut-solid
{ -1 -1 -21 } cut-solid
{ -1 0 -12 } cut-solid
{ 1 2 16 } cut-solid
ensure-adjacencies
;
: solid2 ( -- solid )
<solid>
2 >>dimension
"solid2" >>name
{ -1 1 -10 } cut-solid
{ -1 -1 -28 } cut-solid
{ 1 0 13 } cut-solid
! { 1 2 16 } cut-solid
ensure-adjacencies
;
: solid3 ( -- solid )
<solid>
2 >>dimension
"solid3" >>name
{ 1 1 1 } >>color
{ 1 0 16 } cut-solid
{ -1 0 -36 } cut-solid
{ 0 1 1 } cut-solid
{ 0 -1 -17 } cut-solid
! { 1 2 16 } cut-solid
ensure-adjacencies
;
: solid4 ( -- solid )
<solid>
2 >>dimension
"solid4" >>name
{ 1 1 1 } >>color
{ 1 0 21 } cut-solid
{ -1 0 -36 } cut-solid
{ 0 1 1 } cut-solid
{ 0 -1 -17 } cut-solid
ensure-adjacencies
;
: solid5 ( -- solid )
<solid>
2 >>dimension
"solid5" >>name
{ 1 1 1 } >>color
{ 1 0 6 } cut-solid
{ -1 0 -17 } cut-solid
{ 0 1 17 } cut-solid
{ 0 -1 -19 } cut-solid
ensure-adjacencies
;
: solid7 ( -- solid )
<solid>
2 >>dimension
"solid7" >>name
{ 1 1 1 } >>color
{ 1 0 38 } cut-solid
{ 1 -5 -66 } cut-solid
{ -2 1 -75 } cut-solid
ensure-adjacencies
;
: solid6s ( -- seq )
solid3 clone solid2 clone subtract
;
: space1 ( -- space )
<space>
2 >>dimension
! solid3 suffix-solids
solid1 suffix-solids
solid2 suffix-solids
! solid6s [ suffix-solids ] each
solid4 suffix-solids
! solid5 suffix-solids
solid7 suffix-solids
{ 1 1 1 } >>ambient-color
<light>
{ -100 -100 } >>position
{ 0.2 0.7 0.1 } >>color
suffix-lights
;
: space2 ( -- space )
<space>
4 >>dimension
! 4cube suffix-solids
{ 1 1 1 } >>ambient-color
<light>
{ -100 -100 } >>position
{ 0.2 0.7 0.1 } >>color
suffix-lights
;
! {
! { 1 0 0 0 }
! { 0 1 0 0 }
! { 0 0 0.984807753012208 -0.1736481776669303 }
! { 0 0 0.1736481776669303 0.984807753012208 }
! }
! ------------------------------------------------------------
! constant+
[ { 1 2 5 } ] [ { 1 2 3 } 2 constant+ ] unit-test
! ------------------------------------------------------------
! translate
[ { 1 -1 0 } ] [ { 1 -1 -5 } { 3 -2 } translate ] unit-test
! ------------------------------------------------------------
! transform
[ { -1 -1 -5 21.0 } ] [ { -1 -1 -5 21 }
{ { 1 0 0 }
{ 0 1 0 }
{ 0 0 1 }
} transform
] unit-test
! ------------------------------------------------------------
! compare-nleft-to-identity-matrix
[ t ] [
{
{ 1 0 0 1232 }
{ 0 1 0 0 321 }
{ 0 0 1 0 } }
3 compare-nleft-to-identity-matrix
] unit-test
[ f ] [
{ { 1 0 0 } { 0 1 0 } { 0 0 0 } }
3 compare-nleft-to-identity-matrix
] unit-test
[ f ] [
{ { 2 0 0 } { 0 1 0 } { 0 0 1 } }
3 compare-nleft-to-identity-matrix
] unit-test
! ------------------------------------------------------------
[ t ] [
{ { 1 0 0 }
{ 0 1 0 }
{ 0 0 1 } } 3 valid-solution?
] unit-test
[ f ] [
{ { 1 0 0 1 }
{ 0 0 0 1 }
{ 0 0 1 0 } } 3 valid-solution?
] unit-test
[ f ] [
{ { 1 0 0 1 }
{ 0 0 0 1 } } 3 valid-solution?
] unit-test
[ f ] [
{ { 1 0 0 1 }
{ 0 0 0 1 }
{ 0 0 1 0 } } 2 valid-solution?
] unit-test
! ------------------------------------------------------------
[ 3 ] [ { 1 2 3 } last ] unit-test
[ { 1 2 5 } ] [ { 1 2 3 } dup [ 2 + ] change-last ] unit-test
! ------------------------------------------------------------
! position-point
[ 0 ] [
{ 1 -1 -5 } { 2 7 } position-point
] unit-test
! ------------------------------------------------------------
! transform
! TODO construire un exemple
! ------------------------------------------------------------
! slice-solid
! ------------------------------------------------------------
! solve-equation
! deux cas de tests, avec solution et sans solution
[ { 2 7 } ]
[ { { 1 -1 -5 } { 1 2 16 } } intersect-hyperplanes ]
unit-test
[ f ]
[ { { 1 -1 -5 } { 1 2 16 } { -1 -1 -21 } } intersect-hyperplanes ]
unit-test
[ f ]
[ { { 1 0 -5 } { 1 0 16 } } intersect-hyperplanes ]
unit-test
! ------------------------------------------------------------
! point-inside-halfspace
[ t ] [ { 1 -1 -5 } { 0 0 } point-inside-halfspace? ]
unit-test
[ f ] [ { 1 -1 -5 } { 8 13 } point-inside-halfspace? ]
unit-test
[ t ] [ { 1 -1 -5 } { 8 13 } point-inside-or-on-halfspace? ]
unit-test
! ------------------------------
! order solid
[ 1 ] [ 0 >pv solid1 solid2 order-solid ] unit-test
[ -1 ] [ 0 >pv solid2 solid1 order-solid ] unit-test
[ f ] [ 1 >pv solid1 solid2 order-solid ] unit-test
[ f ] [ 1 >pv solid2 solid1 order-solid ] unit-test
! clip-solid
[ { { 13 15 } { 15 13 } { 13 13 } } ]
[ 0 >pv solid2 solid1 clip-solid first corners>> ] unit-test
solid1 corners>> '[ _ ]
[ 0 >pv solid1 solid1 clip-solid first corners>> ] unit-test
solid1 corners>> '[ _ ]
[ 0 >pv solid1 solid2 clip-solid first corners>> ] unit-test
solid1 corners>> '[ _ ]
[ 1 >pv solid1 solid2 clip-solid first corners>> ] unit-test
solid2 corners>> '[ _ ]
[ 1 >pv solid2 solid1 clip-solid first corners>> ] unit-test
!
[
{
{ { 13 15 } { 15 13 } { 13 13 } }
{ { 16 17 } { 16 13 } { 36 17 } { 36 13 } }
{ { 16 1 } { 16 2 } { 36 1 } { 36 2 } }
}
] [ 0 >pv solid2 solid3 2array
solid1 (solids-silhouette-subtract)
[ corners>> ] map
] unit-test
[
{
{ { 8 13 } { 2 7 } { 12 9 } { 12 2 } }
{ { 13 15 } { 15 13 } { 13 13 } }
{ { 16 17 } { 16 15 } { 36 17 } { 36 15 } }
{ { 16 1 } { 16 2 } { 36 1 } { 36 2 } }
}
] [
0 >pv <space> solid1 suffix-solids
solid2 suffix-solids
solid3 suffix-solids
remove-hidden-solids
solids>> [ corners>> ] map
] unit-test
! { }
! { }
! <light> { 0.2 0.3 0.4 } >>color { 1 -1 1 } >>direction suffix
! <light> { 0.4 0.3 0.1 } >>color { -1 -1 -1 } >>direction suffix
! suffix
! { 0.1 0.1 0.1 } suffix ! ambient color
! { 0.23 0.32 0.17 } suffix ! solid color
! solid3 faces>> first
! enlight-projection
]]
FILE: [[adsoda/adsoda.tests]] [[! : init-4D-demo ( -- space )
! OK
! espace de dimension 4 et de couleur 0,3 0.3 0.3
<space>
4 >>dimension
{ 0.3 0.3 0.3 } >>ambient-color
{ 100 150 100 150 100 150 100 150 } "4cube1" 4cube suffix-solids
{ 160 180 160 180 160 180 160 180 } "4cube2" 4cube suffix-solids
<light>
{ -100 -100 -100 -100 } >>position
{ 0.2 0.7 0.1 } >>color
suffix-lights
! ;
! : init-3D-demo ( -- space )
! OK
! espace de dimension 4 et de couleur 0,3 0.3 0.3
<space>
3 >>dimension
{ 0.3 0.3 0.3 } >>ambient-color
{ 100 150 100 150 100 150 } "3cube1" 3cube suffix-solids
! { -150 -10 -150 -10 -150 -10 -150 -10 } "4cube2" 4cube suffix-solids
<light>
{ -100 -100 -100 -100 } >>position
{ 0.2 0.7 0.1 } >>color
suffix-lights
! ;
: s1 ( -- solid )
<solid>
2 >>dimension
"s1" >>name
{ 1 1 1 } >>color
{ 1 -1 -5 } cut-solid
{ -1 -1 -21 } cut-solid
{ -1 0 -12 } cut-solid
{ 1 2 16 } cut-solid
;
: solid1 ( -- solid )
<solid>
2 >>dimension
"solid1" >>name
{ 1 -1 -5 } cut-solid
{ -1 -1 -21 } cut-solid
{ -1 0 -12 } cut-solid
{ 1 2 16 } cut-solid
ensure-adjacencies
;
: solid2 ( -- solid )
<solid>
2 >>dimension
"solid2" >>name
{ -1 1 -10 } cut-solid
{ -1 -1 -28 } cut-solid
{ 1 0 13 } cut-solid
! { 1 2 16 } cut-solid
ensure-adjacencies
;
: solid3 ( -- solid )
<solid>
2 >>dimension
"solid3" >>name
{ 1 1 1 } >>color
{ 1 0 16 } cut-solid
{ -1 0 -36 } cut-solid
{ 0 1 1 } cut-solid
{ 0 -1 -17 } cut-solid
! { 1 2 16 } cut-solid
ensure-adjacencies
;
: solid4 ( -- solid )
<solid>
2 >>dimension
"solid4" >>name
{ 1 1 1 } >>color
{ 1 0 21 } cut-solid
{ -1 0 -36 } cut-solid
{ 0 1 1 } cut-solid
{ 0 -1 -17 } cut-solid
ensure-adjacencies
;
: solid5 ( -- solid )
<solid>
2 >>dimension
"solid5" >>name
{ 1 1 1 } >>color
{ 1 0 6 } cut-solid
{ -1 0 -17 } cut-solid
{ 0 1 17 } cut-solid
{ 0 -1 -19 } cut-solid
ensure-adjacencies
;
: solid7 ( -- solid )
<solid>
2 >>dimension
"solid7" >>name
{ 1 1 1 } >>color
{ 1 0 38 } cut-solid
{ 1 -5 -66 } cut-solid
{ -2 1 -75 } cut-solid
ensure-adjacencies
;
: solid6s ( -- seq )
solid3 clone solid2 clone subtract
;
: space1 ( -- space )
<space>
2 >>dimension
! solid3 suffix-solids
solid1 suffix-solids
solid2 suffix-solids
! solid6s [ suffix-solids ] each
solid4 suffix-solids
! solid5 suffix-solids
solid7 suffix-solids
{ 1 1 1 } >>ambient-color
<light>
{ -100 -100 } >>position
{ 0.2 0.7 0.1 } >>color
suffix-lights
;
: space2 ( -- space )
<space>
4 >>dimension
! 4cube suffix-solids
{ 1 1 1 } >>ambient-color
<light>
{ -100 -100 } >>position
{ 0.2 0.7 0.1 } >>color
suffix-lights
;
]]
FILE: [[adsoda/authors.txt]] [[Jeff Bigot
Greg Ferrar]]
FILE: [[adsoda/tags.txt]] [[adsoda 4D viewer]]
FILE: [[adsoda/solution2/solution2.factor]] [[USING: kernel
sequences
namespaces
math
math.vectors
math.matrices
;
IN: adsoda.solution2
! -------------------
! correctif solution
! ---------------
SYMBOL: matrix
: MIN-VAL-adsoda ( -- x ) 0.00000001
! 0.000000000001
;
: zero? ( x -- ? )
abs MIN-VAL-adsoda <
;
! [ number>string string>number ] map
: with-matrix ( matrix quot -- )
[ swap matrix set call matrix get ] with-scope ; inline
: nth-row ( row# -- seq ) matrix get nth ;
: change-row ( row# quot -- seq ) ! row# quot -- | quot: seq -- seq )
matrix get swap change-nth ; inline
: exchange-rows ( row# row# -- ) matrix get exchange ;
: rows ( -- n ) matrix get length ;
: cols ( -- n ) 0 nth-row length ;
: skip ( i seq quot -- n )
over [ find-from drop ] dip length or ; inline
: first-col ( row# -- n )
! First non-zero column
0 swap nth-row [ zero? not ] skip ;
: clear-scale ( col# pivot-row i-row -- n )
[ over ] dip nth dup zero? [
3drop 0
] [
[ nth dup zero? ] dip swap [
2drop 0
] [
swap / neg
] if
] if ;
: (clear-col) ( col# pivot-row i -- )
[ [ clear-scale ] 2keep [ n*v ] dip v+ ] change-row ;
: rows-from ( row# -- slice )
rows dup <slice> ;
: clear-col ( col# row# rows -- )
[ nth-row ] dip [ [ 2dup ] dip (clear-col) ] each 2drop ;
: do-row ( exchange-with row# -- )
[ exchange-rows ] keep
[ first-col ] keep
dup 1 + rows-from clear-col ;
: find-row ( row# quot -- i elt )
[ rows-from ] dip find ; inline
: pivot-row ( col# row# -- n )
[ dupd nth-row nth zero? not ] find-row 2nip ;
: (echelon) ( col# row# -- )
over cols < over rows < and [
2dup pivot-row [ over do-row 1 + ] when*
[ 1 + ] dip (echelon)
] [
2drop
] if ;
: echelon ( matrix -- matrix' )
[ 0 0 (echelon) ] with-matrix ;
: nonzero-rows ( matrix -- matrix' )
[ [ zero? ] all? ] reject ;
: null/rank ( matrix -- null rank )
echelon dup length swap nonzero-rows length [ - ] keep ;
: leading ( seq -- n elt ) [ zero? not ] find ;
: reduced ( matrix' -- matrix'' )
[
rows <reversed> [
dup nth-row leading drop
dup [ swap dup clear-col ] [ 2drop ] if
] each
] with-matrix ;
: basis-vector ( row col# -- )
[ clone ] dip
[ swap nth neg recip ] 2keep
[ 0 spin set-nth ] 2keep
[ n*v ] dip
matrix get set-nth ;
: nullspace ( matrix -- seq )
echelon reduced dup empty? [
dup first length identity-matrix [
[
dup leading drop
dup [ basis-vector ] [ 2drop ] if
] each
] with-matrix flip nonzero-rows
] unless ;
: 1-pivots ( matrix -- matrix )
[ dup leading nip [ recip v*n ] when* ] map ;
: solution ( matrix -- matrix )
echelon nonzero-rows reduced 1-pivots ;
]]
FILE: [[adsoda/solution2/summary.txt]] [[A modification of solution to approximate solutions]]
FILE: [[cpu/arm/bootstrap.factor]] [[! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: bootstrap.image.private kernel namespaces system
cpu.arm.assembler math layouts words compiler.units ;
IN: bootstrap.arm
! We generate ARM3 code
f have-BX? set
4 \ cell set
big-endian off
4 jit-code-format set
: ds-reg R5 ;
: word-reg R0 ;
: quot-reg R0 ;
: scan-reg R2 ;
: temp-reg R3 ;
: xt-reg R12 ;
: stack-frame 16 bootstrap-cells ;
: next-save stack-frame 2 bootstrap-cells - ;
: xt-save stack-frame 3 bootstrap-cells - ;
: array-save stack-frame 4 bootstrap-cells - ;
: scan-save stack-frame 5 bootstrap-cells - ;
[
temp-reg quot-reg quot-array@ <+> LDR ! load array
scan-reg temp-reg scan@ ADD ! initialize scan pointer
] { } make jit-setup set
[
LR SP 4 <-> STR ! save return address
SP SP stack-frame SUB
xt-reg SP xt-save <+> STR ! save XT
xt-reg stack-frame MOV
xt-reg SP next-save <+> STR ! save frame size
temp-reg SP array-save <+> STR ! save array
] { } make jit-prolog set
[
temp-reg scan-reg 4 <!+> LDR ! load literal and advance
temp-reg ds-reg 4 <!+> STR ! push literal
] { } make jit-push-literal set
[
temp-reg scan-reg 4 <!+> LDR ! load wrapper and advance
temp-reg dup wrapper@ <+> LDR ! load wrapped object
temp-reg ds-reg 4 <!+> STR ! push wrapped object
] { } make jit-push-wrapper set
[
R1 SP 4 SUB ! pass stack pointer to primitive
] { } make jit-word-primitive-jump set
[
R1 SP 4 SUB ! pass stack pointer to primitive
] { } make jit-word-primitive-call set
: load-word-xt ( -- )
word-reg scan-reg 4 <!+> LDR ! load word and advance
xt-reg word-reg word-xt@ <+> LDR ;
: jit-call
scan-reg SP scan-save <+> STR ! save scan pointer
LR PC MOV ! save return address
xt-reg BX ! call
scan-reg SP scan-save <+> LDR ! restore scan pointer
;
: jit-jump
xt-reg BX ;
[ load-word-xt jit-call ] { } make jit-word-call set
[ load-word-xt jit-jump ] { } make jit-word-jump set
: load-quot-xt
xt-reg quot-reg quot-xt@ <+> LDR ;
: load-branch
temp-reg ds-reg 4 <-!> LDR ! pop boolean
temp-reg \ f tag-number CMP ! compare it with f
quot-reg scan-reg MOV ! point quot-reg at false branch
quot-reg dup 4 EQ ADD ! point quot-reg at true branch
quot-reg dup 4 <+> LDR ! load the branch
scan-reg dup 12 ADD ! advance scan pointer
load-quot-xt
;
[
load-branch jit-jump
] { } make jit-if-jump set
[
load-branch jit-call
] { } make jit-if-call set
[
temp-reg ds-reg 4 <-!> LDR ! pop index
temp-reg dup 1 <LSR> MOV ! turn it into an array offset
scan-reg dup 4 <+> LDR ! load array
temp-reg dup scan-reg ADD ! compute quotation location
quot-reg temp-reg array-start <+> LDR ! load quotation
load-quot-xt
jit-jump
] { } make jit-dispatch set
[
SP SP stack-frame ADD ! pop stack frame
LR SP 4 <-> LDR ! load return address
] { } make jit-epilog set
[ LR BX ] { } make jit-return set
[ "bootstrap.arm" forget-vocab ] with-compilation-unit
]]
FILE: [[cpu/arm/arm.factor]] [[! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types kernel math namespaces
cpu.architecture cpu.arm.architecture cpu.arm.assembler
cpu.arm.intrinsics generator generator.registers continuations
compiler io vocabs sequences system ;
! EABI passes floats in integer registers.
[ alien-float ]
[ >r >r >float r> r> set-alien-float ]
4
"box_float"
"to_float" <primitive-type>
"float" define-primitive-type
[ >float ] "float" c-type set-c-type-prep
[ alien-double ]
[ >r >r >float r> r> set-alien-double ]
8
"box_double"
"to_double" <primitive-type> <long-long-type>
"double" define-primitive-type
[ >float ] "double" c-type set-c-type-prep
T{ arm-backend } compiler-backend set-global
! We don't auto-detect since that would require us to support
! illegal instruction traps. This works on Linux but not on
! Windows CE.
"arm-variant" get [
"ARM variant: " write "arm-variant" get print
] [
"==========" print
"You should specify the -arm-variant=<variant> switch." print
"<variant> can be one of arm3, arm4, arm4t, or arm5." print
"Assuming arm3." print
"==========" print
"arm3" "arm-variant" set-global
] if
"arm-variant" get { "arm4" "arm4t" "arm5" } member? [
"cpu.arm.4" require
] when
"arm-variant" get { "arm4t" "arm5" } member? [
t have-BX? set-global
] when
"arm-variant" get "arm5" = [
t have-BLX? set-global
] when
7 cells profiler-prologues set-global
]]
FILE: [[cpu/arm/architecture/architecture.factor]] [[! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types arrays cpu.arm.assembler compiler
kernel kernel.private math namespaces words words.private
generator.registers generator.fixup generator cpu.architecture
system layouts ;
IN: cpu.arm.architecture
TUPLE: arm-backend ;
! ARM register assignments:
! R0-R4, R7-R10 integer vregs
! R11, R12 temporary
! R5 data stack
! R6 retain stack
! R7 primitives
: ds-reg R5 ; inline
: rs-reg R6 ; inline
M: temp-reg v>operand drop R12 ;
M: int-regs return-reg drop R0 ;
M: int-regs param-regs drop { R0 R1 R2 R3 } ;
M: int-regs vregs drop { R0 R1 R2 R3 R4 R7 R8 R9 R10 } ;
! No FPU support yet
M: float-regs param-regs drop { } ;
M: float-regs vregs drop { } ;
: <+/-> dup 0 < [ neg <-> ] [ <+> ] if ;
GENERIC: loc>operand ( loc -- reg addressing )
M: ds-loc loc>operand ds-loc-n cells neg ds-reg swap <+/-> ;
M: rs-loc loc>operand rs-loc-n cells neg rs-reg swap <+/-> ;
: load-cell ( reg -- )
[
"end" define-label
! Load target address
PC 0 <+> LDR
! Skip an instruction
"end" get B
! The target address
0 ,
! Continue here
"end" resolve-label
] with-scope ;
: call-cell ( -- )
! Compute return address; we skip 3 instructions
LR PC 8 ADD
! Load target address
R12 PC 0 <+> LDR
! Jump to target address
R12 BX
! The target address
0 , ;
M: arm-backend load-indirect ( obj reg -- )
tuck load-cell rc-absolute-cell rel-literal
dup 0 <+> LDR ;
M: immediate load-literal
over v>operand small-enough? [
[ v>operand ] bi@ swap MOV
] [
v>operand load-indirect
] if ;
: lr-save ( n -- i ) cell - ;
: next-save ( n -- i ) 2 cells - ;
: xt-save ( n -- i ) 3 cells - ;
: factor-area-size 5 cells ;
M: arm-backend stack-frame ( n -- i )
factor-area-size + 8 align ;
M: arm-backend %save-word-xt ( -- )
R12 PC 9 cells SUB ;
M: arm-backend %save-dispatch-xt ( -- )
R12 PC 2 cells SUB ;
M: arm-backend %prologue ( n -- )
SP SP pick SUB
R11 over MOV
R11 SP pick next-save <+> STR
R12 SP pick xt-save <+> STR
LR SP rot lr-save <+> STR ;
M: arm-backend %epilogue ( n -- )
LR SP pick lr-save <+> LDR
SP SP rot ADD ;
: compile-dlsym ( symbol dll reg -- )
load-cell rc-absolute rel-dlsym ;
: %alien-global ( symbol dll reg -- )
[ compile-dlsym ] keep dup 0 <+> LDR ;
M: arm-backend %profiler-prologue ( -- )
! We can clobber R0 here since it is undefined at the start
! of a word.
R12 load-indirect
R0 R12 profile-count-offset <+> LDR
R0 R0 1 v>operand ADD
R0 R12 profile-count-offset <+> STR ;
M: arm-backend %call-label ( label -- ) BL ;
M: arm-backend %jump-label ( label -- ) B ;
: %prepare-primitive ( -- )
! Save stack pointer to stack_chain->callstack_top, load XT
R1 SP 4 SUB ;
M: arm-backend %call-primitive ( word -- )
%prepare-primitive
call-cell rc-absolute-cell rel-word ;
M: arm-backend %jump-primitive ( word -- )
%prepare-primitive
! Load target address
R12 PC 0 <+> LDR
! Jump to target address
R12 BX
! The target address
0 , rc-absolute-cell rel-word ;
M: arm-backend %jump-t ( label -- )
"flag" operand f v>operand CMP NE B ;
: (%dispatch) ( word-table# -- )
! Load jump table target address into reg.
"scratch" operand PC "n" operand 1 <LSR> ADD
"scratch" operand dup 0 <+> LDR
rc-indirect-arm rel-dispatch
"scratch" operand dup compiled-header-size ADD ;
M: arm-backend %call-dispatch ( word-table# -- )
[
(%dispatch)
"scratch" operand BLX
] H{
{ +input+ { { f "n" } } }
{ +scratch+ { { f "scratch" } } }
} with-template ;
M: arm-backend %jump-dispatch ( word-table# -- )
[
%epilogue-later
(%dispatch)
"scratch" operand BX
] H{
{ +input+ { { f "n" } } }
{ +scratch+ { { f "scratch" } } }
} with-template ;
M: arm-backend %return ( -- ) %epilogue-later PC LR MOV ;
M: arm-backend %unwind drop %return ;
M: arm-backend %peek >r v>operand r> loc>operand LDR ;
M: arm-backend %replace >r v>operand r> loc>operand STR ;
: (%inc) ( n reg -- )
dup rot cells dup 0 < [ neg SUB ] [ ADD ] if ;
M: arm-backend %inc-d ( n -- ) ds-reg (%inc) ;
M: arm-backend %inc-r ( n -- ) rs-reg (%inc) ;
: stack@ SP swap <+> ;
M: int-regs %save-param-reg drop swap stack@ STR ;
M: int-regs %load-param-reg drop swap stack@ LDR ;
M: stack-params %save-param-reg
drop
R12 swap stack-frame* + stack@ LDR
R12 swap stack@ STR ;
M: stack-params %load-param-reg
drop
R12 rot stack@ LDR
R12 swap stack@ STR ;
M: arm-backend %prepare-unbox ( -- )
! First parameter is top of stack
R0 R5 4 <-!> LDR ;
M: arm-backend %unbox ( n reg-class func -- )
! Value must be in R0.
! Call the unboxer
f %alien-invoke
! Store the return value on the C stack
over [ [ return-reg ] keep %save-param-reg ] [ 2drop ] if ;
M: arm-backend %unbox-long-long ( n func -- )
! Value must be in R0:R1.
! Call the unboxer
f %alien-invoke
! Store the return value on the C stack
[
R0 over stack@ STR
R1 swap cell + stack@ STR
] when* ;
M: arm-backend %unbox-small-struct ( size -- )
! Alien must be in R0.
drop
"alien_offset" f %alien-invoke
! Load first cell
R0 R0 0 <+> LDR ;
M: arm-backend %unbox-large-struct ( n size -- )
! Alien must be in R0.
! Compute destination address
R1 SP roll ADD
R2 swap MOV
! Copy the struct to the stack
"to_value_struct" f %alien-invoke ;
M: arm-backend %box ( n reg-class func -- )
! If the source is a stack location, load it into freg #0.
! If the source is f, then we assume the value is already in
! freg #0.
>r
over [ 0 over param-reg swap %load-param-reg ] [ 2drop ] if
r> f %alien-invoke ;
M: arm-backend %box-long-long ( n func -- )
>r [
R0 over stack@ LDR
R1 swap cell + stack@ LDR
] when* r> f %alien-invoke ;
M: arm-backend %box-small-struct ( size -- )
! Box a 4-byte struct returned in R0.
R2 swap MOV
"box_small_struct" f %alien-invoke ;
: temp@ stack-frame* factor-area-size - swap - ;
: struct-return@ ( size n -- n )
[
stack-frame* +
] [
stack-frame* factor-area-size - swap -
] ?if ;
M: arm-backend %prepare-box-struct ( size -- )
! Compute target address for value struct return
R0 SP rot f struct-return@ ADD
! Store it as the first parameter
R0 0 stack@ STR ;
M: arm-backend %box-large-struct ( n size -- )
! Compute destination address
[ swap struct-return@ ] keep
R0 SP roll ADD
R1 swap MOV
! Copy the struct from the C stack
"box_value_struct" f %alien-invoke ;
M: arm-backend struct-small-enough? ( size -- ? )
4 <= ;
M: arm-backend %prepare-alien-invoke
! Save Factor stack pointers in case the C code calls a
! callback which does a GC, which must reliably trace
! all roots.
"stack_chain" f R12 %alien-global
SP R12 0 <+> STR
ds-reg R12 8 <+> STR
rs-reg R12 12 <+> STR ;
M: arm-backend %alien-invoke ( symbol dll -- )
call-cell rc-absolute-cell rel-dlsym ;
M: arm-backend %prepare-alien-indirect ( -- )
"unbox_alien" f %alien-invoke
R0 SP cell temp@ <+> STR ;
M: arm-backend %alien-indirect ( -- )
R12 SP cell temp@ <+> LDR
R12 BLX ;
M: arm-backend %alien-callback ( quot -- )
R0 load-indirect
"c_to_factor" f %alien-invoke ;
M: arm-backend %callback-value ( ctype -- )
! Save top of data stack
%prepare-unbox
R0 SP cell temp@ <+> STR
! Restore data/call/retain stacks
"unnest_stacks" f %alien-invoke
! Place former top of data stack in R0
R0 SP cell temp@ <+> LDR
! Unbox R0
unbox-return ;
M: arm-backend %cleanup ( alien-node -- ) drop ;
: %untag ( dest src -- ) 0b111 BIC ;
: %untag-fixnum ( dest src -- ) tag-bits get <ASR> MOV ;
: %tag-fixnum ( dest src -- ) tag-bits get <LSL> MOV ;
M: arm-backend value-structs? t ;
M: arm-backend small-enough? ( n -- ? ) 0 255 between? ;
M: long-long-type c-type-stack-align? drop t ;
M: arm-backend fp-shadows-int? ( -- ? ) f ;
! Alien intrinsics
M: arm-backend %unbox-byte-array ( dst src -- )
[ v>operand ] bi@ byte-array-offset ADD ;
M: arm-backend %unbox-alien ( dst src -- )
[ v>operand ] bi@ alien-offset <+> LDR ;
M: arm-backend %unbox-f ( dst src -- )
drop v>operand 0 MOV ;
M: arm-backend %unbox-any-c-ptr ( dst src -- )
! We need three registers here. R11 and R12 are reserved
! temporary registers. The third one is R14, which we have
! to save/restore.
"end" define-label
"start" define-label
! Save R14.
R14 SP 4 <-> STR
! Address is computed in R11
R11 0 MOV
! Load object into R12
R12 swap v>operand MOV
! We come back here with displaced aliens
"start" resolve-label
! Is the object f?
R12 f v>operand CMP
! If so, done
"end" get EQ B
! Is the object an alien?
R14 R12 header-offset <+/-> LDR
R14 alien type-number tag-fixnum CMP
! Add byte array address to address being computed
R11 R11 R12 NE ADD
! Add an offset to start of byte array's data area
R11 R11 byte-array-offset NE ADD
"end" get NE B
! If alien, load the offset
R14 R12 alien-offset <+/-> LDR
! Add it to address being computed
R11 R11 R14 ADD
! Now recurse on the underlying alien
R12 R12 underlying-alien-offset <+/-> LDR
"start" get B
"end" resolve-label
! Done, store address in destination register
v>operand R11 MOV
! Restore R14.
R14 SP 4 <-> LDR ;
]]
FILE: [[cpu/arm/architecture/authors.txt]] [[Slava Pestov
]]
FILE: [[cpu/arm/summary.txt]] [[ARM3 compiler backend
]]
FILE: [[cpu/arm/allot/allot.factor]] [[! Copyright (C) 2006, 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel cpu.architecture cpu.arm.assembler
cpu.arm.architecture namespaces math sequences
generator generator.registers generator.fixup system layouts
alien ;
IN: cpu.arm.allot
: load-zone-ptr ( reg -- ) "nursery" f rot %alien-global ;
: %allot ( header size -- )
! Store a pointer to 'size' bytes allocated from the
! nursery in R11
8 align ! align the size
R12 load-zone-ptr ! nusery -> r12
R11 R12 cell <+> LDR ! nursery.here -> r11
R11 R11 pick ADD ! increment r11
R11 R12 cell <+> STR ! r11 -> nursery.here
R11 R11 rot SUB ! old value
R12 swap type-number tag-fixnum MOV ! compute header
R12 R11 0 <+> STR ! store header
;
: %store-tagged ( reg tag -- )
>r dup fresh-object v>operand R11 r> tag-number ORR ;
: %allot-bignum ( #digits -- )
! 1 cell header, 1 cell length, 1 cell sign, + digits
! length is the # of digits + sign
bignum over 3 + cells %allot
R12 swap 1+ v>operand MOV ! compute the length
R12 R11 cell <+> STR ! store the length
;
: %allot-bignum-signed-1 ( dst src -- )
! on entry, reg is a 30-bit quantity sign-extended to
! 32-bits.
! exits with tagged ptr to bignum in reg.
[
"end" define-label
! is it zero?
dup v>operand 0 CMP
0 >bignum pick EQ load-literal
"end" get EQ B
! ! it is non-zero
1 %allot-bignum
! is the fixnum negative?
dup v>operand 0 CMP
! negative sign
R12 1 LT MOV
! negate fixnum
dup v>operand dup 0 LT RSB
! positive sign
R12 0 GE MOV
! store sign
R12 R11 2 cells <+> STR
! store the number
v>operand R11 3 cells <+> STR
! tag the bignum, store it in reg
bignum %store-tagged
"end" resolve-label
] with-scope ;
M: arm-backend %box-alien ( dst src -- )
"end" define-label
dup v>operand 0 CMP
over v>operand f v>operand EQ MOV
"end" get EQ B
alien 4 cells %allot
! Store offset
v>operand R11 3 cells <+> STR
R12 f v>operand MOV
! Store expired slot
R12 R11 1 cells <+> STR
! Store underlying-alien slot
R12 R11 2 cells <+> STR
! Store tagged ptr in reg
object %store-tagged
"end" resolve-label ;
]]
FILE: [[cpu/arm/allot/authors.txt]] [[Slava Pestov
]]
FILE: [[cpu/arm/intrinsics/intrinsics.factor]] [[! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays cpu.architecture cpu.arm.assembler
cpu.arm.architecture cpu.arm.allot kernel kernel.private math
math.private namespaces sequences words
quotations byte-arrays hashtables.private hashtables generator
generator.registers generator.fixup sequences.private sbufs
sbufs.private vectors vectors.private system
classes.tuple.private layouts strings.private slots.private ;
IN: cpu.arm.intrinsics
: %slot-literal-known-tag
"val" operand
"obj" operand
"n" get cells
"obj" get operand-tag - <+/-> ;
: %slot-literal-any-tag
"scratch" operand "obj" operand %untag
"val" operand "scratch" operand "n" get cells <+> ;
: %slot-any
"scratch" operand "obj" operand %untag
"n" operand dup 1 <LSR> MOV
"val" operand "scratch" operand "n" operand <+> ;
\ slot {
! Slot number is literal and the tag is known
{
[ %slot-literal-known-tag LDR ] H{
{ +input+ { { f "obj" known-tag } { [ small-slot? ] "n" } } }
{ +scratch+ { { f "val" } } }
{ +output+ { "val" } }
}
}
! Slot number is literal
{
[ %slot-literal-any-tag LDR ] H{
{ +input+ { { f "obj" } { [ small-slot? ] "n" } } }
{ +scratch+ { { f "scratch" } { f "val" } } }
{ +output+ { "val" } }
}
}
! Slot number in a register
{
[ %slot-any LDR ] H{
{ +input+ { { f "obj" } { f "n" } } }
{ +scratch+ { { f "val" } { f "scratch" } } }
{ +output+ { "val" } }
{ +clobber+ { "n" } }
}
}
} define-intrinsics
: %write-barrier ( -- )
"val" get operand-immediate? "obj" get fresh-object? or [
"cards_offset" f R12 %alien-global
"scratch" operand R12 "obj" operand card-bits <LSR> ADD
"val" operand "scratch" operand 0 <+> LDRB
"val" operand dup card-mark ORR
"val" operand "scratch" operand 0 <+> STRB
] unless ;
\ set-slot {
! Slot number is literal and tag is known
{
[ %slot-literal-known-tag STR %write-barrier ] H{
{ +input+ { { f "val" } { f "obj" known-tag } { [ small-slot? ] "n" } } }
{ +scratch+ { { f "scratch" } } }
{ +clobber+ { "val" } }
}
}
! Slot number is literal
{
[ %slot-literal-any-tag STR %write-barrier ] H{
{ +input+ { { f "val" } { f "obj" } { [ small-slot? ] "n" } } }
{ +scratch+ { { f "scratch" } } }
{ +clobber+ { "val" } }
}
}
! Slot number is in a register
{
[ %slot-any STR %write-barrier ] H{
{ +input+ { { f "val" } { f "obj" } { f "n" } } }
{ +scratch+ { { f "scratch" } } }
{ +clobber+ { "val" "n" } }
}
}
} define-intrinsics
: fixnum-op ( op -- quot )
[ "out" operand "x" operand "y" operand ] swap add ;
: fixnum-register-op ( op -- pair )
fixnum-op H{
{ +input+ { { f "x" } { f "y" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} 2array ;
: fixnum-value-op ( op -- pair )
fixnum-op H{
{ +input+ { { f "x" } { [ small-tagged? ] "y" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} 2array ;
: define-fixnum-op ( word op -- )
[ fixnum-value-op ] keep fixnum-register-op 2array
define-intrinsics ;
{
{ fixnum+fast ADD }
{ fixnum-fast SUB }
{ fixnum-bitand AND }
{ fixnum-bitor ORR }
{ fixnum-bitxor EOR }
} [
first2 define-fixnum-op
] each
\ fixnum-bitnot [
"x" operand dup MVN
"x" operand dup %untag
] H{
{ +input+ { { f "x" } } }
{ +output+ { "x" } }
} define-intrinsic
\ fixnum*fast [
"out" operand "y" operand %untag-fixnum
"out" operand "x" operand "out" operand MUL
] H{
{ +input+ { { f "x" } { f "y" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ fixnum-shift [
"out" operand "x" operand "y" get neg <ASR> MOV
! Mask off low bits
"out" operand dup %untag
] H{
{ +input+ { { f "x" } { [ -31 0 between? ] "y" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
: %untag-fixnums ( seq -- )
[ dup %untag-fixnum ] unique-operands ;
: overflow-check ( insn -- )
[
"end" define-label
[ "out" operand "x" operand "y" operand roll S execute ] keep
"end" get VC B
{ "x" "y" } %untag-fixnums
"x" operand "x" operand "y" operand roll execute
"out" get "x" get %allot-bignum-signed-1
"end" resolve-label
] with-scope ; inline
: overflow-template ( word insn -- )
[ overflow-check ] curry H{
{ +input+ { { f "x" } { f "y" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
{ +clobber+ { "x" "y" } }
} define-intrinsic ;
\ fixnum+ \ ADD overflow-template
\ fixnum- \ SUB overflow-template
\ fixnum>bignum [
"x" operand dup %untag-fixnum
"out" get "x" get %allot-bignum-signed-1
] H{
{ +input+ { { f "x" } } }
{ +scratch+ { { f "out" } } }
{ +clobber+ { "x" } }
{ +output+ { "out" } }
} define-intrinsic
\ bignum>fixnum [
"end" define-label
"x" operand dup %untag
"y" operand "x" operand cell <+> LDR
! if the length is 1, its just the sign and nothing else,
! so output 0
"y" operand 1 v>operand CMP
"y" operand 0 EQ MOV
"end" get EQ B
! load the value
"y" operand "x" operand 3 cells <+> LDR
! load the sign
"x" operand "x" operand 2 cells <+> LDR
! is the sign negative?
"x" operand 0 CMP
! Negate the value
"y" operand "y" operand 0 NE RSB
"y" operand dup %tag-fixnum
"end" resolve-label
] H{
{ +input+ { { f "x" } } }
{ +scratch+ { { f "y" } } }
{ +clobber+ { "x" } }
{ +output+ { "y" } }
} define-intrinsic
: fixnum-jump ( op -- quo )
[ "x" operand "y" operand CMP ] swap
1quotation [ B ] 3append ;
: fixnum-register-jump ( op -- pair )
fixnum-jump { { f "x" } { f "y" } } 2array ;
: fixnum-value-jump ( op -- pair )
fixnum-jump { { f "x" } { [ small-tagged? ] "y" } } 2array ;
: define-fixnum-jump ( word op -- )
[ fixnum-value-jump ] keep fixnum-register-jump
2array define-if-intrinsics ;
{
{ fixnum< LT }
{ fixnum<= LE }
{ fixnum> GT }
{ fixnum>= GE }
{ eq? EQ }
} [
first2 define-fixnum-jump
] each
\ tag [
"out" operand "in" operand tag-mask get AND
"out" operand dup %tag-fixnum
] H{
{ +input+ { { f "in" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ type [
! Get the tag
"out" operand "obj" operand tag-mask get AND
! Compare with object tag number (3).
"out" operand object tag-number CMP
! Tag the tag if it is not equal to 3
"out" operand dup NE %tag-fixnum
! Load the object header if tag is equal to 3
"out" operand "obj" operand object tag-number <-> EQ LDR
] H{
{ +input+ { { f "obj" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ class-hash [
"end" define-label
! Get the tag
"out" operand "obj" operand tag-mask get AND
! Compare with tuple tag number (2).
"out" operand tuple tag-number CMP
"out" operand "obj" operand tuple-class-offset <+/-> EQ LDR
"out" operand dup class-hash-offset <+/-> EQ LDR
"end" get EQ B
! Compare with object tag number (3).
"out" operand object tag-number CMP
"out" operand "obj" operand object tag-number <-> EQ LDR
! Tag the tag
"out" operand dup NE %tag-fixnum
"end" resolve-label
] H{
{ +input+ { { f "obj" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
: userenv ( reg -- )
! Load the userenv pointer in a register.
"userenv" f rot compile-dlsym ;
\ getenv [
"n" operand dup 1 <ASR> MOV
"x" operand userenv
"x" operand "x" operand "n" operand <+> LDR
] H{
{ +input+ { { f "n" } } }
{ +scratch+ { { f "x" } } }
{ +output+ { "x" } }
{ +clobber+ { "n" } }
} define-intrinsic
\ setenv [
"n" operand dup 1 <ASR> MOV
"x" operand userenv
"val" operand "x" operand "n" operand <+> STR
] H{
{ +input+ { { f "val" } { f "n" } } }
{ +scratch+ { { f "x" } } }
{ +clobber+ { "n" } }
} define-intrinsic
: %set-slot R11 swap cells <+> STR ;
: %store-length
R12 "n" operand MOV
R12 1 %set-slot ;
: %fill-array swap 2 + %set-slot ;
\ <tuple> [
tuple "n" get 2 + cells %allot
%store-length
! Store class
"class" operand 2 %set-slot
! Zero out the rest of the tuple
"initial" operand f v>operand MOV
"n" get 1- [ 1+ "initial" operand %fill-array ] each
"out" get tuple %store-tagged
] H{
{ +input+ { { f "class" } { [ inline-array? ] "n" } } }
{ +scratch+ { { f "out" } { f "initial" } } }
{ +output+ { "out" } }
} define-intrinsic
\ <array> [
array "n" get 2 + cells %allot
%store-length
! Store initial element
"n" get [ "initial" operand %fill-array ] each
"out" get object %store-tagged
] H{
{ +input+ { { [ inline-array? ] "n" } { f "initial" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ <byte-array> [
byte-array "n" get 2 cells + %allot
%store-length
! Store initial element
R12 0 MOV
"n" get cell align cell /i [ R12 %fill-array ] each
"out" get object %store-tagged
] H{
{ +input+ { { [ inline-array? ] "n" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ <ratio> [
ratio 3 cells %allot
"numerator" operand 1 %set-slot
"denominator" operand 2 %set-slot
"out" get ratio %store-tagged
] H{
{ +input+ { { f "numerator" } { f "denominator" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ <complex> [
complex 3 cells %allot
"real" operand 1 %set-slot
"imaginary" operand 2 %set-slot
! Store tagged ptr in reg
"out" get complex %store-tagged
] H{
{ +input+ { { f "real" } { f "imaginary" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ <wrapper> [
wrapper 2 cells %allot
"obj" operand 1 %set-slot
! Store tagged ptr in reg
"out" get object %store-tagged
] H{
{ +input+ { { f "obj" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
! Alien intrinsics
: %alien-accessor ( quot -- )
"offset" operand dup %untag-fixnum
"offset" operand dup "alien" operand ADD
"value" operand "offset" operand 0 <+> roll call ; inline
: alien-integer-get-template
H{
{ +input+ {
{ unboxed-c-ptr "alien" c-ptr }
{ f "offset" fixnum }
} }
{ +scratch+ { { f "value" } } }
{ +output+ { "value" } }
{ +clobber+ { "offset" } }
} ;
: %alien-integer-get ( quot -- )
%alien-accessor
"value" operand dup %tag-fixnum ; inline
: alien-integer-set-template
H{
{ +input+ {
{ f "value" fixnum }
{ unboxed-c-ptr "alien" c-ptr }
{ f "offset" fixnum }
} }
{ +clobber+ { "value" "offset" } }
} ;
: %alien-integer-set ( quot -- )
"offset" get "value" get = [
"value" operand dup %untag-fixnum
] unless
%alien-accessor ; inline
: define-alien-integer-intrinsics ( word get-quot word set-quot -- )
[ %alien-integer-set ] curry
alien-integer-set-template
define-intrinsic
[ %alien-integer-get ] curry
alien-integer-get-template
define-intrinsic ;
\ alien-unsigned-1 [ LDRB ]
\ set-alien-unsigned-1 [ STRB ]
define-alien-integer-intrinsics
: alien-cell-template
H{
{ +input+ {
{ unboxed-c-ptr "alien" c-ptr }
{ f "offset" fixnum }
} }
{ +scratch+ { { unboxed-alien "value" } } }
{ +output+ { "value" } }
{ +clobber+ { "offset" } }
} ;
\ alien-cell
[ [ LDR ] %alien-accessor ]
alien-cell-template define-intrinsic
: set-alien-cell-template
H{
{ +input+ {
{ unboxed-c-ptr "value" pinned-c-ptr }
{ unboxed-c-ptr "alien" c-ptr }
{ f "offset" fixnum }
} }
{ +clobber+ { "offset" } }
} ;
\ set-alien-cell
[ [ STR ] %alien-accessor ]
set-alien-cell-template define-intrinsic
]]
FILE: [[cpu/arm/intrinsics/authors.txt]] [[Slava Pestov
]]
FILE: [[cpu/arm/authors.txt]] [[Slava Pestov
]]
FILE: [[cpu/arm/tags.txt]] [[compiler
]]
FILE: [[cpu/arm/4/4.factor]] [[! Copyright (C) 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays cpu.architecture cpu.arm.assembler
cpu.arm.architecture cpu.arm5.assembler kernel kernel.private
math math.private namespaces sequences words quotations
byte-arrays hashtables.private hashtables generator
generator.registers generator.fixup sequences.private
strings.private ;
IN: cpu.arm4
: (%char-slot)
"out" operand string-offset MOV
"out" operand dup "n" operand 2 <LSR> ADD ;
\ char-slot [
(%char-slot)
"out" operand "obj" operand "out" operand <+> LDRH
"out" operand dup %tag-fixnum
] H{
{ +input+ { { f "n" } { f "obj" } } }
{ +scratch+ { { f "out" } } }
{ +output+ { "out" } }
} define-intrinsic
\ set-char-slot [
"val" operand dup %untag-fixnum
(%char-slot)
"val" operand "obj" operand "out" operand <+> STRH
] H{
{ +input+ { { f "val" } { f "n" } { f "obj" } } }
{ +scratch+ { { f "out" } } }
{ +clobber+ { "val" } }
} define-intrinsic
\ alien-signed-1 [ LDRSB ]
\ set-alien-signed-1 [ STRB ]
define-alien-integer-intrinsics
\ alien-unsigned-2 [ LDRH ]
\ set-alien-unsigned-2 [ STRH ]
define-alien-integer-intrinsics
\ alien-signed-2 [ LDRSH ]
\ set-alien-signed-2 [ STRH ]
define-alien-integer-intrinsics
]]
FILE: [[cpu/arm/4/summary.txt]] [[Additional compiler intrinsics for ARM4
]]
FILE: [[cpu/arm/4/authors.txt]] [[Slava Pestov
]]
FILE: [[images/processing/rotation/rotation.factor]] [[! Copyright (C) 2009 Kobi Lurie.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays colors combinators
combinators.short-circuit fry grouping images images.bitmap
images.loader images.normalization kernel locals math sequences ;
IN: images.processing.rotation
ERROR: unsupported-rotation degrees ;
<PRIVATE
: rotate-90 ( seq^3 -- seq^3 ) flip [ reverse ] map ;
: rotate-180 ( seq^3 -- seq^3 ) reverse [ reverse ] map ;
: rotate-270 ( seq^3 -- seq^3 ) flip reverse ;
: (rotate) ( seq n -- seq' )
{
{ 0 [ ] }
{ 90 [ rotate-90 ] }
{ 180 [ rotate-180 ] }
{ 270 [ rotate-270 ] }
[ unsupported-rotation ]
} case ;
: rows-remove-pad ( byte-rows -- pixels' )
[ dup length 4 mod head* ] map ;
: row-length ( image -- n )
[ bitmap>> length ] [ dim>> second ] bi /i ;
: image>byte-rows ( image -- byte-rows )
[ bitmap>> ] [ row-length ] bi group rows-remove-pad ;
: (seperate-to-pixels) ( byte-rows image -- pixel-rows )
component-order>> bytes-per-pixel '[ _ group ] map ;
: image>pixel-rows ( image -- pixel-rows )
[ image>byte-rows ] keep (seperate-to-pixels) ;
: flatten-table ( seq^3 -- seq )
[ concat ] map concat ;
: ?reverse-dimensions ( image n -- )
{ 270 90 } member? [ [ reverse ] change-dim ] when drop ;
: normalize-degree ( n -- n' ) 360 rem ;
: processing-effect ( image quot -- image' )
'[ image>pixel-rows @ flatten-table ] [ bitmap<< ] [ ] tri ; inline
:: rotate' ( image n -- image )
n normalize-degree :> n'
image image>pixel-rows :> pixel-table
image n' ?reverse-dimensions
pixel-table n' (rotate) :> table-rotated
image table-rotated flatten-table >>bitmap ;
PRIVATE>
: rotate ( image n -- image' )
normalize-degree
[ '[ _ (rotate) ] processing-effect ] [ ?reverse-dimensions ] 2bi ;
: reflect-y-axis ( image -- image )
[ [ reverse ] map ] processing-effect ;
: reflect-x-axis ( image -- image )
[ reverse ] processing-effect ;
]]
FILE: [[images/processing/rotation/test-bitmaps/lake.bmp]] base64[[Qk3lAQAAAAAAADYAAAAoAAAADQAAAAoAAAABABgAAAAAAK8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQID/QID/QID/QID///+A//+A//+AAAAAAAAAAECA/0CA/0CA/0CA////gP//gP//gAAAAAAAAAAAAAAAAAAAAABAgP9AgP9AgP9AgP///4D//4D//4AAAAAAAAAAAAAAAAAAAAAAAAAAQID/QID/QID///+A//+A//+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgIAAAIAAAIAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECA/wCAAACAAACAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAICAAIAAgAAAgAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgACAgACAgACAAEBAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgIAAgIAAgIAAAABAQAAAAACAAP+AAP+AAP8A/wAA/wAA/wD/gID/gID/gIBAQABAQAAAAAAAgAD/gAD/gAD/AP8AAP8AAP8A/4CA/4CA/4CAQEAAQEAAQEAAAIAA/4AA/4AA/wD/AAD/AAD/AP+AgP+AgP+AgEBAAEBAAEBAAEBAAAA=]]
FILE: [[images/processing/rotation/test-bitmaps/small-rotated.bmp]] base64[[Qk3GAQAAAAAAADYAAAAoAAAADQAAAAoAAAABABgAAAAAAAAAAACAAP8AgAD/AAAAAAAAAAAAgAD/gAD/gAD/AP8AAP8AAP8A/4CA/4CA/4CAQEAAQEAAQEAAQEAAAIAA/4AA/4AA/wD/AAD/AAD/AP+AgP+AgP+AgEBAAEBAAEBAAEBAAACAAP+AAP+AAP8A/wAA/wAA/wD/gID/gID/gIBAQABAQABAQABAQAAAAAAAAAAAAAAAAAAAAAAAAAAAgACAgACAgACAgAAAgAAAgAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgIAAgIAAgIAAAIAAAIAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAICAAICAAICAAACAAACAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQID/QID/QID/QID///+A//+A//+AAAAAAAAAAAAAAAAAAAAAAAAAAECA/0CA/0CA/0CA////gP//gP//gAAAAAAAAAAAAAAAAAAAAAAAAABAgP9AgP9AgP9AgP///4D//4D//4AAAAAAAAAAAAAAAAAAAAAAAAAAQID/QID/QID/QID///+A//+A//+AAA==]]
FILE: [[images/processing/rotation/test-bitmaps/small.bmp]] base64[[Qk3WAQAAAAAAADYAAAAoAAAACgAAAA0AAAABABgAAAAAAKABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAD/gAD/gAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAP+AAP+AAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA/4AA/4AA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAP8AAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAA/wAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAD/AAD/AAAAQID/QID/QID/QID/gACAgACAgACA/4CA/4CA/4CAAABAgP9AgP9AgP9AgP+AAICAAICAAID/gID/gID/gIAAAECA/0CA/0CA/0CA/4AAgIAAgIAAgP+AgP+AgP+AgAAAQID/QID/QID/QID/gAAAgAAAgAAAQEAAQEAAQEAAAAD//4D//4D//4D//4CAAACAAACAAABAQABAQABAQAAAAP//gP//gP//gP//gIAAAIAAAIAAAEBAAEBAAEBAAAAA//+A//+A//+A//+AgAAAgAAAgAAAQEAAQEAAQEAAAAA=]]
FILE: [[images/processing/rotation/test-bitmaps/PastedImage.bmp]] base64[[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H6VgI6FcIKVgJKNdIqBZHqhfJq5lLLBnMbFoM7NsNbdyOrRyObd3P7V2QbV5R8CGV8mRZNOcc9+pg5hOAJhOAJhOAP///5hOAJhOAP///////////5hOAJhOAJhOAJhOAP///5hOAJhOAJhOAP///5hOAJhOAJhOAP///5hOAJhOAP///////5hOAP///5hOAJhOAP///5hOAJhOAP///5hOAP///5hOAACcWR+dWh2lYyOpaSiwbzGubjKzczqpazWiZC6iYyqzcjewbjKwbS+uaS2sZiuoYSmqYi6qaDKlZS+mZS+oZjGoZjGsaDWsaDOqZTCuaDOvaTSqZi+raDGvbTemZC6lYi2jYSypZzKzcT21c0CubDiqZzOnZTCpZzGraDKoZS2gWyOgXCGrZSqtZiurYyepYyeiXiOnZSqpZyuiYCOfXB+cWRyhXiOkXySpYyiuZy2pYyasZCexaiyxai2waC2yajCxazG1bza3cjuxbTWsZjCwajSwazSybzeycjyxcz2zeUS+h1bPm23bqH7grojksZCYTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgCYTgD///+YTgCYTgD///+YTgD///+YTgAAqWgusm81wYBCu3w+snI2tHM6yopU2Jhl1JVfvX9GsXE2rWsvsW8wtnM1s280r2oytG85snA5sHA3rGozrGkyrms1s245smw2sGkyr2cwqWIqqGMpq2YuqWYuqmcwsW83tXI8uHZBvXtGu3pGuHdDtHNAq2s5pWQyn10pmFYfmlcgoF0kp2MoqWQpqGInqGInq2gtsnA1sG4zrmwxp2UqpGInpmQqqWUssWwzs241rWgusGowtG0ztGsytm00t283uHI8u3hCtnVBsnI+sG87s3A7snA8s3I+uXtHyI1Z1Zxr2qV33ql+6baN9MGb876bmE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4AmE4A////mE4A////mE4AmE4A////mE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4AmE4A////mE4AmE4A////mE4A////mE4AALh2P7d2PbR1ObFyNqprMadnLrRzPs2LWdKQXMB/SLNyOK1rL7BvMK9uMKxrL6ZlLKxqM6tpMKxqMKpnLq9qMrFsNK5oMK1nLrBpL69mLKlhJ6tlKa1nLapkKqllK6toL6toL6tpMaZlLqVlLrJyPLt8ScyPYN+ic9ucarRzP6lnMqpoMa9sNLNwNrp2PLRxNrNxNqhmK6dlKqtpLqxpL6pnLqJfJ6NgKKdjLKhlLalmL65rNLRvOLNtNrJrNbJsOLRxPcSFU8KFVMuRYNyhcOOlc+Chb9SVY8SHVdqdbeuxgu20ieathOGogt6kfdabcphOAJhOAJhOAP///5hOAP///5hOAJhOAJhOAP///5hOAJhOAP///5hOAP///5hOAJhOAP///5hOAJhOAJhOAP///5hOAP///5hOAJhOAJhOAP///5hOAJhOAP///5hOAJhOAP///5hOAP///5hOAACoZi+gXiWjYiepaS2mZyykZCukYi2ybjq1cDusZzCiXiWaWBudXB6kZSepai6maC2pazCraS+qaCyqZiqrZSupZCqnYSisZiuwai+uZyuqYyesZiqqZCmjXyOmYialYSaiXyWiYCehYCahYSimZi6rbTnEiVrSl2jXmGfBgU60cz2ycDm0cTmubDOvbjSwbTSxbzStai+wbDKwbTSybzevbDSsaDKrZzGuazSoZS+saTasaTawbDmqZjKmYi6lYS+3dkTYm2rboHDlq33vuInssIDQk2SvcUKlZje5ekzPkGPSk2nMjWXBgVuyckeraTiYTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgCYTgD///+YTgCYTgD///+YTgD///+YTgAApGEqnFkgpWInqGcroWAlomAopmMtsW02qmUunlkgm1YdoV0ipGImq2wvrG0xqWwvqGsuqGgqpmIlpmEkpmAlp2EmpmAlolwhn1keoFoeoFoepF4ip2InqGQop2MopGAlo18lol8lomAlpGIprWwztnZB05dn05Zmx4dVu3hEsm84rmszr2sxqWcts3I4tHI4tHA1tXA1tXA3tnE6tHA7tXE8sm47tnE/sGw5q2g1rmo6sGw7qWY1tXJAwoBNw4FPxYRSy41dy45fxopdxIhay49gxYZYqGk6o2EzsG0+tHBCr2w/qWU5ol4yoFsqpV4omE4AmE4A////////mE4AmE4A////////////mE4AmE4A////mE4AmE4AmE4A////mE4A////////////////mE4AmE4A////////////mE4A////////////mE4A////////mE4AmE4A////mE4AAKlmLbFsM7h0ObNwNaxqL6lmLqZjK6xpL6xqL6pmLK1oL7RvNrRxN7RxN6xrMKlrLKVmJ6ViI6NeH6JdH6NdIadhJqljKKZgJaZhJqhiJ6diJ6pmLK5qMa1oL7BqMrBrM7BrMrBrMrNuNbx3PsiDSsuJU8uLWbd2Q61qNKtmLqhhJ6hiJqdhJKNfI6ViJqRhJqJcIaNcIqljK61mMbRtO7hzQrRvPrhyQrx3Rrl0Q8N8TcB6S8eDUdKPXM2LV8aFUsqKV86OW8yLW7t7S61tPrRzQ7VzQ715Sbl1RK1nNaVfLKFbKKFbKKZgLKxkMKlgKJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAP///5hOAJhOAJhOAJhOAJhOAP///5hOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAP///5hOAAC1cTi3cTi3cjezbzSsaS2taS+tajGsbC6ubzGubjKxbjSwazOrZi6pZSujYCShYCGfXh6fWxuhWxymYCKsZSmuaC6wajCzbjS4dDm0cDarZy2taTGvazWybji6dT+3cjy1bzm0bji4czy+d0C0bTepZS+hYCqdWyWjXyaqYyirYyaqYSOmXyCjXiCdWRudWR2jXSOqYiyxaTSyaze1bz2+eEe8dUazbT2sZjaoYjKrYzSyazurZTOkYCyfXSeaWCOhXyqwbjmwbDqnYzKraDeuajmlYC+mYC6jXSihWSOjWyWiWiOhWiKhWyKhWSGfVyCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///+YTgAAs284tXI6tHE5s283sGsxrGctqmUqq2ctr20zsnI3rm40pWUro2EmpWAlpF4jpmAko2AjpF8mpmAorWgxt3I7s3A7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j2DEhle7fEyxcUCubD2nZDaYVSaaViWdWiafXSekYy2nZjKmYzKrZzWtazemZC+jYSyhXyqjXy2mYi+oYy2oYyqqZSqpZSqsZzCvaDKuZDCqYiupYSiqYyinYialYSajXiWdWCOhWyifWiWhWyWkXiWhWyGmXyeoYi2rZDGrZDOpXy+rXy2nXCieVR+ZURubUx2ZUh2ZUx2WURyVUBuXUR2XTx6UTBuVTRyYUB2dVCCgWCKgWSCdVRyZURegWB6jWh+fVhycUxmbUhmfVRyhVh6fVR6eVB2cUhqZTxiYThWaUBeXThSYTxWdVBqfVhyjWiCkWyEArWwur24tsXAxr20wrGgvqWUuqGItpmEqqWQrp2Mrp2QtqGYvrWs2sW45sm04smw3sWg0r2c0rWYyrmYys2k0tWw2tWs2tWw3sWg0q2Mxo1wsnVopnV0sqms5wYRS3aBu251s36Fx2ZtryopcsXFCrGo5pmQxo2Ato10sqWMwqWMurGcvrmkwrmowrmkxqGMupF8toF0om1kjllQemFQgm1Yjn1omn1oknlkfnFYbnFccolwlqGErpVwooFgin1kgol0ioVwgn1ohoFojn1kkolwnpF0opl8pqGEppl8npF0mpF0poFkmnlclolgnoVUjn1QgoVchn1Ygn1cholskolsloVsmolwnn1gjn1UjoFYkoFcknlUinlUhoFgim1MdmE8XnVQaoFcdnlUanVUaoVgfo1kipVojplsko1ggnlQcnVMcn1Ufn1UeoFYeoFceoVgepFwipFwiqF8lrWQqALh1Ord0Nrh1ObZzOLRxOLNwObBsN6xpMrBrNa9pNK1oNK1qNa9tOK1sNq5rNrNrN7JoNKxmMahjLqdhLKtkLq9oMq9nMq5nNK5nNrBqOq9rPLh3ScSGV9iaa9mbbNmbbNqcbMqLW7Z2RapoOKBdLaVhLqllMKtlMKpiL6tiLqhfKKVdJKNbIKNbIKNcIaJdJZ9aJZpWIJhVHplWHZlVHpxWIZtVH5hRG5tUGpxVGp1WHKRcJaNaJZ1UIJ1VIJtVHptWHJtWHJtWHp1XIZ5YIqBaI6NcJaRcJqFZI55WIKFYI6RbJ6FYJKBXI6BWI6BUI6FXI6FXIqFYIaJbIqReJKNcI6BaI6JcJqBYI59UIKFWIqNZJaFYJKJZJaNaJqFZJKNaI6JYIKFYHqJZHqFXHqNZI6VaJadbJqpfJ6pgJ6phKKZdJ6pfLKddJ6RaIqRbI6FaIaRdJKZeJKdeJKJZHwCxbTS1cTa4czqwbTStajOvbTatajWsaDOvaDOtZTKrZDKqZzStazitbDetajWxajWyaDOsZzGlYi2jXimpYy2sZjCrZTCqZjOwbTy4dUe9fFDKi1/Rk2fXmW3en3LPkWO2d0iiYjGjYS+lYjCkXy2qYzCrZTCsZDCkWymhVySkWSOhVh2fVRuhVx6hVx+fVyGbViGZVB6aVR2YUxqXUBmZUBubUh6XTxmcVhueVhuaUxmYUBmXTxuZUR6XURyUTheVUBiYUxueWCKdViKaVBydVxycVhybUx2cUx6eVSGfViKkWiaiWCKgViCgVyKjWieiWSWjWiWlXiajXCKiXCGjXSKkXSSgWSGgWCOdVCCdViKjWSalXCimXiqqYS2sYi2oXSimWyWlWiOkXSKgWSChVyKiVyOlWiWlWySqYCepYCinXiqpXy2nXCimXCajWySkXCWlXSWiWiGhVx+bURgAo14on1kip2EqpGApol8oo2EqoV8pol0ppV0qplwqqV8uqWMyq2k2qmo1q2k0sGo1tGo1rmk0qWcyp2Quq2cwrGgxp2Qwqmc2uXhIwYFUuXpQwIJZxIZex4pfwIJWpmc6oWAyoV8upWEvqGIvqmIuqmMvqmMvqmIwp14tql8vqFwpplwmpFkjo1kioVcinVQgmlUgnlkipF4lqGEopFwko1okpVsmpl4nn1cdoFgcn1gen1YgoFgknlcln1gkoVslpF4opF4ooVsmnFYinFYdnlkcnlgdnVYeoFgkpVooolcko1gjoFYfpFkhqF4oqGEtqGEspF0opF0lpV8kpmAlqGInqWIppV0lolslkk8fgkkeiE0ikVIkl1UnnVgopl4trGIuqF0pp1wno1wioVsipFwopFoopFkmoVchnFQanlYdm1MemlEgoVYkpVsno1ololokn1chm1MbmlEZmk8XAJ9ZJKBbJKJdJaJeJZ5aIpxZIJtXIJtTH55VIqFYJqRdKqVfLaZjMKVlL6ZkL6lkLqtjLqlkL6hmMKlmMK1pNK9sOK5rOa9tPb5/Uc2QZMuNYsyPZ8+RaLt+U6psP6FiM6loN6dlMqRhLqVgK6dhLKtlL6hhLqphL6pfL6xhMK1hL65jL6pgKqZcKKVdKadeLKNe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YjCdWiecWSSeWyWjXyypZDKpZjOkXy2gWymkXyykXimkXSejWiSgVx+hWCGiWSWgVyOfVyGdViGeWCSiXCilYC6mYTCmYTGiXSyiXSmhXCagWyaiWyerYzCwZzWvZjStZDKrYS+tYTCvZjKvZzGvZzGuZjC1bDi1bDivZjKyaTWwZzOnXiqlXCaoXyekXCOjWyKlXCOlWyGlXCKoXiSoXSWoXCWqXyeqYSioXyarZCqxajCuaC2qYymoYSalXSGjWyBeweZewear4PKe//+e//+e//+e//+e//+e//+e//+e//+e//+e//+e//+e//+e//+e//+e//+e//+e//+C5v+y8v8MepxPKxCNSxqjWB2iVhuhVRqiVxsApWUznl0qlVQgl1UgmVYhnVkkoFwnoV0qoV4sol4solwqn1gmpV0sqGExp2IwpGAvpGAvp2Evpl8tpl8upmEwp2IxpGEvl1QhlVIem1cin1wmqGMwqGQyp2UyqWUzq2Y0sGs4rmcyqGArp10mpVsjpFkko1onolklpV0npV4npmApqGMtqmUyq2U1qWM1q2Q2r2o4sW47rms2rGczqGEvpV0ro1spoVgmoFYlpFknqWAsrmYwtGw3tGw2sWg0rmUxrGMvsGcytm04uXA7t286s2s1rWUuq2QrqmEpp14koVgenFMZolgeolgfo1khpFojplwkqWEnqmMoqWMmp2Akp18jqGAlqGEnYcHmYcHmreDyrP//rP//rP//rP//rP//rP//rP//rP//rP//rP//rP//rP//rP//rP//rP//rP//rP//ieb/uPL/FJC3RycOh0gXnFAWnFAVpFcdrWEmAKNhLaJgK6NhLJ5bJZtWIZ1XIppVIZtXJJxYJp9ZJ6JbKaFaKKdfLaxlMqtkMq5nNatmNKpjMadgL6ZfLqplNK1oN6ZhL6ZhLqpmMa1qM65pMqlkMKZiMadkMqZjMKVhLqplMqtkL6hgKqpgKq5jLKtgK6phLqhfKqZeJ6ZgJqZiKKlkLaljL61nNqtlN6liNqtnN69sO69sOaxoNatmNK1mNKxjMalgLqheLKxgL61kMK5lMaphLaRbJ6ZdKalhK6tjLa1lL6hgKqZeJ6RbJ6hfK6tiLqNbJaNbJKZfJqZfJKVdI6lfJ6ZcJKddJ6hdKKdcJqddJKZdIqVeIKdfIadfI6lfJo1iOGXD5mjH6XbJ5uH6/9H8/8v9/8X+/7z//7r//7r//7r//7r//7r//7r//7r//7r//7r//7r//7r//7r//5Dm/73y/zez2UUmD4VJG6RaIKdaIaxfJq9iKQCoZTCkYSqkYSqlYiulYCumYCujXSmjXiyiXSuiXCqmXy2mXy2nXy2qYy+sZjGuaDOpYy6mXy2lXiyhWymjXiyjXiyeWSehXCimYSupYy2oYSqjXSmgWymeWSefWiidWSWbVyKdVyGjWyWqYSuvZC+uZC+rYjCmXSiiWiSmYCamYSekXiecViGXUSCZUiWgWi2lYTGoZTStajiwbTmybjqybDexaTa0azmzajixaDapYC2jWiaiWSWgVyOiWSSjWyWiWiSfVyGiWiSnYCiqYi2wZzWyaTaqYS2waDGzbDOzbDKyazKyaDCvZS2sYSyqXimpXSilWiKjWR6kWx+lXSGpXyWlWiJyYkhoxOaP5/w0ud8nqtY8sdl4yeaV1eyz4vLr+v/g/P/H///F///F///F///F///F///F///F///F///F//+V5v/D8v9Iudw7NSiCSR+nXSapXCOoWyKlWB8Ao18ppF8pq2YwsGw2rmo2rWg1qmQyqmUzqWIwqWMxqWMwpmArpV8qolwnnlgjnVcimVMdmVMemFEel1AellAemVQinlgmnlgkoVolpFwmpV0mo1smo1wqnlklm1Uhm1YhnFcim1Qfo1smq2Iur2Uxr2YzsGg2s2w3sWo1rmgxrGYvp2QtpmAsp2Iwq2U2smw+rms6rms5tXE+sGw4rWgzqGItpF0ppFwppFsqplwrqWAtq2IuqmEtq2MuqmIsp18ppV4mpV4mp2AoqWIprWQvr2QxrWIuq2Arq2IsqmAorGMrqWAoqmAorGIqp1wmp1wmp1wmqV0lqFwjpVkgpFkgpVoipVoieGhPoNvyofT/j/X/j/X/f+r5bd/yScjmOLzfHavWa8Ti7fz/1f//0///0///0///0///0///0///0///0///neb/yvL/dszmMENAd0QdoFgjpVgfplkgqVwjAKplL7VvObVvOrJtObFsOqtnNadiMapjMaVdK51WJJtUIpZQG5hTHpVQG5NOGJFMFpNOGJhSHZpUIJ5YJKFaKKVeLKVeLKFbJ6NdKKZeKalhK61jLqxiL6piLqZfKaljLbNtOKxlMKpiLa5lMrFoNrFqOLJtObRvOrNuObJtN7JtN7JuOLBsN7FuOrJvPbRwP7BsOqdjMaRfK6FcJ6RfKaljLaReKalhLrFoN7NpObRqOLFoNLBnM7VsOLhvOrRsNrBpMatkKqpjKadgJqZdJaheJ6JYIKNZIKZdI6RbIaVcIaZdIqdeI6ZdJKlgJq5jKq1iKaxgKKteJaZZIKdbIqleJaheJXxsUKbd8qj6/5b8/5b8/5b8/5b8/5b8/5b8/5b8/zC53HzL5vP9/+z+/+v+/+b//+P//+H//+H//+H//+H//6Pm/8/y/4nS6SdRWG0/GqBaJrJnLrZqMbltMwCrZjGtZzKoYi2gWymjXi2gXCufWimiWiiiWSegWCagWSajXSikYCunYy2gXSahXieiYCikXymlXyqkXimmYCuiWymeVyWgWSWkXSilXCilWyaoXSijVyOdUh6eVR+fWCKeVyKdVyKkXyusZjOuZzasZTSrZzKrZzKpZjGnZC+lYS2pZTCrZzKtajWoZjGkYS2jXiueWCWhWiapYy2rZS6uaDKvaTSyaze0azqyaDiwZzatZTKrYi6jWyajWyWkXCanYCinYCerZSqqZSmnXyOnXSKnXSGkWh2hWBmmXR+nXyCmXR+hWBqeVRecUxWeVRaiVxukWB6qXSSrXiSpXSSnXSKhWBt0ZUWq3vKs/f+Z//+Z//+Z//+Z//+Z//+Z//+Z//+P+fw6v98krNZAstlfv99+zOas3u+85fL4/v/4/v/0///A7P/e9f+75fIjYXByQh6jXyuzaTCwZiytYykAnVcioVsmpV0rp2EvqmQ0q2Y2rWc2tGw6t248rGQyrGYzr2k0qWQwp2QuqGYvqGYvpWMrpmEqo10noVslo1wnoFglnVUinlUhm1IdmE8ZmU4amU4ZnVEcnlMeoFYgoVgjpFwnqWMvrGc1qmUzqWQzqGIwqWQvqWQvqGQxq2c1r2w5q2g1pmMuoF8pnl0momEqqWUxq2YxpmArpF0npl8nqWMrrGQvqmMvq2MwrmQzqGAupFwpqGAsq2Qvr2kzrmkwrmgurGctq2YqqmUprmUnsmgprmQkqV8fpVwbpVsao1oZolgYoFYXoVgYoFcWo1wYrGIhrmMlr2MnrmInqV8jqWAirGMlmGw8dsnmzPv/mf//mf//mf//mf//mf//mf//nv//0vv/1/v/w/z/vfz/ker1fuXyTszmOr/fJ7PZGqbSQLLZcMXigMzmj9LpLXmMklYprGUvsWgurmUqqV8kAKNbJqdeKaheKahfLKhfLatjMKtiMK1kMK1kMahfLKtjMaxlM6pjMa1mNKtnM6VhLKRgK6ReKaJaJp1VIZ5VH55UH5tRGp1TG59UHJ9VHZ1THJxSGqNYIKZcJaddJ6xjMLBoNrJrOa5pN6llMqdkMKZhLKZdKqddK6ZdKaZeKqZgLKlkL6xnMqxpMrFuN7BvOK5sOK5pNrBpNK9lMa5kL7BkMLFmMK9mMK5mMbFpNK9lMLBlMbVqNrNpNLBnMbBnL65lLK9nLK1lKK1lJ7FnKbJnKK9kJrBmKKxkJalhIqtjJK5mJqxjJLFoKbRrKrNpJ7NpJ7BnKK5mJq5kJ7JpK7BnK7NoLbVpLlGNlOP0/KT//5n//5n//5n//5n//5n//9f8/5fW7FaZq1ilunrK5ojQ6bXi8sTo9dz8/9f8/8b9/7b+/1XF4jBpdkZ3fIZrTadfKqZdJKZeIqVdIJ5WGQCvZzGvZjCrYSypXiqgViKfViKcUh+eVSGhWSahWSekXSujWyqiWiqfWCafWSedWCabViOgWiihWSegWSWlXiipYSqsYyqvZi6sZCyoYCmqYiqsYyqwZy6rYiupYCusYzGpYjClXy2kYC2mYi2lYiumYCumXCmmWyimWiemXCepYCquZjCuaDGtZy+wbDSvazSuazW0bzq2bzm4bjmyZjGzZjCzZzCxZzCuZi6uZi+xZS6xZS+xZS+yaDCyaDGxaC+yaS6wZyqtZCatZCSsYiSvZCawZSe0ay21bS+3cDG6czS2bzCtZCaqYSOoXyCqYCCsYyKrYyOtZiapYiOtZiewZyuzaC2yZiycbUJevt/s/f/h/f/K/v/K/v+x///J/v/J6vVBb3eUVietZiyqYiSSZTd7a0xceG5TfnxJmKtcp7xdvt9OuNx6Y0egWCajVyKiVx+lWyGqYSaqYiWqYyUArmYwrWUvrGMtq2Esp10qpFwpp18sp18sqGEupF0rpF0rpV0tpFwsoFgnoVopoFoonVgmoV0roFoooVsoqGItrWcxsGo0tG44t3A6tHA6s245tG42t3A3sms0rmYyqWEvo1wqo1wqpGAspmItqWUuq2UvqWArq2AssGYxsGYwrmQtrGMrrGQrqmMpqmQpqWMqqmUsr2kwsWkwt241t2w0tmsztmsztGoxrmUsrmQrtmowtmgvsGUrsmgusmgvsGcsrGMnqF8hqWAirGQkrWMkqF4fqmAhrmUntGwtunIztGwtrGQmpVwfo1oco1obplwcqWAgqWEhrWUlsGkqsmsstWwvtmwxtGkvtGcuWoJ+W6CvSrDPccbigczmn9nsv+bySJ21hFInpVwkqmEkq2IkqmEkrGMnrWMorWMor2YssGcurWUtqWEpqV8nql4mrWEqs2gwuG40unE3unI3vXU5AKNbJaVeKKRdJ6phLa1kMqxlM65oNq5nNaxlM6hgL6ZeLq1lNa9nN69nN7NsOrRtO7FsOrVxPrBsOq9qOLFsOrJtOa5qNa5pNa5pNbBtOrRxPrRxOrVwOLdxO7dxPLRtObJrObZwPLVxO7JvOLRxObVuOLFoMq9lL6thKqlfJ6lgJ6ZdIqhfJKhgJKZeIaZfIaZfIalhJKtjJ6xlKK5mKbBnK7VrMLNpLrVqL7ptM7hrLbZpK7FlKLFmKa1jJ6xjJqlgIqxjJbNrK7ZuLrVsK7JoKLJoKLVrK7NqKrJpKrBnKa1kJqdeIqVcIKFZG6lhIbVtLbdvL7p0M7lyMrhxMbtyNLpxNLlwNLZrMbZoL7FlKq9lKqxjJphsPYR0VH9xUaBmMa1jJq5kKKxjJa9nKbFoKq9lKLFlKrJmK7FmK69lKrBnLLJpLrluM7xwNbxvN7htNbVqMrVqM7ZsNLlwNgCgWCKhWSOgWiSnYCunYC2mXy2oYzGuZzWwaTesZTOzbDq1bT23bz67dEK3cT6ybDewazWuaTSxbDiybTuvajixbDmwazixbDqzbjyxbjusaTWpZy+raC+raDCvaTOtZzGpYy+sZjCtZzGsZy+sZy6tZy6pXyemXSSpYSavZiuuZSmtZCerYiSnXR+jWhulWxuhWBeiWRigWBiiWhqlXh6mXyCrYySxZimzZimxYiawYSCwYyKxZia0aimxZyizaiu3by+6cjK9dTW+djS9dDS+dDS5by+3bS2zaiqzayu0ayy5cDK8cze/dTq+djm3cDGuZyisZSWwaiirZSOvaCi1bS2wZymwZymrYietYCesYCWrYSWvZim2bi+3cDG0bCy0bCy1bCyyaSuuZiivZymxaCqxaCqzaCu1aiyyZymuZCevZiixaCu1ay24bC+1aTCzaDC1aTO2azW0ajO2bTMAqWErq2UtrGYwrGYwqmQwrWYzp2EuqGAtq2MvqmIurWUxrmUyrmUzsGc0rmYxq2Mtp2ApqmMsr2cxsWo2rmYzrWYzsGg2s2s4sGg2q2QwqGItqWQrp2MopmIoq2UtqGMqoVsjolsjoFohol0ipmAlqGEmrGMorWUpqGAjpVwfoFYYpFkao1kaolgXplwaq2EerGEeqmEepl4bp2AesmsptG0qtWwrsWYmsWMlsmQksmQhtmoluW4quW8tvXMywno6wXk5uXExsmoqs2wqsWgnq2Ehplwco1kYqmAetGsruHAxuXAztm0xr2UrrWQpolodmFETpl8frWYltm8tuHAut28usmkrsmkrsmksr2Yqq2ImrmUptGwvtm4vs20tsW0stW4tt3EuuHEwunM0uHEytW4vtWwusWYorGEjql8hplwerGMlsWgqtWsrtWwttWwwuW42vHA7vXE8uW03tWsyAK5nMK5oL6xnL6xmMKtlL6xlMKtjL6piLKlhK6hgK6hfKqddKKhfKatiLK1kLapiKa1lK7ZsM7JoL6xjK6lgKqheKaddKaRZJKJXIadcJKphJ6liJqhjJrFrMLNtMrRuM7hxNrZvM65oK65nKqxlKKpjJqdeIKJaHKJZGqVcHa1kI7NpKLRqKK5kIbNqJ7NqJrJoJLFnI69mIq9nI7NrKK9nI7BnJLRpKLZpKbptK7xvLLVpJLJnI69mIrBnJalhIaNbG6NbG6dfH6tjIqxjI61kJLFoKLdvLLx0Mbx0MrdvLrVsLrVsL7lwNL51OrpyNrFpLLNrK7hwLr10MblxLrlwL7dtLrBmJ7ZsL7ZtMLxyNcB4O794Or12N715OLl1M7x3Nb95NrdxLrdwMLVuL7lxM7hvMbRqLLVrLbhuMLRrLb11N8B4Ob1zNbtyNblwNbtxOLhtNrVpM7VqMrZrMgCwaTGtZy6taC+sZi+pYiunXiirYi2uZi2uZi2waDCsZCupXyenXSWqYCemXCKpYCSoYCOrYiStZCixZy2tYyqlXCSkWiKlWiGjWR6mWx6pXx+qYSGpYiKrYiOoYSGrYyStZCWsZCSsZCWwaCmvaCmtZiauZSWtZSWwaSi4cS+5cS6zaSeqYR+pYR2sZCCwZyOvZyOwZyOuZSGuZCGtYyCxZiKxZyW5biu2aym0aieyZyKuZB+tZSCsZSGoYR+qYyKvZyezayuyaiq1bS25cTG8dDS8dDS+dzS/eDW8dTK4cS+6czO6czS+djm7cze5cDa+djm+dTa+dDK5biy1bCiwZiSuYyKuZCSzaCq5bjC6cDG6cjO4cDG1bS6xayurZiOrZSKmYB2pYx6rZCSuZyi5cTO9dDa+dTfAeDm+dji8dDa9dji9djm+djq+dTq9czjAdjy/dTy/dDu8cji+czkAs2ozsGkxr2gvq2Qrpl0lplwkrmQts2svtGwwvXQ5u3I4tGswtGsvsWgrrGMmq2MkrGQjq2QirWYksGgprWUosGgst24zt24ws2kpsmYjsGQfqV8apV0Ypl4apVwZpl0aqmEdsGYksWgnrmYlrmYlsmoptW0rtm8stW4rtW4rsmsorWYjsmsos2wps2wpsWonqWIfqV8dsWYksWUitWcks2UirmMfr2UhqmIeqGAcr2citW4ptW4rt3AuuHExvnc3wHk5wno6vnY2wXk5vnc3tm8wr2gpsmops2wptW4rtW4runM0v3g5vHc5unI3vnQ7v3Y7t20utmspsGUhrWIerWIesWUjs2gnvXAxu2wttmkprWEhqFwdpVsboFYWnFMRn1cUpVwZq2Mfs2sruHExvXU2vnU3vXQ2vXU2vHU2uHI0tnE1tHA0uXI4vXQ7vHM5vHM5vHM4vnM4vnI3vXA1ALJpM7BoMq9oL69mLaxjK61jK7FnLrFqLbNqLbFoK6xjJqpiJLBnKbFnKLNpKbFnJq5kI6xlIatlIaVfHaNcHahgIqlgIqphIa5kIa5kHq1iGaheFqZcFaheF6heGatgG6leGqleGqZdGqZdGqJZFqJaFqNcGKZfG6xlIbNsKLlyL7pzML12M711M7hwLbVtK7VuK7FqJ7RpJ7VpJ7BhH6xeG69jIKxiH61nI7FsJ7ZvK7lyLr13M754NcB5OcV+P8F4OsJ5Or92N710NLhwMbRtMLNsLbVuLbdwLrVvK7NtKa9qJ69qKKpmJ6lhJq9mLLBnLK5kJrRqJ7NoJLJlIbRnJLhsKrpvLrdqK7JjIrVmJLhqKrhpKrNmJ7FlJrpuLbtwLrpvLLpwLLlxMLx1Nb94OL12N7t0NbZvMLJsL7RuMrd0N7d0OLlyObtyOrhvN7dtM7RrL7dsMLltMLlrMACyazOzbDSzbDOzbDK3cDW5cji2bTK0ay2uZyerYySpYiGoYR+pYiCrZCGrYx+pYR6tYyGtZSSvZyWtZCGsYR+tYiGsYiGrYiGpYR2rZB2sZRuvZh2tYxyuZR+qYRukWxakWhemXBmsYh6vZSGtYx6vZSGwaSW0bSm4cS28dTG6czC2biq1bCi2ayi4bCm9ci6/djS/dzW8dDO+dDPBdTXCdze+dDO9dTTEfju3dDC2ciy8djC+dzO4cS60bS24bjC1ay24bi+4bi7AdTXGfT7CeTzAeDq8dDWzayuwaiewaCetZSWnYCCiXB2nYCOtZCi0ay67cjO+djS9dDG6cC66cS+9dDS7cjO5by++cjDDdzTIfDrIejrIejvHejvIfT3DeTjAdzbAdje+dje9dzjBejrBejq/eTm+dze4cjS3cjW0cTWxbTKqYiirYSiqYCeuYymvZCmwZCmyZiqzZisAsmswtG4ytm8zuXI1tG0wt3E0tm4xtWwttG0ttG4rsmwpr2olrWgjrGYhsWomuHAtunAuuG8wt20utmootGcktGcltmsquXAvs20ot3EqvncuvXQsvXMtwHgywng0vHMwt20ruW8tuG8ruW4qv3MtvXMtuHAsuXIut3AstW4qtm4qvXMvvHIuvXAtvnAtuGsounEvvXU0wHc4xn0+x30/w3k7uXAxt28ws2wrsGwotXEqr2oip2EcoVoXo1sbqV8gsWYntWort20tvHEwvHIzuW8yunEzuXEyuHAxunIxvXY1v3c3v3c3wno7w3o8x35Axn0/xXw9x4A/wns5wno5xHw8w3s8vnY3wHc3vXYyv3czv3Uyv3QyvXEyvXEyv3Q0vXM0vnU3wHk6v3g8wHo8v3g4v3g4unMyu3Q0vHY2uHM1tXA2unM6uW82uGwzum41um00tmovsmYrsGQpsGQpALhwMLRsLLRsKrNsKbpxMLlwLrpxMLdvLrt0MrZwLLVwK714M7l0L7VuKrFqJq9nJK5lI6tkI6xjI69kIq9iH65iILVqKrlxMLp0L7ZwKbhxKLRsJbRtKLhvK7txL7dvLrRsK7dtK7ZsKbRpJLdrJbdtJ7ZtKbBpJaliHrNrJ8F4NcJ5NbpvK7RnJLNlIrRnJLFoJrNrKrlvL7JnJ6xgIqtgIqtiIqhgIKNcG6JdGaRfGKRfGKtlILdvLb11NbpwMbRqKq9lJaxhIK5jIbBmJa9mKLJpK7lxMb93NsB4Nr53NLx0NLx1NL52Nr52N7xzNb11Nr52Nrx0NLt0M7x1Mr92NsJ6OsJ6OsJ5Obx1M7t0Mr10M8J4Nr1zM7txMblvL7pwMbtyNLpzNb12Obt0NrZvL6xlJaZfH65nJ7JrK7JrLbJrMLVsM7ZtNLJoLq5kKrJmLbVqLrVqLrZqL7FlKgCsZB+uZiGwZyKuZh+vZR6uZB6sYh2mXhujXBmjXBmlXhqpZB+pZB6lXhqgWRWhWBSiWhahWRmkXBuuYyGxZiKxZiOvZSWpYiCmYRynYRuqYhqjXRakXRmoYR6sZSKlXRyiWxmlXhuoXxutYh21aSOzZyK0aSe1aym0aii0aiiuZCKtYyGxZSOyZiSxZSOyZiSuZCKuZCKwZCStYCGrXh+rXyCrYSGmXRymXxyrZCGuaCK7dS7Ffzm7dDCzaSevZSSvZSS0aii4bCm7cCzAdTXCeTrAeDi7czK6cjC6cjC6czC8dTK+dzS+dza7czS8czW4bzG2bi+4cDCzayq6cC6/djS+dDS+dDS8dDS5cTG1bS2waCivZiaxZyewZiavZyewaCmyaSusYyWrZCWtZiewaSmvaCitZSWuZiavZietZCerYiitYyutYyqnXiSmXSOrYSevZiqxaCyrYiWqYSMAp18Yp18XqF8Wpl0Tp14To1sQoFcNoloVqF8cr2cjsGols20nsWslsGgjsGgirmUgr2UhrmYlrWQisWcksmcjsGcjsGclsGonsGsmsGoksWkhsWoktG0qs2wprWYlpFwcqGAfrGQhr2Yit2wnvnIsvXEsvnIwwHUzwHQyum8ts2knt2spvHAuvXEvvHAutmsotGonsWYksGQjvHAvwHQywXQzwnY1wHY0wng2v3YyunMut3Eqt3ErtG0pt24runAvw3k3xnw4xHk1w3gzvHIwt20tuG4uuG4stGsosGcksWglsmomsmkntWwqt24ut24wuG8xunIyvXQ0wXg3v3UzvnIwv3Qyv3MyunAvs2wtsGkqs2sss2srtW0ttW0tsmoqsmortGsts2ostW4vtm8wt28wt28wuG0vs2krr2QnsGQqtWkvtmsxsmkusWktsmkusGctrmUqpV0ho1seo1oeALNsJLBpIbJpILNqIbNqH7NrH7hvJbhwKsB4Mr53McR9N8R8NsJ7NcJ6NMd+OMl/Osd9OMF6N8F5NsJ4NcN4NMF3M711MrhyL7x1Mb52MMB3L8F5NMJ7N8N8OsF6OL12NMB4Nr52M792MrxyLcB0L8N2M8F1M8N3Ncd7Ob90MrhtK7ltK7hsKrltK8B0Msd7Ocd+OsJ4NLxwLbxwLbdqJ7JlI7NmI7VqJ7NpJbJoJLBpJK5oI7RtKb11Mb1zMbdtK7ZtKbdtKbhtKbdsKLJoJrNpKLdtLLdtK7ZtKbRrJ69mIrBnI7FoJLVrKL10M752N8J6O8R7PMF3N8V7Or5zMbpuLL9yML5xLr1yMLtyM7x0Nb52N793NsR8O8J6OrpyMrhwMblwMrxzNbt0NbdwMbNqLLNpK7ZrLbZrLbZpLbVoLbBjKqxgJqlgJKtjJ6pjJ6liJ6hhJqFZHqNaH6lfJAC5cyu3cSm3bye5cSi2biS2bSO4byW5cCm4bymxaSKwaCKwaCKyaiS2bSe0aiS2ayW2ayW3byq5cCy3bSi7cCq7cSy5cS23cC27cy+/di+9cyq4bii2byy8dTK7dDG2byu3byy4cCzAdzO/dDC+cS29by24bCq2aiizZyWqXhyqXhy1aCa6bSu+cjC/czG8cC6yaSWqYByhVhKfUw+iVRGqXRmsXxuxZCG2aye0aia2biq3cCywaCSrYh6uZCKzaia2bCi4bSm5biq2aye2aym9czK7cS+7cS+9dDC9dDC+dTHBeDTBeDS+dDLAdjW8dDO8czK7cTC3bSy9cjC6biy4aym6bCq3aSa6bSy8cjO5cDC1bSyzayqvaCWuZiWuZiauZSavZiivZimtZCatZCasYiSuYyWtYSSqXSCoWh6lWB6kVx6jWB6gVxqfWBmmXiKqYyisZCqsZCqwZiywZSwAqGEbpl4Yp14WqV8WrmUbt20juW8lt24ksGYer2YermYer2chrGQeqF4YrGEbsmYer2Mcr2Ufs2kis2ggs2gfuG4mvHMutW4qtm4ptWsjtmoguW0lvHItu3Ittm0pt24quG8ruXAsvHIuuW4qt2snt2sot20rtWsptmootGgluWwqvW8tuGontGgmsWUjrmMgqF8bplwXql8aqF0XqFsWr2IdsmUfs2Yhs2gjt20ptm0qsmoosWkmtWsquG4st20quG4quW4qtmsntmsnuG4runAwu3Ewv3UzxHs3yH87vnUxs2omsWckrmQir2UjsWgktGkmtWkns2cltGclsWQisWMhsmQitmgltWclsWUksWUksmglsmklrmYirGUir2cmrmUms2kss2gtrmUnrWQmrmQmrmIlrGAkplofplofrmIorGAnp14jq2MlrmUmrGIlqWAmqmAopVskpFojolcgAKtiGqxiGq1iGq1hGK1iGK5iGLRpH7NrHrFoHrFoH7BmHq1kHK1iHLFnILBlHbBkHKxgGK9kHLRpIbRpH7ZrH7NpILBnILRsJrZtJrFnHbVpHbdrIrdrJLNnIbJmIbRpJLRqJLRsJrZrJ65jH7JmIrhuKrpyL7lwLLNoJLFlIrttKrttKrdpJrhqJ7lsKbpvKrlxLLlxK7lwKbZsJLVpIrdrI7ZqIrdsJbhtKLdtKbhuLbhvL791NcB2NrxyMLpvLbNnJLJnI7JnI7VqJrpwLr91NcF3N750MrVsKbNpJq5kIaheHKddG6pgHrBmI7RoI7NlIbVnJLdpJ7VnJbBiILBiILFjIa1fHahaGK1fHK1gHaleGalgGq1lIK1mIqxkI6tjJKheIatfJKphI69lJ6xiJK1hJrJmK7drMLxvNbZqMLJoLrNqL7VrLa1iJK1jJqpgJqRaI6FXIp5UH5xPGwCvYxu0aB+0Zx6yZBuyZBqxYhexYxmuYxiuZRqxaB+2bCS7cCjAdS/Cdi/AdS2/cyrBdSy9cyq2ayG5bSK1ah2vZBmyaSC2bSW1ayO0aR63ah2xZBmuYhmvZBuvYhuwZR65byi5byq+cy++cy+/dDHAdzS9djK9dTG/dDC9cS26bCm4aSa6bCm6bCm2aCW4bSi0bCevZyG0bCS3bia6cCe6bybAdS3Adi+/dC++dDC9dDO9cjS+dDW5by+0aii3aymzZySwZSGxZSG3aie5bS20aSqpXx6nXRymXBqiWBWgVxSmXBqwZiS5by27byy8bym6bSm5bCm3aii2aCa0Zia2aCi4aSi0ZiS0ZiS5aia2aCStYButZBytZR6tZiGrYyGlXR6pYCKrXySrYSOoXR+oXCCsYCWsYCWvYyitYSirYSetZCqwZyyuYyWuYSKvZCexZy2wZi+tYi2uYi+yZTMAtWkftmofum0jum0it2ket2keuWsftWsgtmwitm0jrmMbr2Qbs2cdtWoftmofu24juGwftGgdtWoetWkctGkbuG0ium8ltGohuXAmvXInuGsfr2IYq2AWqF0UqFwVrGIbsGYet2slum8os2gisWYhr2UgqmMfqmIesGYjs2gltGclt2kotWgmrmAerF8csmcksGklsmsot28rvHItwngzyH84xnw2wngywXcxu3Itt3Att24uuG4utWsrtmwsvHAvtmoos2cktGkltWgkrmEgqF4cqF4bq2Eeq2Ifq2IgsGcltWwqtm0st20st20qt2wot2wpt2wptmsquW0tvnEzum4vuWwtwHIxwHMxvnAsuWwntGgjsmcgsWchsmgksmgltm0sunEytm0wt20xtGkttGgusmcstmowuW40uW40tWsysmgvs2kws2Yqs2YpsWUqsmgurWMrql8pq2ArsGQvALtuI7drH7puI7drH7ZqHrpuIbpvI7xyKLtxJ7ZrIa5jF69jF69hFa5iE7BjFK9jEq1hELBiFq9iFq5gFKxfE65hGLFmG6pgFaxiGLBlHa1jGqxiGK5kGrFnH7VqJLZrJbRqIbJmHKtgFaRZD6FVDaJXEaheGa5kILFmJLRpJ7htLbluLrVqKbRpJ8N4NsV8OsR9PMR8PL11Nb50M8F2NbpwLrJpJbRrJq9mIK9oILBpJbBnJK5kI7NpKbZrLbhsLLpuLbpuLLZrJ7hrJrVpJbRpJbZrJrRsJbZvKbhxLr10NLxzNbpxMbhvLbdtK7ZsK7NqKrBnJ7BoKLJoKrNqLLNoKrVqLLZpKrhrK7hsKrZsKbRqJrZsKLdrJ7lsKb1wLbtxLrhwL7dvMLduMLNpLrRqL7RqL7JoLbNpLq1iKatgJ65iKrBkLbNlK7JkKq9iKa9kKqxhKKpfJ6pfJ6xhJwCvYhmuYhiwYxq2ah+6biG5biC7cSS4byS1ah+1ah+vZBepXRCrXRCuYRKtYRKoXQ6qYBCuYBOuYBSvYRWwYhauYhauYhasYBWvYxmuYxmtYhixZhu0aR64bCO4bCW0aCCoXROgVAmmWg6rXhStXxexZB21aSS7bim8byu/cS6/cTC9cDDAdDK+cjC5bSu0aCavZSKoXx2rYB+sYB6tYB6tYB2zZyOyZyGxZx+xaCCxaSWzaii1ayqyaCiuZCSzZyi2aSm4bCq9ci7BdjG9ci66byq7cSu8dCy9dS+7czC8czO8cTO6bzC8cjG7cS+4biy2bSuzaiqxaSq2bS+1bC61aiyxZyeyZie3aiuzZie1aii4biy4bSu7bSu+by68bCu6bSy2bC2waCmuYyWpXiGqYCKpXiCqXyGrYCKsYCSvYyixZCuuYimtXyWsXSOtYCerXiWqXSWpXCSnWiKhVBsAsmYetWkgtGkfs2gcs2kcsGYYsGcZrmYYpl4Qq2IUr2UXsWYYsmYYr2MVq18Rql8RrGETs2UZtmgcumwgtWcbsWMXsWMXtWkdtmoft2sfsWUZqV0RqV4SqFsSqVwVsGMbsGQZr2MWr2QXr2IXr2AYsGAatGUft2gktWUismMgtGUjr2Afr2Efq14cpVcVql4brWIerGEdqVsZp1kXrF4bsGIetGYhrmIcql4XqmAYq2Ier2cksmoosWcnuW8vwHY2xns6yH06yH06yH05wnczu3AsunAqu3MrvHQuunEuvHExv3I0wHQ1vXExuGsqt2wpt20ruG4uuXAwtW0usWgpsmkqsmgptmwruGwrsGIjsGMktmkqtWcot2gpuWgpt2Qmr18hplkboVYYolcYoVcWplwbpFoZpFkYpVsaqF4eql8hrGAkrGAlqVwhqFkfq1wjplceplcfpVYepFUdn08YALpuJ7RoIbJmHbJnHbJoG65kFqphE61lF65mGLBnGbRqHLVqHLVqHLVqHbVqHrVqHbNoG7FjGbBiGLFjGKtdEadZDahaDqZYDKZZDaZZDKJVCKJXCahcEK1gF7FjHLRnH7VpHrpuIbhsHrVoHLhpILpqI7ZmH69eGqpZFaRVEaJUEahaGLRmI7drKLpuKrtwLLpvK7htKLVoJbdpJrlrKLZoJK9hHa1fHLBkH7ZrJrpxLb53NMJ6OMd9PcV7O8F3N8F2Nr9zMbhtKq9kIK1iHq9kILFnIbBoILFpI7FnJLRpKrNmKbBiJbBiI69iIKxhHq1jIaxiIaRbG6FZGZ5WFqZeHa9nJbBnJbFmJLRlJK9jIrFlJLRnJrFhIa9dHalWFqJREqBRE6BTFKJWF6dbGqZaGadbGaZbGaZbGatfH6peIKtfIa1gJK1fJalbIqdZIKZYH6ZYIKdZIaNVHqVWIACyZCCuYRuyZh61aiC2ayCzaRuxaBqzax23byG4byG2bB64bR+3bB+3bB+vZBitYhesYRatYBesXRSqXBKqXBGpXBGmWQ6lVwyqXBCtXxOwZBe7byK9cie9cCe9byi5ayO2ah+4ax+4ah61aB22aCC2ZyCyZB2wYRyuXhqxYx6zZiK3aie9cy++dDC4byu5cC29dDDDeDbHeznG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AJhOAP///////////////5hOAJhOAP///////////5hOAJhOAP///5hOAJhOAJhOAP///5hOAJhOAP///////5hOAP///5hOAJhOAJhOAJhOAP///////////5hOAJhOAP///5hOAJhOAJhOAJhOAJhOAJhOAP///////////////5hOAJhOAP///////////5hOAJhOAP///5hOAAC8dCy4cCi2bia4bym1bSe4byq3byu5cy66dTC2cCu1byq4cCu9dTHCeTW9dDC7ci68cy+1aya1aia4biq6cS26cS26ci+5ci+7dTPAezrBfTy9eTe4czG7dTXEfD7GfkPEe0DFfEHEez7DejzEfD3FfDzEezvCezq+ejm5dDO9dDPDdzjHeTrEeTnFfT2/eDa8dTG6cC+3bC24bi++dDS7cTC8czC9dDO9dDa9dDa6czO6cjK2bi62bi6YTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgAAwHcvu3EpuW4nt20ns2kluW8qvXQwu3Uwu3YxvHcyvngzu3QwvHUxvHQwvnUxvnUxvnUxvHIuwHYywnk1v3czvnYzv3g1v3g2wXo5xX8+xYBAwn08xH09xn9Ax4BBx39Cw3w/xHxAxn1Bx35Axn0/x34/yH4+xX8/wH08unU0u3Mzv3Q0wXM0wHQ1u3MzunMwt3AstWsps2kptWsruG4us2kormYjr2clrWUlrGUmqWIiq2QksGgotGwsmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4AmE4AmE4A////mE4AmE4AmE4A////mE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4A////mE4AALNoH7JnILZsJbtwK8B1McN4NMN6Nr12M7VvK7p0MLVvK7hxLr12Mrt0ML10McN5NsV8OcJ5NcJ6NsN7OMF6NsB5NsJ7OMR9PMiBQceAQMR+PsF6OsF6OsR9PsR8PcR8PcN7PMF5O8J5PL10N7ZtML50N8Z+P8J7PL57O714OMB4OMB1NcB0Nb91Nbx0M712M753Mr1zMLxyMb1zMrdtK7ZuK7dwLLRuKrFrKbBqKbVuLrhwMLZuLrNrK5hOAJhOAP///5hOAJhOAJhOAJhOAJhOAJhOAP///5hOAJhOAJhOAP///5hOAP///5hOAJhOAJhOAP///5hOAP///5hOAJhOAJhOAP///5hOAJhOAJhOAP///5hOAJhOAJhOAP///5hOAP///5hOAJhOAJhOAJhOAP///5hOAJhOAJhOAJhOAJhOAJhOAP///////////////////5hOAP///5hOAAC6bye8cSq9ci2/dTHBdjK8ci61bCi2byy4ci+9dzS8djO9djO+dzS/eDXCeTfEejjFeznBeTXBeja/eDS6czC6czC8dTK+dzW/eDe8dTW8dDS/dzi/eDnAeDm+dja+djbCejnCejrCeTvAdzq9czjEfD/HgEHDfT7AezzBezvEfT3DeTnCdzjAdTXBeDa6ci+6cS23bSu3bS22bCy4bi23byy4ci65cy+5dDK3cjK7dDW4cDGxaSmrYyOYTgCYTgD///+YTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///////+YTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgAAv3Yvw3k0v3cxvnYyv3cyvHUwvXYywHo3wnw5wHk2wHk2wHg1v3g1v3c0wXk2u3EvuG4stm8rtW8rtm8rtG0qt3AtuXIvu3QxvHUyvHMzvnY2wHc4wXg6vHQ0t3Auu3QxvHUyuXEvvXQ1wHg6v3U7wHg7wHk6vnk6vHY3uXMzu3Q0unIxt24ttm0rsmgmsGYksGYksGYmqV8gql4hsWcotGwqsWsns24rtXEvs28vuHEyuHAytm0uuXExmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////mE4AmE4A////////////////mE4AmE4A////////////mE4A////mE4A////mE4AmE4A////////////mE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////mE4AmE4A////////AL12MMF7Nb12Mr13M8B7Nbt2ML54M8F6N8J7OMF6N7tzMLxyML10Mr91M8F3NbxyMLhuLLlxLbdwLLdwLLdwLLhxLr53NMJ7OMB5Nr50M710Mr50NcJ3OL1zMrtyL711MLxzL7duK7pvL7ZrLbBlKLJpLLdwMbdwMLZvL7lxMblxMbVtLLVtK7tyMLluLLVqKLJoKLZrLbluMb1xNsF2Ob10NbpzMLx2NLx4OLhzNbdvMbVtLbdvL7txMZhOAJhOAJhOAP///5hOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAP///5hOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAP///5hOAJhOAJhOAJhOAJhOAP///5hOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAAC/eTS7dDC+dzPAeTTEfTjFgDnCfDXBeDW+dDK4biy3bCq7by2+cjC/czG9cjC8cS+6by27cS68cy+5cCy3byu3biq3byu6cS26cS28cy+9dDC9ci/AdDK/dTHBdzPDeDPCeTXBeDS8ci+0aimzaSm0ayu4cjC7czG5by67cC+5cC65ci+8dTK6cS+5biy4bSu3bS27bzG/cja9bzS5bTC4bi+5cS+9dzW6czSzay2xaCqsYyOtYiOqXR6YTgCYTgCYTgCYTgD///////////////+YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgCYTgD///////////////+YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgAAuXEtuXAtwnk1v3YxunErunIqvHMrvHEtv3IvvnEuum0rum0rum0qu24suWwqum0qum4rum8ru3Ett20puG4pt20puW8qu3EtvHItvXMv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aymtYyGtZCGtZSGsYyCxZya6bi68bzDCczXDdjW/cjK/czS6bjG0aSy3bTC4bTC5bTCzaCqwZCarYiStZSWwZyi0bCyYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgCYTgD///////////////+YTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgCYTgD///////+YTgD///+YTgAAvHMvu3Iuu3Iut28ps2sjtGwktW0lsmsitG0ksmoisGkgrmggqWMbsmsjuXEpuXEpt28nuXEnuG8muG4ntmwnt2wot2woum8rum8ru20qv3Atv3MvunArum8qum8qvXEsum4pwXYyvXUvuHErtW8rtm4stWsqs2kor2UksmgmtGonuW8tunAvum4vvnEzvXAyuWwutWgqsWQoq14kql0ktmowvnE4uWwytWkusmYrrmQosWgrtGsuuG8xmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4A////mE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4AALVsKLlwLLhvK7ZuKLBoIbNrI7NrI65nHrJrIbJrIrBoIK5mHrRsJrpyLLlxK7ZuKLNrI7NsI7BoH7NrI7FpI7RrJ7htKrxwLr5yML5wLrttKrluKrhuKrxxLL1yLcB1ML90L7ZrJ69mIq1mIaliHq5lI7BmJrNpJ7FnJa9mIq9mIrJpJrdsKbdrKrlsLbdqK7ZpK7ZpK7JkKLFkKbVoL7VoL7RnLrVoL7dqMbdqMbdtM7ZuMrhvM7lwMphOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAP///////////////////////5hOAJhOAP///5hOAP///5hOAJhOAP///5hOAP///5hOAJhOAJhOAP///5hOAJhOAJhOAP///5hOAJhOAJhOAJhOAP///////////////////////5hOAP///5hOAJhOAJhOAP///5hOAP///5hOAJhOAJhOAP///5hOAACyaSWyaSWyaSWxaSSzayS2bia3bya2bySzbCGuZx6nXxeoYBqtZR+sZB6pYRuzayS3bye7dCu3cCe4cCi5cSu5byq9cS+9cS+6biy8by27by25byu4biq5biq4bSm2aye1aiWxZyKvZiKwZiSuZiSxaSazaiazaiasYx+kXBeoXxqrYButYh6vZCCzZySxZSOwYyKvYiOvYiSxYye5azC2ai+0aC23azC0aC25bTK7cTe7cTa3bjKzai2YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgD///+YTgD///+YTgCYTgCYTgCYTgD///////////////+YTgCYTgCYTgCYTgCYTgD///+YTgCYTgD///+YTgCYTgD///+YTgCYTgCYTgD///+YTgD///+YTgCYTgCYTgD///+YTgAAt24quXAstWworGQfqWEaqGAYqmEZp18Vo1oRoFcPp14Ytm0ovHEtuXArv3UvvnQuvXQsvnYsuXAntmwlu3ErvHEsu24ruW0quW4ruW4rum4rtmsptGsovHIvunAss2kksmgjtWsns2ontWsqunEwuHAtuHAstm4ptW0nvXQtvHMsuW4ouG0muW4pt20osmgjsWYjsWUisGMjtmkqum0wtmots2grsmYqrmMmsGUpsWcttGsvtm0xvXM3mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4A////mE4AmE4A////mE4AmE4AmE4A////mE4A////mE4A////////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4A////mE4AmE4A////mE4AmE4A////mE4AmE4AmE4A////mE4A////mE4AmE4AmE4A////mE4AALduKrRqJq9mIq9mIapiG6lhGaxjGrFoHrZsJLtvKr5yLsJ0McR2M8J1Mb9zL75yLblvJ7ZtI7NpILhtJrxvK7ttKbpsKbhrJ7htKbhtKLdtKLZrKbNpJ7VrKbJpJbFnIrJoJK9mIrJoJrZsLLlvL7lwL7VuKrVsJ7RsJrdtKLhuJ7dsJbZrJLpwKrlvKrRrJ7FoJLVqJrhsKrtuLr1wMrxvMbhsLrdsLrdtL7NqLLRqL7dtMrdtMbpvM5hOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAJhOAP///5hOAJhOAP///5hOAJhOAP///5hOAJhOAJhOAP///5hOAP///5hOAP///5hOAP///5hOAJhOAP///////////5hOAJhOAJhOAJhOAJhOAJhOAP///5hOAJhOAP///5hOAJhOAP///////////////5hOAJhOAP///////////5hOAP///5hOAAC5biq3bCi5biq6byu4bSa8ciq7cSm5bye6bSi+cCy5aiizYyKuXx2qXBmwYh6xZB+vZR2xZh62aSK4bCW7bim5aya3aSW1ZyO0ZyK1aiW2bii0aieyaCeyaCa0aii3biq2bSm0aye0aii0aiqyZyiyaCmxaie0aye1bCi1aya4bSi4bSizaCOwaCKvZiKxaCS0aye5cC26cC26biy3aiu2aCu3ay62ay20aiyzai22ajC1aS+xZSqxZCmYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///////+YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///////+YTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgCYTgD///+YTgCYTgCYTgCYTgCYTgAAt2wotGkltGklt2woum8pvHEqu3Aqum4oumwpumspuGgotGQksGAfs2QitGcis2chsmcetmoivW8puWwmuGoltWcismQgsGMerWEbsGcgs2sjr2Yiq2Egq2Efsmgms2omsGYisWcjr2QirWEhr2IksGQmsWgnt20st24suG4qvHEtu3Arum8rtWomsmcltGootm0qtmwqt2srtWgpsWQmr2ImsGQosmYqs2gstGsvt2wwtGgutWkstWgrmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4A////mE4AALRp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r2Idr2Icr2MdsWYisGcisWgksGYisWYjsWckrWMerWMdr2UesWcftWkhtmois2UetGYft2YitWQgtmUhtmUhtGQhs2QhtGUis2UismcjsmcjtWomtGols2okt2wns2gjtGkkt2oluGwlt2sls2Uhs2UitGYkvnAtwHIvvnAtu20qtWglsmgmsGclr2YksmgntWsrunAwu3Iyu3MzunIyu3Q0um8zuWwxtGgssmcqsmgqrmUnrGQlqWEhpV0dpl0drGQirmYlsmoqtW0ttGssuG0vt2suuGsvuGovs2UquG0vvHQwuXIwtmwuuGwxvG82vXA4vnE4vHA1t2wutmwrr2UlrGAir2QnsmcqtWktuGwyvHE2v3M5tGovsWYrsmgus2kwtWoxu241vG82t2oxt2oxtWkvALlsLrlsLLZrKLNoJbVpJrVoJ7ZnJ7FhILJiILdoJbttKrhrKLJmIbJlILJmIbBjHrBjHrRoJLNpJbJpJbFoJK9mIqtjHqZdF6ddFKlfFKxiFa9kGrNmHrVoIbNlH7JiHrNjHrNjH7RkILVmI7BhHq9hHrBiH65jH61iHaxiHahfGqpiHK9kH7FmIbRoI7hsJrltJrpuKLptKblsKrtuLb5wL71vLbttKrhqJ7psKbpvLbluLbtwML1yMr1yMrtwMblvMLhvMLVtLbNsLLNoK69hJqpdIa1iJLBmKK5mJq1lJa5lJa5lJbVrKrtyMLlxL7lwMLpyMrpxMrxxM7tvMrpsMb1vNLxuM7tuMLlxL7hxL7ZsLbVpLrZpMLdqMLJlK7RoLLJnKa9lJbJmJ7ZpK7ptL7ptMLlrMLZqLrZpLrhsMbltMr5yN75zOLtxNrpuNLdrMbZqMLhrMrlsMrhrMQCxYyWxZCWyZiSwZCG1aCWzZSOzZCS0ZCO0ZSK1ZiO1aCSwZSCwZSCzaSS2bCe2aya1aiW2ayeyZyOwZSGvZiKuZSGuZSGsZB6xZx2yaBu2bB+5biS3ayS1aCGxZB60ZiG6bCe6aye3aCW1ZiOuYB6wYyCwZCCqXxuoXRmqYByqYR2wZyO2aye4bSi6byq5bim3bCe4bSq6byy8cC+6bS65bC25ayu6bCy7bSu8biu9cS+8by+7bi+7bi+6bC64ay22ay22ay20ayy1bS21ayy0aCq1aSuzaCqwZiaxaCi1bS23bS21aiu6cDC9cjO5by+5by+1bCyyaCqxZigIAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd67bzQAr2EirmEhrGAerF8brWAcrV8crl4dsGAfsmMhs2YitGcjtGoktGsluXArt24ptGkktmsntmols2cis2klsmklsmonsWomsGokuG8ouW0lt2sitWois2citGcis2Yhs2UhtmckvG0qumsptmgmsmUjsWUis2gktGkltWsnt24quXAsu3Iuu3Iuum8ruW4quG0ptm0pum8tvHIxvXIyvHEzvHAzt2osum0uvXExuGwqu20ruWsrt2gqtWUotGQns2QpsmUpsGUnrGMlr2YosWcotGgptmssuW8vuW8vt24uuW8vuG4uuGwtum0uvG8wtmwttGkrs2gqrWQmr2UoCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeuGwvAK9hIK1iH69kILFlH7FkHrBiHbFiHrVmJLhqJ7puKrdrJrhvKbx0LrlxK7duKLVrJ7JoJLRpIrZqJbVqJrVrKLRsKrRrKrFpKLVqJ7ZoJrhqJrptKLltKLhsJ7hqJ7ZoJbZoJbtuK7tuK7tuLLtvLbtvLLtwLLtwLLxyL750Mb1zMLhvLLZsKrhtK7tvLLluK7duK7lwLrlxMbZsLrlvMrluM7RoLLBlJ7BlJrFlJbVmJrJjI7BgIrJhJLRjJ7RlKrFkKK5iJqthIqphI61jJLRqKLlvLbpwL7xyMrhuLrRqKrZpKrVmKbJjJrFkJqxhI6xhI7BlKbFnK7JnLAgB3ggB3ggB3ggB3jcx5Dcx5AgB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3kZB5ich4ggB3ggB3ggB3ggB3rpuMACtYx2rYRutZByxZx2uYhitXxevYRm0ZSC1ZyO4aiezZyOyZyO1aiWxaCKuZB+tZCCtYx+vYx2xYx6uYR6xZyOyaSawZSSxZiW3aim4aSi5aii4bCi1aia2ayi3bCm2aym3bCu6by24bCu5bSu6byy6biy3aim3aiq6bS26by63bCy2ayq2bSu1bSq5cS20ayaxaSWyaiayaii0aym0ayquZCSoXh2pXx6uZSOwZiOzZSS1ZSa3Zyi2Zii3Zym6aiy1ZyiyZiexaCiyaiq2ayy4ayu4bCu3bCu1aiq1aCm2aCm3aCq0ZCewYSWtYCOuYyWxZSeyZSm2ai24ay8IAd4IAd4IAd4YEeDg3/vw7/03MeQIAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4YEeCin/P////////////g3/s3MeQIAd4IAd63aiwArGIarWUdrGUcrGQZrWIXsGMZtmgftGcftGYgr2EermAer2EfrWAdq18arGAbrGEcql8cqlwZrF0arl8crWAdrWIeq2AdsWUhtmkmuGkmuGkms2cjsWcks2knr2cmrmUns2srsmkptmwrtmoos2cjuGspuWoquGkruWsuum0wum0vt20ttm8stW8qsm0ntW8ntW4otW0otW0otW0os2olsWgkrmUhtGsns2sms2gltmgmumort2cou2ssvGwttmgotGcmtWknt28stW0rtWcntWYnsWIjrmIhsGQktWcmtmYntmYnt2cptWcqrWEjrGEirmEjr2Ijs2YosmUnCAHeCAHeCAHeg4Hv////////////ZWHqCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeGBHg0c/5////////////////////8O/9NzHkCAHeu24wALZrJrhwKrNrJK5lHrFlHrRnILZpIrRpIa9lH69jH7JlI7JkIrFjIbFkIK5hHKtdGKxdGq5fHK5gHbNlIrRnJLRoJLdsKLltKbhqJ7lrKLRmI65iH7FoJLNpJ7JqKrVtLbhvL7huLrdtLLZqKLhrKLttK7lsKrdqKrdqK7dqLLZpKrRqKbRtKrBpJK1nILRuJ7hwK7VrKLRrJ7NpJrZsKblvLbpxLrlvLblvLb5yMb9xMbprLLlqK75vMLdoKa9gIbJkJLRpJ7duK7NrKLFlI7BiILJmIrFmI7JnI7VnJLFhH7BfHa1dHatdHahbG6teHq9iIqteHqlcHKtdHggB3ggB3hgR4PDv/f///////////////2Vh6ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3sG/9////////////////////////////8G/9wgB3sF2OQC2aie1aye0ayezaSSzaCO0aCS2aia0bCWzbCa1aymxZia2aCe5ayi2ZyO1ZSG3ZSG3ZSKyYyCvYx+1aSW3bCi3ayi4bSm5biq6biq3bCi2aSa2aia7cy26cS23bSu3bS2zaSm3bCy4bCu4aii6bCm2aSayZySyZiWvYyKsYB+qXh2lXBqoXxysZB+uZh+yaSO0aSaxZiSyZyS1aSi3ayu5bC22aiq2aSq7bjC5bC61aCmyZSa0Zyi1Zie2ZyizZSa0Zyi2aiu0aiqzaSe0aCazZSOwZCGsYx6mXBenWhWpWherWheqWxmtXhurXRuvYh+2aCa4aiixYyKtXx4IAd4IAd51cez///////////////////////9lYeoIAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd6in/P////////////Rz/lGQeain/P///////////8nIeK/djkAr2Igr2QgsmcjtGkltGkls2kltm0os2slsmomtmwruW0uum4tu20rvm8rvW0pumgktmUitmckuW0qu3EtuG4qt20ptmwos2omt24quW4qt2wot24otGwms2ont20ruG0ttGgpsWUlsGMhsmMis2QhsWQgq18bqV4bqV4bqmAdqmAdpFsXp10ZsWcis2kjtmolt2omuGootGcltGclsGIisWMjs2UnuGkrtWUosmQnsGQmr2Qlr2Mks2UmtGcos2YntWgptWgpsWUmr2MjsmQksGMhr2Qhq2MeqmAbrF8brFwZrVwZqFgVp1kWrF4bsWQgtmgltGYjr2EfsmQiCAHeCAHe4N/7////////op/z8O/9////////////ZWHqCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeg4Hv////////////0c/5GBHgCAHeCAHe////////////RkHmv3Y7AK1gHLFlIbNnI7RpJK5kH65lIa1jHqxgG69jH7BjI7VnKLZpKLdpJ7lsKLtuKblrJ7prKL1xLb1yL7xyLrxyLrlwLLVsKLVrJ7ZtKbZsKLVrJrZtJ7BoIrFoJLZsKbdqK7ptLrhrK7doJ7ZnJrVmJLRmIrFlIK5jHrFmIrVrJ7RrJrNoJLZrJrVpJbdrJrVoI7RnIrJkIbFjIK5gHrJkIrZoJ7VnJ7FhI69fIbBiJK5iI65kJK9kJbFlJbNnKLRoKbZqK7RoKbFkJaxfIKtdHq1hIrFnJrVtKrZsKbdqKLNlIrVkJLdnJrdoJ7ZpJrJlIbFjIbFkIbFkIrZpJwgB3ich4v///////////xgR4Dcx5PDv/f///////////2Vh6ggB3ggB3ggB3ggB3ggB3ggB3ggB3mVh6v////////////Dv/Tcx5AgB3ggB3mVh6v///////////ych4rtxOAC0ZyKyZB+sXxqnXBekWxWkXBWjWRKqXRawYh2vYB6uXyCxYyKzZSKwZCCyZyK0aSS2aye2bCmzaieyaCWzaSWzaCS1aia4biq1bSi0aya0bCazayWyaSO2aia4bSq2aCi1Zie3aCi5aSi1ZSS0ZSO0ZiKvYh2qXxqwZSCwZyGyaSO0aSSyZyOwYyCsXRuoWheoXBanWhSrXRmxZCCzZSKzZSOwYiCwYSGzZSW2aCi4ayy4bi6/dTW8cjK4by+4bi61ayu4bi68bzC6bS64ay27bzK+dDa8czS6cTG8cDC6bCy6ai28bS+7bjC3ayuzaCazZyW2aiq3ayu7by8IAd5lYer///////+yr/UIAd4IAd43MeTw7/3///////////+in/MIAd4IAd4IAd4IAd4IAd5GQeb////////////w7/03MeQIAd4IAd4IAd6yr/X////////g3/sIAd62bDQAsWQfrF8Zp1wUqF0WrWQcrWYcrmUctGYes2QesGEer2AesWMhsmYisGQgrmMesGcjsmglr2UjsGYksWYksWYir2Qgsmcjs2gksWYhsGgisWkjsGcgsGYesWQfrF4brV0csmIirFwdq1sarl4drF4bqFkWqVsXrF4asGQfsWgismkksGUgr2QgrmAfq1wcrl4ermEcsGMetWgktmgkt2kmtWcktWcltWcluGoouWwqtmoqtmwsu3Iyt28vtGwss2oqtWwtu3AxvXI0wHQ2v3M2vXE2vHM3u3M2u3I0vnI1vXAzvm80vW4zvG81u28zvHEyvHEzvHEzu3Azv3Q3CAHeg4Hv////////g4HvCAHeCAHeCAHeNzHk8O/9////////////op/zCAHeCAHeCAHeNzHk8O/9////////////ZWHqCAHeCAHeCAHeCAHeVlHo////8O/9RkHmCAHermUqALxuKrVoI7ZpIrVpIbBmHbBoHrNrILVqH7JlHbNmIbVnJLVnJLVoJLJmIbRnIrJmIq5hH6tgHq9kIrFlI69kIa1fHLBiH7FlIa9kH65jHq5mILFmH65hGqlbFqVXFKtaGbBfH6xcHa1eHK1fHa9hHrBhHrRkIrZnJLptKbpvKrVqJbVpJbhsKrpsLbxrL75tMLlqKLpsKb9wLrlqKLhqKLlrKblrKrprLLpsLLpsLLhrLLdsLbVsLLZuLrlxMbpxMrhuMLlwMrxxM7htL7NoKrVrLblxM7pzNbt0Nb1zNrxwNb5xN7xwOL1yOsB1PMJ3Pr90O791O750Or91OwgB3qKf8////////0ZB5ggB3ggB3ggB3ggB3hgR4NHP+f///////////6Kf8wgB3ich4vDv/f///////////2Vh6ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3ggB3rBmKAC4aie3aCW2aCO1aCO2ayO4bya1byK3cCK1bSK0aiO3aye2aSWwYx+vYRyuYButXRqrWxqqXhyqXx2pXRuqXRqrXRqtXxysXxurYBusYRyqYRuoXRauYBmuXxqvXxy1YyK0YiKyYSKzYyKyZCK2aSa3aSa8aim9biy3aSWvYh61aia4bSu4ayy6ay63ZSy7aS+9bi+9bi+5aSq4aSm5ayu8bC68bC67bC69bjDCczXAczS7cDC6cTG6cjK6cTK6cjO4bzG7cjS8cjS/dDbDeTvCeTq/dzjAezvBfDzBeTrAdTm+czm7cTi5cDe5bzi7cTq7cDq/dT6/dkC9dD0IAd7Bv/f///////9GQeYIAd4IAd4IAd4IAd4IAd4YEeDRz/n///////////+in/PRz/n///////////+in/MIAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd6oXRoAumsrtmkmtWgkt2smunAqtm4ntG0jtG0is2wjsmgitWoltGgjr2IdrmAbrF4asWEer14cqlwapVgWoVMRo1UTo1USp1kWp1oXqF0Yq2AbqWAbql0YqlsWr18btWQgtWQitWQjtmUltmYltGUjumsqumsquWkquGkouWspu24rvXIvwHQzvG8wu20xv283v282vGwwuGgrumotu2wvu2wvvW0x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YiavYievYyiwYyiwZCm2aS64ai+zZSutYCetXyauYiiwZCmwZiquZCitYiatYyesYSUIAd4IAd6yr/X///////+Tj/EIAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd6in/P////////////Rz/kYEeAIAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd4IAd6+cz8AuW8qtmwpuG0su28xvHI1vXQ5vXI3vW80u2swvW0xvGwvvG0vvG0vu2suu2svuWkuuWkuumswvnA1vnE1um0vum0vvnEzv3I0vHEyvHIyvHIyvHM1uXA0uG8yunEzu3MzvnY2v3U1v3U1vnQ0u3Exu3ExvnEzu3MzunQ0vXk5u3g3vHg5v3k7wXc8v3E4vHAzt28stm8rtWwptGkpsWYosGUnrGElsWUqt2wwum4zu20yumwxtGYrtWcsuWwwuWswtmgtsmQpsmUnsGMlsGImsGInr2Emr2EmrmAlrmAlqFofp1ker2EmtGYruGsutGgqr2IksGQms2cpr2MlCAHeCAHeVlHo////////////JyHiCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeop/z////////////8O/9NzHkCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHesWUwAA==]]
FILE: [[images/processing/rotation/test-bitmaps/PastedImage90.bmp]] base64[[Qk06qgAAAAAAADYAAAAoAAAAfAAAAHUAAAABABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq2Asp1wnpFgkmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4Ao1ognFMZpFshrWQqolkfm1EYmk8Xm1AYoVchqF4orGQupl8pp2AqpFwlolkhplwjnlIaolYcm1IVmlETolcbrWEmr2IppVgfqVwjuW0zrWMpqV8knlYZqmMlvXU5uXA2tm0ztWsytmsyvnM5vXA1uWsws2YrsGQpsWUqqmEjo1oeqV8ksGUsolcgnE8bsmUzsGQvrGEnoVQbn08YpVYgsWQumE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AuWwzu241tWkvuGsxu280uGwvum4wt2osu24wwXY5v3Y5v3Y7u3E4tmw0rmUqsGYoqF0au3Ewv3Y7wng/sGYws2k0vnM/sWUwq2ItqF0opVokmE4AmE4AmE4AmE4A////////////////////////////////////mE4AmE4Ao1kfm1IYo1ogqF8lp14koVcfmlEZl08XpFkkp1wnqWArqWArqWErp18ppVwkplsjnlIaoVYdnFMWnVIWoVUapFcdrF8mqFsiplkgtmoxsGYsrmUqpV0gqmIlunI3tmw0tGozuW03tWoyvHI4vnI3uW0wsmYqsGQptmovq2Ilo1seo1ofsGYspFojnlQfrmIvq2Arql8np1oipFUdo1UeqV4mmE4AmE4AmE4AmE4A////////////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////////////mE4A////mE4AmE4AmE4At2oxuWwzt2oxuWwyCAHeCAHeCAHeCAHeCAHeCAHeJyHiRkHmJyHiCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHesWkxqmIqpFsimE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AoVcdm1IYn1YcpFwipl4kolohm1MblUwWolcjp1woqV8rqmErqmErqWAqqmEpo1ggoFUdolcdn1UYn1QYolYbnFAVp1ohqVwjpVgfsmcus2kwsWgupl4iqmEmunE3tWoztms1vXE8tWkzv3Q7vnM4t2wwsGQpsmYrtWousWgspV0hoVkerGQqpVskoVcirWItql8pql8nqVwkpVYep1khploimE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AuWwzu241t2oxuGsyCAHeCAHeCAHeCAHeNzHkwb/3////////////4N/7RkHmCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHerWcsq2Uqo10hmE4AmE4AmE4AmE4A////////////////////mE4AmE4AmE4AmE4AmE4AmE4AolgemlEXnVQapFwipF0kpV0ln1chnFMdnVMeplsnq2Erq2Eqq2EqrGIrrWMrnlMbm08YolceoVYcoFUao1gdnFAWpFogp10moFgjoFomo18rrGUvpl0kpVshuG40tWoytWkzvHA7uG02v3U8vHM4tGsvr2QptmovtWour2YqrmUqqGEmrGQqqmAopFojsGYvrWMrrGEoql0lplcfplggplohmE4AmE4AmE4AmE4AmE4A////mE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4Au240vnE4vG82tmowCAHeCAHeCAHeNzHk8O/9////////////////////8O/9CAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeqmQor2ktpmAkmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AoVgemlEXmE8VoVgeoVohpFwlolokn1Ygm1Ebo1kjrGIqqmEpqmEpq2IqrWMsmlEdkkoYk00akkwZjkwZjUsah0gXhUkbgkkfd0QdbT8ackIeklYpp18qolcfs2gwuG01s2gwuW42u3E4wHY8vHM5t20zrmMpum00smYtq2EnsGctqWInqmMoqWAmqmAmsWctsmgur2Qqq14lplceplgfqmAmmE4AmE4AmE4AmE4A////mE4AmE4A////mE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AvG82u241u241t2sxCAHeCAHeCAHe4N/7////////////////////////////CAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeqmQpr2ktqmQpmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4An1Ycm1IYl04UoFcepFsjo1sko1oloVkjn1UdolgfqmIqmlUgk1MhklMjjlImeUEZbDcTZDUSXDAQVi4QTysQRycORSYPOzUoMENAJ1FYI2FwLXmMhmtNo1cirWEqvG83tWkwtWwwuXA1vXM4vHM5uG83qmAnum41rmQqpl0jsmkuqmMnpl4irGIlrWMmr2QnsWUqr2IprWAnq1wjp1kgqF4kmE4AmE4AmE4AmE4A////mE4AmE4A////mE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////////////////mE4AmE4AmE4At20ztGgwtWoxum40CAHeCAHeJyHi////////////op/zCAHeZWHqsq/1VlHoCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeqmMpsGkvrGYsmE4AmE4AmE4AmE4A////////////////////mE4AmE4AmE4AmE4AmE4AmE4AnlYcm1IYmlAXoFYepFoiplwmpVsno1kjoVcfnVQanVkjc0AXVzETTS0USSsVOyoaLD48J0VHGlprE2qEDHqcFJC3N7PZSLncdszmidLpu+Xyj9LpRnd8oFgmql4mvHA1uGwvtWwtu3I1vnU6vXQ7u3I6q2EouGwzsmgup14ksWktq2Mnn1gZrmUmrWIkrmEis2YpsmQqrF0jqFkfqVsiql8mmE4AmE4AmE4AmE4A////mE4AmE4A////mE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AunA2tGkxs2kwu3E2CAHeCAHeRkHm////////////RkHmCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeqGAnrWUsr2gvmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AoVkenVMamE4Vn1Uep10np1wooVYko1kkplwjnFMajlAeVzIWG1xtCYCoG6bZG6bZRb/mSL/meNnyfdnysvL/uPL/vfL/w/L/yvL/z/L/3vX/gMzmMGl2emNHqV8nuW4ztWsttWsrvXM1vnY6uXI4uXI5qmIouW82tm00rWMqsmkuqWAkoFcaq2MltWstrmMls2Yqs2UrrV8lqVwhrV8lrmIomE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////////mE4AmE4AmE4AmE4AmE4AmE4AunA1smgusmguvnM4CAHeCAHeCAHe////////////0c/5GBHgCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeplwksGgvs2wzmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AoVcenlMbmU8Yn1Ufql8sqV8tmlEgoFcjqmAom1Ibf0UZSSsUBom0c9j/ddr/d9z/ed7/fOH/fuP/gOX/gub/ieb/kOb/leb/neb/o+b/wOz/cMXiVcXiTrjcqWEpsmkusWgrsWgqwHg5vXY5tHA0t3Q4sW0yunM6tWwzrWMrtmsxrGAmo1gep14js2ovsGcss2kwsGQtrmIprGAlrWAkrmAlmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AuXEzs2susWYrvnI3CAHeCAHeCAHeop/z////////////0c/5NzHkCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHep10lrmYusWsymE4AmE4AmE4AmE4A////////////////////////mE4AmE4AmE4AmE4AmE4An1QdnlMcnFIanVMcpl0np14qm1MenVQfqV8nmVIdcj4WOTUqIKvZfuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///4f//9P//QLLZtv7/Xb7frWUtsGcsr2YorGMlvXU3vXY4tnE1t3Q3tHE1tXA2smswq2IotWkvsGMqpFcerGAnsmgurWQqsmgvrmIqsWQrrGAkq18hq10gmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4At3Aytm4ytGovuW0yCAHeCAHeCAHeGBHg0c/5////////////8O/9NzHkCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeNzHkrWMrrmUttG00mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AnFIdoVchnlQdnlQcqmEoqWAonlYdl00WqV4pmFMjZDcXKUhMP73mfuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///4f//+P7/GqbSxv3/XKe8sGcur2UqrmQnplwetGstvHQ2uHI0tG4yt3I1uHM1smstrWQnsGQqtWgtpVgermIotmowq2EntWsyq2Anr2Moql8hql4gq14hmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4Atm4ytm0yv3M5uGwxCAHeCAHeCAHeCAHeGBHgwb/3////////////8O/9ZWHqCAHeCAHeCAHeCAHeCAHeCAHeCAHeGBHg8O/9rGIqrGMruG83mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4Amk8bnFIcn1Ueo1ggqmAnqmAnnFQamk8YpFkkkE4hVS8VGGN6Xc7yfuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///4f//+P7/J7PZ1/z/SZirr2YssWYrsmcpql8huG4wvnY4vHU2smwvuHI0vHY2smsrr2Ynr2QntmktqFoeplofvG81rWEouW40rWIprGAkqF4eq18fr2IjmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4A////////////////////////mE4AmE4AmE4AmE4AmE4AvnU7t20zvHE2tmkuCAHeCAHeCAHeCAHeCAHeCAHeop/z////////////////ZWHqCAHeCAHeCAHeCAHeCAHeGBHg0c/5////qWApqmMrsWoxmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AnFIbm1EZoVYeplskql8npVskoVchn1Qfn1QhhkgeSSoUCYGoe+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///4f//vOXyOr/f3Pz/U358rWMosmYrtWosrGEjtWstwHg5vXU2tm8wvnc3u3Q0rmcnrmYms2krtmstql0gploft2swr2MouW40s2kuq2AipVsaplsZrGAfmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AvXQ6t20zuGwytmouCAHeCAHeCAHeCAHeCAHeCAHeCAHeg4Hv////////////////op/zCAHeCAHeCAHeGBHg0c/5////////o10np2IstG42mE4AmE4AmE4AmE4AmE4A////////////////////////////mE4AmE4AmE4AnlUcnFMZn1UcpVojp1smpVolpFkmolcjm1Mid0AaQCQRGKbWe+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///4///rN7vTszmxOj1XHhurWMosWUqs2grsWYotGosvnU3vXQ2u3Q1v3k5unMypl8frWUluG0vtmstrWEkrGAksmYrrGAltmowsmgtql8hpFkYplsZsGMimE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4Au3E3uW80tWktuWswCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeZWHq////////////////op/zCAHeGBHg0c/5////////////oF0ppGArs3A5mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4An1cbnVQZm1IZo1kipVololcjpFoopVspl1EkZTYWKz8+Nbfie+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///5v//fszmfuXyteLye2tMrGMnr2UosWgqtWwuuG8xvXQ2vnU3vXY3wXo6v3g4rGUlr2got28ws2krrmMlrmIlrWEmrGAlsmcstGovqV4gpFoZp1sZr2MimE4AmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AunE2uW80smcqum0wCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeRkHm8O/9////////////0c/50c/5////////////op/zqGc1qmg1tHI8mE4AmE4AmE4AmE4A////////////////////mE4AmE4AmE4AmE4AmE4AmE4An1ccnVUanFMZoVgfo1kjoVcipFwop14rkVAiVC0TGlttUsfve+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///6/7/X7/fker1iNDpkmU3qmEksWgqsWgqtW4vuXEzuXEzvXU2v3g4wXo6v3g4tm8vsGkpt28ws2osrGIkrmQmrGIkqFwgtGgutGovqmAiplwbploZrmIhmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4A////////mE4AmE4AmE4Atm0wuG4xr2Qnum0vCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeNzHk8O/9////////////////////////op/zCAHernA/qmo3tnVAmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AnVMaoFcdn1YcnVUaoVceoFkgoVsipV0oiUwhSCgSDHmbaNP5e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//0///7P7/QLLZvfz/esrmqmIkq2Ikr2cpr2cpuHEytW4vrmcouHExvHU1vXc4wHo8u3Q2rWYntm8wt3AxrWQmrWQmr2UnqF0ftGkts2kuqV4hoVcWp1saq14fmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4A////////mE4AmE4AmE4AunEzt24vrGAitmkrCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeJyHi0c/5////////////////op/zCAHeCAHevYFQtHdFvH1JmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmU8Yplwjo1ofnlUaolkepF0io1winloke0QdQSUQD6HSdtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//xf//1f//8/3/JKzWw/z/WKW6rWYsqmEkrGMlrmYounM0t3Awq2Qks2sruXEwvnY3v3g8vXY5q2QltW4vu3Q1rWQmrmUnqmEjq2Ejt20xt24wrmMlolcYolYXqVwdmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4Au3ExvXQ0r2UlsmYnCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeop/z////////////op/zCAHeCAHeCAHezJBhw4ZWuXlImE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmlEdpFwloFgeoFcdoVgepVojp1wnnFYlbT0ZMDk0LLHfdtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//x///7fz/fMvmOr/f1/v/VpmrlFYnpVwkrmQosmkruHEwt3EuqWMeq2MfunAswHY3wHk6unM1rGMls2osvHM1r2Yps2gtq18kq18ktm0wt28wsGgpoVYYoFMUqFoamE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AuG4uv3U0tmwrr2UlCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeop/z////////////0c/5CAHeCAHeCAHeCAHeyY1gyItcvH1NmE4AmE4AmE4AmE4A////////////////////////////////////mE4AmE4AmVAcnlYfmVEXnVQaolggplslqF0pl1MlXDIVH1ViSMDsdtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//4Pz/a8TiMLncj/n80vv/l9bsQW93hFInrWMmtWwst3Euv3k2pmAdpVwZum8swHc2vnU3u3I0smkrtGstuXAyr2Yos2ksqF4hqWAiunEyuHAvtmwtplkboFETo1QTmE4AmE4AmE4AmE4A////////////////////////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AuW4vvHIzt2wusmcpCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeop/z////////////0c/5GBHgCAHeCAHeCAHeCAHew4da0ZRm1JRlmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AnVQfolojnVUcmE8Xo1ojqF0orGIuj08kUCwUD3ORXcv1dtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//uv//6/r/HavWlvz/mf//nv//1/z/yer1SJ21oGYxtGwstW4tvHc1q2Uin1cUu3Auw3k4vXM0unAxsGgpsmoruHAxrmUmrmUmq2MkpV0etm0su3Euum0sr18holESolIQmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4Aum0xvnI2vHA1tGgsCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeop/z////////////0c/5GBHgCAHeCAHeCAHeCAHeCAHet3tPzpFj25tsmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmlIdnlcgoFkgm1MdoVkkrGItpl4tg0giRScSDY23ctf/dtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//vP//s+LyOLzflvz/mf//mf//mf//yf7/v+byf3FRtGwssW0suXUzq2YjnFMRum4tyH09v3Q0uW8vr2cnsmoqunIyrmYmr2cmrGQjq2MhsmglvXAtvGwrt2QmqVYWpFIQmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AvW40uGsyvnE4smUrCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeZWHq////////////0c/5GBHgCAHeCAHeCAHeCAHeCAHeCAHeuHxQ0JJk3JxumE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AnFMgnVUfoFgioFgio1omqmEtnVgocz8dNDAmJKzcctf/dtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//xf7/ldXsScjmlvz/mf//mf//mf//sf//n9nshHRUt3Axs20tvXk4sWsroFYWsWUmx3o7vXEyu3ExsGYmtW0twno6rmYlrGUirWYirWYhsmgkuWwpvm8uuWgpr10dolAPmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4Au2wyt2oxvXA4t2owCAHeCAHeCAHeCAHeCAHeCAHeCAHeZWHq////////////0c/5GBHgCAHeCAHeCAHeCAHeCAHeCAHeCAHevoFVz5Bj15VnmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AnlUhnFMenVQgnlUholklpl4ql1UnYTYYIkxUOLbmctf/dtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//y/3/eMnmbd/ylvz/mf//mf//mf//yv7/gczmmGw9tm4vtm4vvXY3tW0upVsbs2YnyHo7vXEyvXMzsWcntW0txHw7r2glrmYirWUgrWUesWcht2snu20rt2gpsWEhoFEPmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////////mE4AmE4AmE4AmE4AmE4AmE4AuWoxtmkxvG82tmkwCAHeCAHeCAHeCAHeCAHeCAHeZWHq////////////8O/9GBHgCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHevoFW05Rm15VnmE4AmE4A////////mE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4An1cklU4bmFAdnlUioVgkpVwokVIkUy8UE2mDU8Xyctf/dtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//0fz/PLHZf+r5lvz/mf//mf//mf//yv7/ccbirGMmr2YptGwvv3g6uHAxqFwduGkqyHo6v3Qywng2r2Yms2srv3c2s2sqsmklqWAarWQcsmcgtmwouG0rtWcotGcmpFcVmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4A////mE4A////mE4AmE4AmE4AmE4AmE4Aum0zt2swuGwxtWkuCAHeCAHeCAHeCAHeCAHeZWHq////////////8O/9NzHkCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHevoBXzo9j1pRlmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AoFoolU4clU0coFcko1klo1kmiE0iRygRCICnbdL/ctf/dtv/e+D/fuP/g+n/huz/i/H/j/X/lPr/mP7/nv//rP//4fr/J6rWj/X/lvz/mf//mf//mf//4f3/SrDPr2Uqq2ElrmUpwHg7unIzrWEhuGoqyHw6v3UyvXQzsGgos2ssvnY3tW0ssmglqV4ZrWAbtGgjtGomuG4stmkqsWUkploYmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4A////mE4A////mE4AmE4AmE4AmE4AmE4AtGotsWcptmwutmwtCAHeCAHeCAHeCAHeZWHq////////////8O/9NzHkCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeuntSxoZby4lZmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4An1opmFEhlEwboFYkoVYinVYigkkeRzEbIKjZf9n/g9z/leP/nuf/our/p+3/vPD/wfL/xfT/u/D8p9/yq+DyreDydsnmNLnfj/X/lvz/mf//mf//pP//7P3/W6CvsWUqrGAlq2ImvHI1unAxtmkptWYkw3c0v3czu3QytW0tsGkqvHQ1uXAwsWUkrWAdtmgkuWwntmwptWoosGMkr2MipFgWmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4A////mE4A////mE4AmE4AmE4AmE4AmE4As2sqsGknuXIwuHEvCAHeCAHeCAHeNzHk////////////8O/9NzHkCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeJyHivoBXw4RXyIdXmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AoFsqm1Qjl08en1Ujn1QgnVQgkk8fT1pNLq7ZXMPmU77iMa7ZMq/ZM6/ZJ6rWCp3PKKrZKqvZLKzZOLHcXsHmYcHmaMfpj+f8ofT/qPr/rP3/zPv/4/T8Xr7fWoJ+tmgvrWAnr2Yqtm0wuW4wu2wtsmMivnIwvXYyvHUzuXExs2wtu3IzvHIzsWUkrV8cuWomvnAsuGwqs2YnsGIjtGUkqVsZmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4Ar2gnsmsovHQwuXEvCAHeCAHeNzHk8O/9////////////op/zGBHgCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeJyHik4/x////x4lgyIpdx4dXmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AoFwomFQfl1Edn1gjoFgjoFgjolslg1kwXWteTXh3THh4THl5Snh6JYiiJ4mkSpiuTZmwQ565LKzZRLXfXsHmYcHmZcPmaMTmoNvypt3yqt7ydsnmUY2UnG1CtGcutmsxq2Insmkstmwvs2gqvXAxt2oruW8vwHc3wnk5vHQ0unAvvXIwum0stWclqFoYtGYkwHMxuGsrt2oruGwrsWYkqV4cmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AtGkrsGUmuG0vu24wCAHeCAHeNzHk4N/7////////////////////sq/1g4HvRkHmRkHmRkHmVlHog4Hv0c/5////////////xIZdxYZcxIVYmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AnVkklFAblVAbolwnolwmoFkhpV0lnFIZm1EZo1kjn1YipV8qp2Eto10rqGMvpl8qp14qp10npFsiolofo1sgqGEnjWI4cmJIeGhPfGxQdGVFmGw8tWkusmYstGkvuXA0sGcpsmkrsGYnrmQks2gnum8uu3IzvnY3wno6vnQ0v3MyvnEut2kmtmglrV8dtGYkwHIxtmkqsmYntmwrsGclqGAdmE4AmE4AmE4AmE4A////////////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AtmovsmQps2UqvG4zCAHeCAHeCAHeGBHgg4Hv8O/9////////////////////////////////////////////////////////yYthxodfvn9UmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AnVkkmVUgllEcoVsmoFojpF0kqWIpm1EZmU4XoVYgnVQgp2ArqmMvolsoqmIup14qo1gkpVslqF8mp18kpV0hqGAlqV8mpVoipVoiqF4loVgbrGMls2gts2gttmwxunE0sGcpsmkrt20urmMisWUjuGwqvXQ0w3s8wno6vnQ0v3Qyv3IwumwqsmQisWMhuGkouWwttWossWcnsmgpr2clqWEfmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4At2ovs2UquGovvW80CAHeCAHeCAHeCAHeCAHeGBHgdXHs4N/7////////////////////////////////////////sq/1VlHozY1ky4xkxYdcmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4An1smnlgjmVMdolslo1wjo10iqGInnVUcmk8ZnVMdn1Uhp18rrmgzpl8rpl0pplwon1QgolciqF4nq2IpqGEmp18jp18jqV8lpVoiqV4lp10iqWAisGcrsGcrtWwvu3I0tW0tt28uuXAvsGYkrWIetGckunEvxHw8v3Y2v3Y0vnIwum4suGspsWMhsGIgtmgoum4vs2gqtWossmkqpl4drWUjmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////////////mE4AmE4AmE4AmE4AmE4AtGYrtGcruGsvumwxCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeJyHiZWHqg4Hvop/zwb/3wb/3g4Hvg4HvRkHmCAHeCAHeCAHezIxh0JFnxohemE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4Ao10nn1kjmVIdolskpF4kolwhpmAlo1sinlQen1UfoVgjqWEssGg0qF8roVgkpFklo1gjoFYgp14prGQsqmMpp2Akp18hpV0hpFkgp1siqV0kqV8jsmkrrWYnsmssuHExr2gouHAuuXEutWworWIesmUhunAuwno5vHUyunAuv3UzvnMxum4ssWQisGIgtGYmvnEzs2ostWwusWgpnlYWqmIhmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AtmovtWktt2suu28yCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHeCAHexIVV1pdpxYlamE4AmE4AmE4A////////////////////////////mE4A////mE4AmE4AmE4ApF8pn1gim1Mdn1cholsio1wipV8kpFwjoVchn1Uhn1YiqmEtq2Iupl0pn1YioFYiqF0oolgiqGArr2cwrmgtqWMmpV4gpFsfpVkgplkgq14krmInrmQnqWIjsGkquXIyq2Ujtm8tvXQxuW4ssGUhs2gkvXQxwns5u3Qzs2sqwXg3xXs6vXIwtGcltWcltmgmuW0tsmgqtm0vtW0uoVkZq2MjmE4AmE4AmE4AmE4AmE4A////////////////////////////mE4AmE4AmE4AmE4AmE4A////////////////////////mE4A////mE4AmE4AmE4AuGwxs2gruG0vvHEzsWYor2UosmcsuGsvsmUnq10erV8esmQitmknu28vv3Q3v3U7vXQ9unA6tGgvr2QrrWQpo1oerGElr2MluXhH1JVky45dmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AqWMto1wmmVEbn1YgoVghpV4mpF0loVkin1UgnFMfn1YiqmEtpFsnpl0poFcjnFIdqF4op10nqGAsrmYwsWowqmMopl0io1keqFwjq14lql0kr2MnrmYmrWYmrWUlunQzsGoorWYluHAuvnQytmsptGonvnY0x4A/vHQ0uHAwvXQ0wXc3t20ss2clt2knt2ootmsqsGgosWkquXAwpFsbq2IhmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AtWous2krtGssunEysmgqrWQmsWcrtmots2YoqVwcsWMir2EfsWQit2sru3AzvnQ6v3ZAvXM9uW00sWYssGYsqWAlrWMns2cps3I9yopY05VjmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AqGIsqGAqnlUfoVchoVcio1olpF0ooVolm1IemlEdoFcjq2Iuo1omp14qolgknFEcplwmqV8qqmEtp18oq2QqqWEnp10kpVoiqV0lrGAopFgermMlsGcoq2MjqWEht28vrGUlpl8fs2srvnU2t20urmQmu3IzxXw9vnY2tm4vunIyxHs8u3EwtWkntWckuWwpt2wpsGcns2oquG4urGIhq2EfmE4AmE4AmE4AmE4A////////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AsmossWkptW0tunIytWwss2gqsGUpsmUpr2Ijq14euGootGYjsWQhtmoqvHEzv3U7v3U+v3RAvnI7sWcvp10ksGcsrWImsGQmpmQvv35M05RimE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AqmMsqmAsp1won1QgoVcjolklqGEso1wnnVQgmlEdoVgkq2IvpFsoo1gkqV4qpVolpVskqmAoqGApqGEpqF8mplwkp1wmqV0op1wmrWIpolcbrGIhs2knrGMiqWAgtW0trmcomFETsWksvnY5v3Y7sGcstGsuxn0/vXU2uG8xuG8xwno7vHMytGkms2Uhum0pt2wps2oqtm0rt20rrWMhrGIgmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4As2osrmYnsmoquXAwuW8vtGkrrGEjsWUnrmEjr2IitmgmtmglsWMhs2clvHEzv3Q7u3A6v3M/v3M+s2gxpVsjsmkurmQor2Iko2Ert3VDwoFRv4BQsXJCwYJS15xw36mD5LGQ876b1ptyq2k4pV4oqWAon1cgnVogp2YrqmYtqWIsrGIuq18toVUjoFQjo1onqGEtpl8roVolm1Ieo1omqF8so1kmnFEdp1worWMtpVskq2EpqF4nq2EpqmEopFojqF0oql4pp1wmrmMqnlUWo1wYs2knqmAgplwcqWEht3AxolodunI2uXA2vnQ7r2YsrWQox35AvHM1vHM1t24wvnY3vHQzsWgktGgjvG8pt2wotmwruG4st2wprGEer2QimE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4As2wtq2MjrmYluXEvuW8vtmwtrGEjrmMlrGEiq14er2IfsWQgsmUhs2gmvHEywnc+u3E6vnM/wndCtmw1qF4mrmQrsGYqtGgqrGgzsm88tnNCtHJDuXdIwX1Q1JVq05xz4K6I9MGb3qR9snJHoFsqrGQwoVkhm1UbpmEnqWQsoVomqF8tqV8volgnoFYjoFciqF4oqmEqpVsln1Ufp1wmpFolnlUfm1Mem1QfrGQuo1okq18pqlwoqV0mql8no1khp10nrGEsp1wmqWAmnFMVoFcWtGsqqF8go1oboVkbvnY5rWQpvnU6u3M3unI3qWEmp2Ajw3o8vnY3u3M0t24uvXQzwHY1r2UjsGYju28st20qt20ru3EvuGsqr2Igr2IgmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AtW0uqGAgrGQiu3IwvXIzvG8wsWQmrWAjrWEjqFsbq10brF4btmkmt2sru28zwHU8uW84tm04wXdDtmw3plwlqV8msGQpuGsurGcytG89r2o5sW08xYFRyoVXy4teyZFk26h+6baN4aiCwYFbol4ypmAsoVsinFQao1oiqmMso10pqGIwq2QznlcloFcjoFYgpFkhql8nplwkpVoipVkin1QdnVQdpV8on1wlqWQtpFslp1omqVomqFolqFwlolgfplwkr2UtrGIqpl0knlUXoVgYsWgpqmEjo1ocpVwgv3U6r2UruXA0vnY5vHc5qmYnolwdwno7vnY2vnc2tWwqtWsovnQyrmQiqmAeuW8tt20suG8tvHIxvXExsGIjr2AhmE4AmE4AmE4AmE4A////////////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////mE4AmE4AmE4AmE4AmE4Atm0uqWEhpl0dtWsqunAwum0usmMmsGEltWcqq10drV4bp1kWt2gnu24wvG81vXI6uXA3tGw0vnVBuG45pFoiqFwkrmIotGYrqWMutW87qmUyp2IwxYBNzolZvn1OwIZXz5tt3ql+5q2EzI1lqWU5oVsooVoioVkgo1kirGMtpl8qpF4qq2QxoFkmoVgkolgioFYfolggplwkqV4nolYgoFUgnlYgqGMsqGUuq2Yvp14qqV0pp1ckplgjqF0lolgeqV8nsmgwqmAop14joVgaoFYXrGMkrWQmpVwfp14ivHM3tm0xtWwvunM0v3g5r2oop2Agv3c3vHU0vnc0smknsWgkwXg0sWckp10bsGYktm0sunExum8wwHQ1sGIlr18jmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4At28vr2cnpV0drmUltWoruGwttWYptGQnt2cprV0dqlsZqFgVt2cmvG0vvW4zvHA4u3E4t242wnlCunA6pVojrGAorV8mr2EmqmMtuXM9q2UwnlgjsGo1xYBNtHFAtXlHvodW2qV37bSJ0pNpr2w/oVsoolojpVsjo1gjqF4oo1sloFkjqGItpF0ppFsnpFomo1gjolgjpFwkqF4nnVMdoFchoFgipmMsp2Qvp2Espl8qpVklqVklplghqF4knFMZpV0jsmsyqWAopl0ipl0folgYrmYmtm8wrGQmrWQmuXAyuXAztWwuunMzunM0r2onrWUlv3c3vHQ0vHUysmomsGcjwXg0s2omqF4cplwatWwqvHM1vHEzv3I0s2YprmEkmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AtWwutW0tqWEhrmUlt20tuG4utmkqt2gqtmYnsF8dq1oXrVwZtWQkumotvm80vnE3vnM5uW81vnQ8uG02p1wkrmEorWAnp1keq2Qru3Q8sWoypF0lolsjt3I8tHI8tXZBs3lE1Zxr67GCz5BjtHBCpV8so1slpl0mplslpVwlpV4lo1sjpl8npF0moVgjn1YiolckplwopV8oqmEroFchmVEboFolp2QuqWYxol0oqmMvolcjolUgoVYdpVwioVgepl8ks2wyrGMrpVwhp18go1oZq2MkunM0tGwtsGcptGssuHAxt28uuHEvtW4rs20psGgnvXY1vnc0unMwsWglr2YivnUxvnUxrmQhoFcUsGclvXQ0vHMzvHExtGkqrmMkmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AsmoruHAxrGQlrWUltW0tuW8vtGoqtmgptmYnsWEfqVoXrFwZs2UiumwsvXAzvHA1wHU5u3I2unA2uG40rWEorV8ms2UrqFofpl4ktGwytm41pl8lnlgermgwtnI6t3c/sXM9yI1Z2p1tuXpMsG0+rWc1oVkjolkjpFokolojqGEoo1wioVshpl8nnlYgnlUhpVooolomo10nrWUvp14pkUoWnlgkp2MvqmczmlUhoVomoFUhoFQdoVYdpVshp14kpl8ms2wzqmAopFshpl0fpVsaqWEit3AxunIzsmkqs2srtGsrvHQyvHUytW4rtW8rsGonunIxwHg2unIwsGcktGsnvXQwyH87s2kmolgVq2IguHEuu3MwunEusWckrGMhmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4A////////mE4AmE4AmE4AsWost24wrmUnrmYmsWgot24uuG4utWgptWcmtWckp1oVrF8bt2oovHAwvnI1vXM2wXk6v3c5u3E2t20yrWIop1oguGovrmAlpVwisGcts2owpV0ipV8kq2YttnE5tHI5snI8uXtHxIdVpWY3o2EzuXVEo10omlMdoFgiolokp2AoqmQrpF4lqGEpoVkjnFMeoFgkoFgjoFkjqmIsp14qlEwZnVclqmc1qmg1n1omolsmoVcinVIbnFIYpVwjqmEpo1sksGgxq2Ispl0joVgZpVwbrGQltW0vtGwts2oqs2oqqmAevHQxv3g1s2wpt3Aus2sruHAxv3c2unIwtGsotm0pvXQwxHs3tWwpplwaq2Iftm8pvXUvvHQusWkjq2IdmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4A////////mE4AmE4AmE4Asmout24xsmgqsGYosGYmuW8vvHIytWoqsGQksmcjplwXqmAbtmwpunExu3I0u3Q1wXw8wHs7vnY6uG8zrWInpFcctmkurmAlo1sfrmYqs2svo1ogpl0kqGEqtnE5t3I6sm83s3I+1JVjr3FCqGk6vXlJpmAul1EbnFchoFokpmAqqmQuoVslpl8ppFwmm1MdnVYeoFoioFokp18ppl0qmFAemlQirGc2p2Uyp2ItolklpFoloFQdlkwTo1siq2Qro1slqmEtq2Aro1kgpFodqV8fsGYotGstrmUntWsrt20to1kYt28svnc0smoptW4tvHQ1uXEyuXExu3MyuG4st20ru3Evv3UzvnQyp10cq2EetGwlvHQsu3MrsGggpVwWmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4As2ouvHE2smcqrWIks2gquW8vunAvt2wrrmIhsWYjrGMeq2MetW0qvHM0u3M2unM1wHs7vXg4vnY6t24yqV4jplofsGQpr2EmqmMlsWksrmYqpVwiq2IpqGIsr2gzs2w1sGs0snA84KFv0JNkxYZYtXNDpWAvlFAbl1YdnFkiqWQvqGMun1olpF0oo1wlnFYcnlgdoVshpmApqGArq2EunlQjm1MjqmQ0oVwqqGEtpVsno1kko1cglUsTpFwjrWUuq2Iusmk2rWIuolggp10hrmQkr2QmsGUnqmAhsmgouW8vplwcsWgovHQ0r2gps2wtwHg6unEzsmkrwHg4uG4ut20su3Evu3EwwXc3qV8eqF4btmsmu3ErunAqsWchqV4ZmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4A////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4As2ctvHA1tGgsql0htWkrtmssuW8tuGwrsWIjsmYisGQhr2QhsWcmvnQ2vHM3uXEzv3c4u3Q2vHY7uXA2qmEmql8ksGMor2EmqGIjtG4ypF0ipl0jrGQqrGYwq2MusWgzsGo0s3A746Vz7LCAy49gtHNDrmo5mVchl1YemFghqWcyp2MwoVsoolwnoFojnVccnlkcol0iqWIsqWEsrWIwpFkpn1cmrGc2n1kooVooqF8ro1cjpFkimU8XqF8ns2s1qF8rsGc1r2QxqF4np10ismgpsmcor2QmqF4fsmgovnQ0q2EhrWQkvHQ0tm8wtG0wwnk8uW8yr2Yownk6t20ts2kovXMyunAwv3U1tGkqqF4ctGklum8qu3Asr2QgrGEdmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AsmYsuGowuWwxr2EmtGgqtGgptGoouGsrtWYnsGIgs2UjsGMhrWEiu28yvXE2tWstwnk6wHg6vHY6u3M5sWgtrmQpr2MosGInq2UptnA1pF8kpV4ksGcusGcxqmAqsGcxrGYwsG873KFw77iJxIharW0+q2g3ol8ql1YemVghqmcxqGQvnVgjn1kknlgimlQcnFYdoVsjp2Itp2AsqWEupFsqoFkorWg3pF8tnlglqF8spVomo1gjnVMdpVwmt286pFsnqmItrWQvpl0lp18jrmUnsWcprGIkrWMktWwrvXQ0sWgnrGMjuXExvnc3uHAxxn0+vHIzsGYlwHU1vHIwsmgmtmspuG4runAuuW0trmEgtWklvXIuwnczrWIeqF0amE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4As2cttmswum8zs2grtWsssWcorWMktmsstWcnsWUjtGgmsmQkq10euGstv3M2s2gqw3k7w3k9unI5uG83smgvsGUrr2InsGImrmYtr2owoV0jnVkermYss2ctrWEormUssW01snI+y5Fg5at9xopdu3tLp2MyqGMunVghmVUdqGMqrWcvo14loFojnVchnVYinFYim1YipmItpF8sqmQypV8tolwqpV4sqmMxo10po10oolsnolgloVckp14quXA7pl4np2AoqWIpp2AmqmUpqmUprWUnrWQkrGQktm4uvnY0s2wqq2MitW0twXk5vXQ0wHU1vHEwrmMhu3Asw3gzt2wotmsntmsntWomt2ontWgkuGsmwXYxyH05r2QgplsYmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AtGwuuHAyu3Q0s2wstW0tr2YoqmEjsmoqtW0rs2sos2knr2MjrF8gum0uwHQ2uG0vv3Q2v3Y6unA6unA6tGkxsmctrmImsGMlq2MqsGsxpGAlnVgdrGUpsWYsrGAnqF8mt3I7tnVBwoVU26Bwy45fzItbsGw6qWQsoFognVccqGInq2YrpWEmn1ohm1YenlgioVsmm1UgpF4ppmArqmMwrWUzpV0rnFUjqGAuq2Mwpl4qpFonoVUjoFcjsGcztm04qGAqolokp2AoqmMpq2Uqq2YqrWUorWQmqWAis2srvXU1smoqp18fsmoqvnY2v3Y3uG4ut20trGEguGwpxHk1uG0puW4qtmsnsmcjsWUhtGkltmsnvXIuyH06uG0qql4cmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AuG8xt28vunIytW0ttGssrGMlq2EisWgot28st24rtGoqsWUmsWQlvG8wvXI0vHEzvHI0unE2unA5vHI8u3A4sWUrrmInsmUnp2AmrmovpWEloFofqmMnr2Ysp14koFketW82u3hCxIVT2Jtqy41dzo5bsG45pmEopV0jpV0hqWImrGYqp2ImoVwgm1YcmFMbpF4opF0no1slqGAqq2Iur2UzqV4tmU4dpFgnq18tploop1spo1ckolgksmk1sGcyrWUvn1chpV4mq2Qqp2AnrGctr2cssGcqqF8hrGMlunIyuXExo1sbs2srwno6wnk6uG4vtWorr2UltGooxnw4t20puG0puW4qsmcjsGUhs2ckum4suGwqyH06v3Mxr2MjmE4AmE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4A////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4As2kqtGwsu3MzuG8wtmstsGUnrmImsmYntWkntGkntmortWgptGgpuG4uu3AxuXAyu3I0uG80vHI6vHI6v3Q7smUrsmQpsmQppmAlrGgspGAkoVsfpV4hqWQppmIno10isWsxuHI8tHE9t3ZExYRSyopXoV8qp2Aop10jo1ofpVwhrGQpqmMool0im1YclVAYpF4oqmQto1wlqGErrGUwrGMwqF4tnlMho1cmplkop1korWAupVklo1omr2YyrGMvq2MtolokpV4msGkxp2AormgurmUssmkurGMnqWAit28vwXk5o1sbr2cnwHk5wXg6tWstsWYntGoqr2Ukw3k3tm0ptmwouG4qs2cks2cktmooum4ttmkpxns6wXY2r2QkmE4AmE4AmE4AmE4AmE4AmE4A////////////////mE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4Atmwss2oqu3IyuW8wtmstsmUpsWQotWcotGcmsmQktGcotWgptmortWsrtWwtuG4wuG8xsGgrv3Y7v3Q5um40tmkvtmgttmgtoFwgp2QnoFwgo1wfolkcp2UopGMnpWAksmowt283smw4pWEvw4FPxoVSmlgjqmMsp1wkpFkhpVsjqF8mqWEon1kgm1UelE4XoVslq2Yvo18mpF8pqGMtq2UxolwpnVUjolgmplspoFQjr2Mxo1gkolgktWw4rmUxqWEro1slp18ptGw2pFwmrmkwsGcvsWgvsGcsrGMms2orwno6qWEhqmMivnc3xX4/uG4wqV8gunAxr2UkunAvt20rs2omt20qum8tt2spvHAvuGwss2cowHY2wXc3r2UlmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AuG4urmQkunAwu3AxuGsts2QptGUqumostmgor2Ahs2Ums2YntGgpuG4us2oqunEyunIzr2covnU5wXY6um4ytmkuuGouuWswnVodpWIloFwfpF4hn1kbpGMmoGAjoVwgsGgttm00sms1pmIuwoBNzYtXn10npl4pp1woo1gio1kirGIrqmIroFginVUgl1Ecn1gkqGMtol8noF0mpmQtp2UvoF0plVAenFYkq2MwnVMhoFUjpFklolgktWw4sWg0pl0polkkqmIsuG86o1slr2kzsGcxsmgxsmgvrWMnsWcovXMysGclqGEfuHExwHk5tG0to1sbvXU1s2knt24rvXMxrmQiuG4svHIwtGootmwstmstrmQkuW8vxXs7tGoqmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AmE4AunAwq2EgtWsrvXIyumwutGQntGMnt2cpvGwtt2gptmcotGcos2couG8vtGwsuXExunEysWgpuXAyv3Q2um8xuGwuvG8yuWwwn10gomEkoV0hpV8jolsfp2Ypo2IlpWAjsWottGsys202qmYytXJA0o9cpGAspV4qp14qolklolklrmUwrmQwpVwonVQgmVEenlclpF8qoV0lmlghoWAqpGQupGMujUsYlFAeqmUynVcjmE8boVcio1okrmYwtGw2pFsnoFcjq2MutWw4o1smq2Qvs2k0smgwsmgusWYptGopuW8tr2YirGUht3Auvng1uHEuoVoXt28tu3QwtG0pvXUxq2IetWsqwHY2uW8vtWsrs2kpsmgosWcnx309s2oqsWkpsmsouHEvunMxvXUztm4utGwss2srq2MjuXExu3Exql0enU8PplgWu24ttmwsuHAwtGwsuG8xuXAys2otvXM3um8zsWQptWgruG0urWUltm4uuXExqmAfsmgnvXIyu24vtWUosmEktmYou2ssvm8wtWYns2UmsWUlvHIyt28vtm4uunIyr2cnunIyvnY2vHIzuGwuum0vtWcsn10gn18in14ioFofm1QZqWUpp2Qmo10fsWostG0ztG84sGw5qWY1x4NRq2Uzo1wqpl8roVoln1gjrGUvr2gyqGEro1oll08boFgkp2ErpmIqo2EqoWAqn18po2Mtk1MeklAcq2cymlYhmlQeoVkjqF8pr2cxtGw3qmEtolklqmEtsGczq2IuqGAstWo2sWUvsGUrsWUosWYmuW4qsmcjrWUgtW4rvXczvnczp2Ecq2UgxX85t3ErtG0psGgksWkmv3U1vnQ1uG4urmQjtWsqsmoowno4t28trmcltW4rvnc0vXYzvnc1tm4usGgotm4usWkptm0ut28vrWIjmU0NpVgWuWwquG4utm4usGcotGsuuG8zt24ytm0xt20xsWUqtWksuW8yqGAhs2ort28vrmYkr2Yku3Awu24vt2gqsGAit2cot2couWortGcor2Mkr2Qlv3U1u3IytWwsunExqmIit3AwwHg4u3EztmwuuG0vtGYrnV0foGEkn18jo18kmVMZqmQorGYpolwdrGQnsGowrms0rGk2sGw7wHpLsms7oFkmol0noFslm1YfqGMsrGcwolwlpFwlmFAZn1YgqmIsqGIrrGYwol8qnFoloF4pmVgimFYhp2QulVEbmVMdpVwmqWAqr2cxrmYwrmUxo1omq2IusWg0rWUypFwpsGUxsWUvtmgvtmkrsGMitmoltWkkrmQftW4puXIuvHYwr2oipF8Yu3Uut3Eqrmgjt3AssmoouG8vvXI0t24usGcks2oor2ckvnc0vHUyq2QhsGkmwXo3u3QxvXYzunIyq2QkuHAwuHAxuHAytW0trGMjnFEQpFcVt2onvHIxtGwsrWUlsWgrtm4yu3E2tGsvt20ytWkvtGgutmwwpFsetWwuvHQ0sGknsGcluW4tvG8vuWsrsmMjtWUmumorumsssmUmr2QlrmQkuG4utmwst2wtu3Awr2Ymsmwrw3w7u3M0s2kruW4wumwxmlkcoF8ipmQprGgun1gfqmMprWcqpV4hqWMmrWguqWYvrGk2rmo6w3xNq2M0o1wooFsjoV0knlogpmEnqWUqnFccnVYcmlMZn1gerWYuqWEsq2Qwo18qomAqo2EsmlcimlgiomAplVIcm1YgplwoqmAsr2YyqWAsrWQwqWAtqWAttGo4sGc2qGAur2UwsWUutmowuGstsGEgsmQhvG8ssmcir2citm8rtnIstXEqpF8YrmgiunMusGkktm4qtm0quG4tvXQzt3AtsGklsWklq2IeunEtwXk2rmYkrGQjw3w7tW8su3UzunMzqWIitW4uu3Q1uHEyt28xsWgqoFYWplsZsmcjvHMwtm0sq2IkrmQot20zu3E3sWcttGovtmowt2wwtm0xqmMmsWgpvnY1tWwqsmgmum8tvXEvu20rtWYms2Uktmgmv3ExtWgpsGQmrmIjuGsstmoquGsswHM0tWsrtG0tvHU1tWwus2krtWotu20yl1IWn1kfolwjqGIpo1wjqWAmrWQqologrmcts241qGUtqGUvq2g1uXRDqGIypl4qo1wipV8ln1kfpGAmqmUqnFYbnFUanlYboFgcrmcuqmQwqWQvol4poFwmo2Apmlchl1UeoWAqnVsmmVUhql8vq18urWEwpFknrGAvsWg2plwrs2k5smg4rmQzsWk0rmYvrmQrum0zsWImsmQkum0rtGonqGAcsWwnt3QwsGwool0Zq2Qhv3YysmgktGomt20pt20pvnQwu3Itr2ggsWggqmAYtmsmx307tWwtrWYovXg5uHIxu3Q0vXQ2rGUmsGopt3Iys28vuHM1s2stoVgZpl0ar2YhuG4quG0rsGQmsmYrt2oxuW0ysGUps2oss2ottGsvuG8yrWQlrmQkum8tvXAttWglumwpvG4ruGwqsWUlsGYjs2glvnIxuWwusmQnsGIktmgouWwqumwswnM1uGosuG4uv3Y4t24xsmksrWQoum4zm1UanlcdnVcco10ipF4jqGAmrWQqoVkfqWMosWwzp2Msrms0sGw5vHdGrGY2sGg2pV4noVsjoVwkpmEpqGMqnlkfm1QanFYbn1cdqWIpqmUwrGgzpWAqmlUfo14nmVUfm1ginVolo2EsmVQiqV4urGAvq2EvoFYlqF4ss2o4pFsqsWg3tGs6q2MwrmYxrmYurmUstWovs2YpsWMltmkptmspqmIerWcjxH47s2wro1wbpl8cwng2s2kltmsns2gjuG0ov3QvwXcxr2YgsWcfql4XsGQfxXo4vHM1sGkrunM0tW8uvHQ0vXQ2rWUlsWspuXQytXEvvHg4unM0pV0cpFwXsWkiuW8qt20rs2gqtWkut2oxtGgtrmMmt20vtGoss2gstmwvrWQksmcnt2spwXQxu20quGonu20rvXExsGUmrmUjs2smuW8tu24wtWUor18hs2UluGooumwsvW4wvG0wuW4vxXs8vHI2tWwwplwht2wwnFYbnVcbnFYaoFoep2ElrWUqrWUqpV4jpF8kqWUso2Aoq2cxtnE/uHJCs209u3VFpmEunFcjoFwnq2YxqGMtn1okmFEbl08Zpl4np2AqqWQurWgyqmQum1UfolslnlgipmAroV0ppGAto10roVYlqmAurWQyoVgmqWAutGs5pFwpqWEusms3qmMvr2YwsWcwtGoxs2kusWYpsWYmtGkouW4rr2UhrGIfvXU0t28wqGAgpl0cwHY0tWonsWQhs2Yht2wlwHYvwngytGsmsmchrmIcrV8cxnk4v3U2s2wttW4vtW4tt3AtvXQzr2cltG4quXMvs24rvHY0vXc1rWQholkTtGoiunEstmwquW0wuWwytWgvt2swsmYqt2wutmstsmYqsmgqs2oqs2kotWknum0qvnAtu20qumwsum0usGUnqV8etGsnuW8ttmkquGkrsWEjsGEhtWclumssu2wuvW8xvXIzw3g5v3Q3unA0qV4jsWUqnlgcnFYamlUYnlgbqGMmrWYqsmsvpmEloV4jpmQqol8nrGgysm47tG8+vHVGtnFArmo4oFwqnVknqWUzpmIvn1omm1Ufm1IepVsmrGMuqGIsqmQupmAqm1QenFQeolokpmArolwppmEvpV4sm1EfpVwqr2Y0o1sprGMxsWk2pF0ppF4pr2k0rGQvsWYws2cwtmsztWswq2MktWwrsGcksWclrmMfr2MgvnQzuXAxq2Iiq2EhwnY1s2YjrF8bsmUftmoiwHUtxnw2smkls2cjtGYhr2EdxHg2wHY2tm4vtW4tuXIuunIuvHMwrmYjt3AsuHIusWsnunMwuXEvrWQhpl4YqmEZvXQvu3EwuG0wvnE4tGcutGgts2gruGwut2susGQorWMltm0ttGoouGwquWspwHIvvW8tuWsrt2ostGgsqF4drmUhunEutmoqs2UntWcnsGIgtWcluWsqvGwuvW4xv3M2w3c6wnc7vXE2sGQprGElo10hnlkbn1oboFscpWAhqmQotW8zqWQonFkcpGInqmcur2w0tXE8uHNCvnhHrmo5xIFQr207n10rpGIwo18tm1YjnFYhmVAbo1okqmIspV8prGQupV0nnlYgnFQeo1smp14qpF0qqmMxpl8tmVAeoFcksGc1pV0rrWY0smw3qGItqWMtrmgyqWMrsGQws2YwtmszsGcrpl8gtG0qr2cjsWYis2UirF4bwnc3w3k7q2Aiq18gwXQzsmUjql0Zr2Idt2sjum8myH84unAurWAdsGIetmgkwHMxvnQ0uHAwuHEuuXIvvHMwu3Ews2kotm4rt28stGwqvXQ1uG4vsWYlrGAcp10Xt28qvHMzt20wtmowtWgvtmovtmotvG8xtmgrr2Imq2Eis2opunAtt2wos2UivnAtvnAvuWwtvHAzuW4zrmQksWgkuW8tuWwtsWMjtmgns2UjtWckuWspvGwuvW0xv3E2w3c8v3M4uW0xtmsvsGUnpmAkoVwdoVwdol0eol0fp2Elsm4xqWUon1wfp2UqrGkvsm83tHA7tG07tW89tXJAx4VTsnE+omEupWQvoV8qmFQgmVUel1AZpFwkqmIsnlgjq2MupFwmnVQeoFYgpVslqWAso1onrWUzqWEvnFMfnFMfq2MwqGEvq2Y0sm46rWgzpF8pq2Uupl8nrmQvsmYxt2w0rmYppV4esmsps2sorWMgtWcksGEfwXU1x30/rGAiq14fwHQyt2onolURqFsWtWkiunAnwngzwXY1rWAerF4buWsow3c1wXc3uHAwt28uvXUywXc1vnQ0uG4ut20ruG4tsWcowXY5uW0wsmUnrmIgq2ActWwou3IxtGksql0ktWgvuWswum0wvXAyt2orsWQmrWIisGclt20rtmsnq10atGYku24tum0uvHEzuW8ytGsqs2oltmwpt2srsGIismQis2Uit2kmuGoouWsru2wvv3E2wnQ5wXU4uW0wt2wvsWYop2EloFseoFsepF8iolwfpmImr2ovqGUpomAjrmwxq2kusG00tnE6rWYxsms3tXE/woBOsnA9o2EupmQvo2EsllQemVYdmFMaqGEorWUvoFolrWYxpl4oolkjpVslqF4oqmArolklqmEtqF8solkknVUfolsnrGczrGg1sG05sGw4oVwnqWMtpF0nr2UxuG45t241rGUooloap2Aer2cjrmQhsWUitWknvnQzxn0+smcnrWAhvHAvvHAtn1MPqF0Xtmwkt24mvHItvnQzrGAep1kXt2kmxno4xXs7unExuXExv3Y1wHY1uG4vtWsrvXMytmwsql4hvXE2vW80sGMms2Ymr2MguG4qu3Evum4xq14ksWQpsWMntmkqu24uum4stWgpsGUks2gmtGkmt2snr2Ies2UiuWwqvHAvvXIytmwutGsptW0os2kmtWkotGclrmAesWQgtmgkuWoouGkpu2wvv3A1wXM3w3Y4vnIzuW8utGkppmAkpF4joVsgo10ipV8koFshrWkurWkuqWcrsG4zp2UqsGwytXA3qWMrsWk0rmo3xIBOvnpInVsopmQxpmQvm1kjmFUemlUdpF4lr2kzolwopV8rqWEtolkkqmAqqmAqplwmpVwnpV0op18qpFwlnlchoFsmrms2r2w5rWo4tXE+pF8roVompmArsGk0tm85sWkwq2MnoFgYpl4br2YirmUhsWYktGknvHQzwHc4uW8vsGQksGQjvHAtoVYSql8auXAptGwkt28rvXU1q2AfqVsZtWglx3s5wnk5u3M1u3M0u3Iyv3U1t2wts2kpvHIxt20tqV8guW4xv3I2smQns2YnrWIft20pvnMxv3M0sWQosmQor2IksGMjuGwqunAtt2srs2gnuW4stWgmtWcksWQgs2Uhum0pum8svHIxuXExsmootW0otGsnsmcktGclsWMgq10ZtWgkv3AuuWkqumotvW0xwXM1wXQ0u28uunAttWwppF4jolwhpF4jpmAlqWMonFcdpmIotnI4p2UqsnA1qGYrrWovtXA1o1wiqmIstGw7y4RVxH5OnVkpnFkorWs3oF0omlYgmVQenlkipV8qo10roVooqGAsoVkjpV0nqWAqpl4ooFgiolokqGApn1gfn1kjoVwmsW47r2w7qGU0rms5p2Mxnlglq2Yxrmk2tG86r2kwqWEkolkYqmEesWcjsGcjqV8dsWonv3c1vXU0s2sqrmQisWYkwng0qmAcplwXuXErr2chsmsoxHw8qF8drGEduG0ow3g2wHc3vHU1vnY4vXM0vnQ0unAvtWspvXMwt20rsGYmtmstu28xr2Ijr2MhrmMft2wownYzv3IytWgqtmkrr2IjsWUitWomuXAttmwqs2knuW4stWkntWcksmUgt2slum4ouG0qum8tuXAusmomtW0otWsosWYkuGoosmQhp1oUsGMeumwpvW4vuGgrvGwvwnM0xXg3vHIutm0ptm8rpF4iolwip2Ampl8mpV4lmlUcpmIptXE3ol4jq2gts3E2sW80tHA1olwho10jsmo4y4RWwXxOoVwumFUkq2c1pF8tn1olm1YhmlUgo14qolwro1wqrWUxpFsmnlUfpV0nq2Mupl0po1smpl4omFIamVMdol0pr2o4q2c3pWExrms6sGw6o14rqWUxrmw4rms1qmUspl8hoVgXrGEesmgkr2cjqWIftW4rv3Y0unEvsWgmrmQitGonx346smklqF8buXEstGwnsGklxH08r2UirWIeum8rvXQwv3c3vnc4u3I0vnU2u3IxvHUxt3AsvncyunEtsGYksmgot20tq2EfrWMfrmMetGgkwnUyw3Y1uWwutmkrsGMisWYjsWgktGsntm0qtWopuG0rtmsos2UismUhuGwluW0mt2wntm0pt24rsWkltW4ouHArtGkmt2omtGciqFwWrmEcuWoovW4vvGwwu20wv3EyxXc3wHQxuG4qt28sp2Iko10hp2Eko10ioVsgnFYcqGEotW40qWMnqGIntHE2sG00tHI4pGEmnVkdqGQtwH1Ly4lbpWQ3nVwupmMyqGMuol0ln1chnVQgp14sol0ppF4prmYxp14pnVMepVomsWUyr2Qyp10rpFwqmFQfk08bol0sq2Q2qWI2oFotsmw+tHA/pGEtomEqsG84r2s0qWMqpl8hpVsbq2Ees2omsGcjsWontW0rvXIuuGsotGcksmYktmsox3s5vHAurmMgum8quG0osmckxXw6tGgmql4bu3AsuXAtu3UzyIFAv3c3v3Y3vXU1v3g2unMwvXYzunIvsGYktWoouG0rql0bsWQisWQismQivnAuwnM1vXAyt2orsWUjsmgjtGsnsWgktGootmsnt2snuWwntGcisWQft2oluGwmuW4puG0puW4rtGsmtW8ntG4nsmkjtmoltWgjqFoXrl4evm0wu2kvv282um40uWwxv28zw3M2vm8yvHAzqmUmo10fqGIlpV8joFofnlgfqmMqs2wxq2MnqGInunY8r240s3I4pWImnVkbp2UruHhD2ppqs3VHnl4vp2Yyrmkxo1whoVcfoVcipV0ppmEspV8qqGErqF8pnVMdnlIfrGAusGU0qV8up18vn1wplFEgpmExqWM1q2U3mVIlq2U2sm89qGYxnl0msW43sGw0qmQppl4ho1obplwas2onrGQgs2wpuHAtuGwpvnAts2UisWUjvHAuwHQyv3MxsWUjuWwptmglrF8cw3g2uW0rpVcVum4quG8rsmsoxH48v3g3u3IyvXM0xX09u3MzvHQzwXg2smgmuW4suW4sqFwasWYks2clrmEfvXAwvG8wvnEzuWwts2ckt20ouW8qr2YismcltGkltWgjuGsmsWQfrmIdtGkktGgjum8quW4qu28suXEtsm0nrWcgrmYfs2kjt2smrF0bq1wcvGsvt2Usv283uG00vG81umouwXA0wHA1v3E4qmUopmAkp2ImqGMnoVwinVkhqGMrsWovrWYrqWQps3A2rmwzqWcto18jo14gqGQqtHM90JBeunpKmloopGMtrmowo1sgoVceo1kiplwoq2Mvolwnpl4opVwmnFIcnFEdrGEvrmQypFsqpV0tol4smlclpmEwq2U1rWc2l1Egp2IwsW46rWo1oF8prGkyrWcvqmMpqGAkp10folgXrmQhqWEds2wpvXUztmsovXAttGcksmYkvXEvuW0rvnIwtGgmuGonumwprmAetGknvnIwq14ct2sovnQwt28swHo2xH07tGwru3ExxHk5wHQ1v3U1wHU1tm0ru3IwunEvqWAdsWgmtGspsmglwHUyum4uum4vt2sqr2QguW4punAqsGgitWomr2QgsWQgtWkksGMerGEcs2gjsWYhuG0oum8ruG0rtW0qtW8qsGkkrGQfsWcitWklsGMgrmAfumwtumsuu20xuW4yv3I1tWcpvW8yvXEzwXc8p2ElpF8kqWUqpmInoFwin1wlqWUtsWwyq2Uqp2Mor2w0tHE5r2sxp2Ekpl8grGcqs3E5wIBMuHhHn14tn10nrmkwo1sgn1UbpFkjqmAqrmUxp10pm1Mdpl0nnlQfnlUhqmEtrGQxoVopnVcmp2IxmVUkpWAuqmUyqWMvnFYhpmAssGw3q2cypmMurGcyrmgxrGQrqF8kq2Iko1katGooqmEfsmsovXYztWwovHIuum8rsWUjvHAuuGwqum0ruGont2kmumwptWgmtWopwHQyr2EftGYjvXMvvXYyw305w3w5uXEuwnc2x3k6wXM0wHQ1wnc4t24ttW0rvHUyrmckq2UirWcks2omw3k2sWcmunAvt2wprWIeuG0mtmsks2gjum8rsmcjrWIesGUhtWolsGUgt2wnr2Qftmsnu3Iutmwqtm0rtm8stG0qqF8cp10Ztmsmsmcjr2QguGwquGssvG8wvXEzuWwtsmYlsWcmvXU2v3k7olwhoVwhqGUro2AnnFshnlsjqGQsr2oxoFwhoF0kqmgxsnA5rmszqGImqmEjsWwvtXM6v35Kvn9OrGo6nVomrGcvpV0koVYdplwmrmMvr2UxqF4qnVMdo1oknlYgo1olqWItqWIvoFoomlQjqWQynlknolwoqGMtqWQtpF4np2Qtsm44qWUwq2g1qWQvrmYwrGMrpl0irWQnpFkas2kos2knrWYjunMwtm4qvXMvwnk1rWMht2spuW0rtWgmvW8tu20quGkmt2kouW4uvXAwr2AfqFoYt2onvnUxwns3wns3wHc0wXc1w3c4v3Q0wHU1w3k5unIxtW0suXIvsmonq2MfqV8br2chwHczrGMguW8tsmkmq2AbuW4ot2wluG0ou3ArtWomql8brGEcsWYhtmsms2okqmIcsGcju3IuuG8stmsqt20ttGoppVwapFsXs2gktGkksGUgtWkluG0rwHQzvXAwuGwqsWckqWEevXc1vHg5nVcdpmAnp2MqpWMqm1shmVcfpWEpsm41oFsjmlcgqWcytHM9sm84qGEnq2MmtG4zs3E6uXhGzYxfu3lLmlYlqWMuqF8opFkjqFwprWEvr2QwpFkloVgiolokm1Qeo10nrmgzp2Iuol0pn1koqGExpF0rnlgkpmAppmIopmEnrGYvsm03pWEtr2w5pmAsqWAqrmQtqWAnrmUpoFYYrWQjuXEusmsouXIvunMwtm4qwXg1rmQis2knuG0rql4cuWwqu20qumwptGcluG0tv3EwtGUjolQRs2Yiv3Uwv3gywns3wHg0uXAtvXQzu3MzwHg4xH09u3Q0uXExuXAutmsosmcjplsWsWgjv3g0rWUhtGonr2YiqF8avHMsuG4nuG0ovHEtt2woql8cql8arGEct2wntGolqF8aqmEduXAsvXMwt2wsum0vtmkqql4dqmAdtGsmsmkjsmkktWoltWomvXIvvG4tum0qsmgkq2QfuXQxu3g3oFkgpF4lpF8mpmQrm1shnFohqmYtt3M6qGUtmFYftHM/wYFOu3hEq2YuqmMosWwysnA6unhHzo1gw4FVmFUmqWMwq2IuoVckql8vrGEwrWIvoFUhnFMeoFgimFIcn1kjrmkzq2cxqmUxpWAsqmIxpV0rnVYhpV4npmAmpmAmrmgxsm03p2Qvq2c1pl4qplwnsGYwqV8nr2YrpVwfpVwduHEvtW4rs2wovHUxtW4qs2sntGooum8tv3Qyql4ctGglsWUivXEts2gltGknv3EusmMgpFURsWMewHYwwHkzw3s3w3o2t3AtuXQzunU0vXg4wXs7uXMzuXExu3AvtmkmtmckqVsWs2okvncyrWQhsmgmr2YipFwXvXQtt20otWsmuG4qum8trWEeqFwZrWEesmcjtWomrGIdqmAct24qvnQxum8uum0wt2osrGAfqmAdtWsnsGchsWgium8qr2Ieu24rvnAuvW8sum4qsGgjuXMwvXk5oFggoVsipmIprWsxoGEmqmcuq2YtrWkwq2gyn10p25xq15hnx4dVrWo0o18mq2cus3E6u3pIwYFUw4JWp2Q2o10sqmIvpFspp14tql8vr2Qxo1gkl08aoFkjlU8ZlE8YrWozqGQvp2ItpV8qpl8sqGAsn1chpV0npl4noloksWo1s245qWYxqGQxpl0pplonsGYxq2EqqWEmqGAjolkasGkotW4rrGUhuHEtt3AsqWIetGoowHQyx3s5s2cltmoos2gkv3QwsGYjsWYkvG8rtWUiqlkVrl4axXk0w3o1wnk1w3o2v3g1vno5wH08vns7wHs8vHY3tm8vuW8usGMgtGUhrl8atmsmvHMvrWMhr2UksWclrGMftW0ntGwmtWwot24su3AvsmUjqFsZrmIetGklsmcjrWIdqF0ZtWsnvHIvum0tuWsut2orr2MiqV4bsWYisGUgsGQfum0pt2kluWspu20tumwqvXEttWsntW0runQ0oFginFYepmIprGswpmUqrWkwp2IppGAoqWcxpWQy36Jz0pdo05Zmt3ZDnVslp2UqtHQ6s3NAuXpLxIRWrmw9o2Atq2UwrGQwqmIwqmEvrWIvolklmFEcp2ErmFMdllMcq2gxpmErqGItqmMuqmEtrGMvoFcjolklqF8qpl0os2w3tG86q2cyqWQvp10rplsoq2Asr2Uvpl0krWUpolocrWUltm8spl8btG0puXIusGkltWspwHUzw3c1tmootWspuXAsvXUxqmIermQgu24pt2gkr14asGEcw3cywnkzwno1wnk1wXg1wns6xX8/wns8w30+vnk6t3Awu3Mxs2cksmUgrmEat2wnvXQwtWsps2kos2kns2omtm4ptWwntGsnt20su28vtWYmr2EfsGIftGgksmcjrmMfql8btGklu3Ast2oquGkrt2oqsmYlqV4brmMeql8arF4atmckvW4suGkouGostmgnvG4rum0qtmspu3MzoVkjmVIap2Mprmswrmswq2Usp2Eoo14mp2Uwq2s5zI9gxIla05dny4tZoWAqpGQps3Q4rnA6t3lIzY5fsXFApmQxqWUwq2UwqmMvqGEuqmIuo1snlU4ZoFwlmlcgmlcgqWUuqGItqGAsqWAspl0oqF8qolklo1onqmEuq2IwsGg2sm05q2cyqWQvpl0qplwpqWArsWgyqV8nrGMop14grmUltW0ro1wYsGkluHAstm0ptGknvnIwwXUzuGwqt20runIvvXYyqmMfqF4ZtWkktGUftmYfsmQdvnItxHo1xHs2xXw5wXg2xHs7yH4+xn4/x4BBwHk6t3AxuHIwt28rtGwmsmkht20ou3AtuW4stWsqsGYms2omuHAstW4qsWonsWgnum0utmcnsGIgsWMhs2Uis2UisGIfsGQgs2gku3Ast2opuWoquWwqsmckq18bsWUgr2IdqVsXtGQivGopuWkqu2wvuGoqumspvW4rvG4tvnEzpF4nm1YgqWQtsGw0sWsxrGYtqmUtpF8pqmcztHNAu3xJq205tnZBy4lTqWUvp2MqtXI5sW85r249x4lYu3xMrGo5pWEuqmMwqmMvq2UvrGgypmIqk08XmlYen1sjoV0lqWMtp2ErpV4pqmMuo1skpFwloVghpFkkq2ArrmQvr2YzsWo4rGU0qGIwpmEspmArq2UvtW44rWcuqGEmqmMmrWYmsmopoloWr2UhvXMtt20ns2civXEsw3YzvW8tt2souG4qwHc0r2UgolcRsWQdsGAaumojtmcgtmkjwnUxv3Qxwng2xHo5xXw8x34/vnQ3xHw/wHg7smkstGsrunItt28puHApt3Aqt3Aqt28stm4srmUjsWkmuHAtuXAvsmgpsGQmumssuGkosmMhsWIftGUitGUir2EesGMgsWUiu28sum4suGspu20rtmkmsWQgtGYitGYiqFkWsGEet2kmumsqvm4vu2ssumsru24uvG8wu3ExoV4nl1MepF8qs204s2w1sGoysGw0o18qrmw4uHdDsnI8pmYurWwzyINKtG03pV4mtm83tG87tnRDzIxcxIZXsXFCoF0tpF8tqmIup2EsqmgwqWYtmVUdmlYeoFoipV8orGYwqWMuolsnp2EspV8oo1wkoFcfpVsjrmMsr2Qvr2UxsWg2rmc2qWQzp2QwpWIrqWUutHE5rGcupmAlrGUor2gprmYlolkWrWMev3Mtt2sltWkjvnIswHQvvnEtt2snsmYiv3QxsWYhoVUNrV8Xr2AYuGkgtmggsWQdvnIswnYzvnMxw3k5xHw9xn0/tm0wvXM4v3U7sGUos2kpu3IusmojtW4mt3Ers24osm0otW8rqWIermYkunEwuW8vsmcor2IktmYnuGgntmYlsmMgsmMgs2QhsGEermAesmUju28tum8ss2cjuGsoumwps2QhtWYktGUjrF4br2Eetmkmumsqvm0uvGssuWorum4vu3Exu3ExpGArk04ZoFsmunU/tW85sGw0sm83qmcytXNAu3pGpWUuoWEopGIpvHc+vndArGUtsWw1sW45uHhFyIpZzY9gyopcqmg4pWIwqGIvpWArqmcyq2gynlkjmVMdoFokq2MtrmcyqWIvo1wqq2Qxo10no1wmo1okp10mqmAqqmErq2IurmUyrGYzqmUzqWUypmItpmItsm84rGcvol0irmcqsGgprmYlpl0ar2UhuW4qtGkkrWIdt2wnvHItv3QwuW4qrmMfvnMvs2gipFkPq14Ur2IXtWgctWgds2YdvXAow3cyt20pvXQyw3o8x35AvXQ3wHc6wHg6tmsttGopu3IusWkjs2kjtG0ms20ntG4ouHErrWYhsGYktWsqtmwstGoqrWEhtWcnt2cmt2cmtmUismEdtGQhtWYjtWYjtmgmu24suW0rtmootmoouGoosmMitmcmtWUkrl4drV8dsmQitGUjumkqvGwst2kqu28vvXMzvnQ0qmQwl1EcoVwnv3xFs3A5p2Usr2w0rmw2s3E9vXtGpmUuoWAmomAls241uHM8tnE5sm83rmw3sXE+vX9OxohZ2ZtrtnZFo2EvpWEvpGEuq2g1rmo3pF4pmlQfnlciqmEtrGMvqF8spl0srWUyo1woo1wnpF0nqGArqGAqo1slo1smqmItpF8rrGc1rmk3pGAtpGAstXE7rWcxoFohrmgrrGQlsWgnpl0arGIeuG8rtmwpqF8br2Yiv3YywHczvHIutmsnvnMvum8oq2AVploOr2QXuGweuGoetWkevHEnxXszvHIsvHIwxHs+xn1Bwnk8wnk7vXQ1um8vvHIvu3EttGoltGkktWsltGsltm4ovXUvr2Yir2Yis2onsmgmtGoor2Qit2kouGcltGMgtWQhtWQgtmUhtGQgt2glumspu24ruGwrtmwrt20suGwrsGMht2gnuWkoq1sarV4cs2MitmYluWkot2kosmUkt2wrvHIyv3U1pl8tmFIdnlkjt3Y/rG02nl8lrGszqmgyqWcyuHZBq2kxomAnol8lsGsytG44rmkyrms1qGczrG05unxKxolY36FxyotbomIxoV8up2UyrGo3sG07qmYyoFsmmlMeo1slqGAqqWArq2IurmUypV8tn1sopF4prmcyq2QvnVchm1QfrGUwnVciqWMvsms5pV8to1wqtnA8rGYwolsjtm8zrGQksGYkqV4aplwZuW8tt20rpV4brGQhvnYzuHAsuXAstGwmuW8qt2slsmYcoFQJr2MWum4huGsftmoetmohyHw1w3o1vXU0xXxBxHxAwXk7wno6uXEvt24rwXg0vHIusmcjtGklu28rtWolsmciwXYytmsnsWcitWsnr2YitGsnsWcjtWglt2clsmEetGMftWQgtmUhs2MfumsnvG0qu24rum8tsmkpuG4ut2wssWUluGsrt2gorFwdrFwdsmEitmUluGgmtWcksGMhs2gmu3Ewv3U1oVwrnFYhnlwlsnM8qm44nF4lrGwzq2ozo2EstXI8q2gvol8lo18lsGsytW85rGgxsW84p2YwrGw5tHdFwINR251s2pxstndIoWAyqWg3qmk2r245sG03pWArl1EanlYeolojqGApr2cwsGgzpV8tnFclpF8ssGs4qmUym1cinFcis204nlcipFwnsGg2qWIwo1wqsms5qWMvoVsjuHE2rWQlqmEdqV4apFoXt20rtGwrolsZqGAfwHg2t28suG8rtGokuW8osGYetGohqF0TsGQZtWketmofuGwjr2Mcw3g0xnw5u3M0xHtAw3w/w3s8wno5vHUyvHMvwnk1v3Uxs2gksWYiu24puWwnr2Meum4pv3QvtWolsmgjsmgktm0psGYitmgluWonsmIetGMftGMftWQgs2Meumwntmcktmglt2wrs2sruG8vs2kptGgpum0utWYnsmIisF8ftGIitWQjtWYjtmgltWkmtmspunEwvnY2nVknn1kjoF0msHM8p2w1lVggrG00tnU+pWItsW83q2gvpWEmpGAlsGszt3I8sW84snE7pGMupmYyrG06rXA+3aBu2Ztsz5Fjpmc6oWIzq2o3snE9tnU/o2ApllEan1gfn1gfolwir2gvsWozp2Eun1oooFspq2Y0pWEunVklm1YhqWMtn1gioVgjrGMwrGMxqWEvtG05rWcxqGMqtG4zq2Mkpl0aq2AbpFsWvHMwt28upV0cpFwcvXY0tm8rt24qtGkksGUerGIbtmsltGggsGMbtGcfuWsjtmkirWAcum4sx349wHc5xn5Dx39CxHw9vnY2u3QxvXUww3gzv3QvsmcjsWUgt2sku24ns2YgvXEswHUwtmsns2kksWcit24qs2omt2onumwptWYitGMftWUgt2YismIetGYhs2UhtmgltmsprmUntW0tt20tuG0tt2ortmgorV0cq1oZtWMitWQitGUitWckuWwquW4tunAxu3Mzo2Aun1oknVoivH9Ip243nmMqq200unpDpmQuqmcwqWUrpmImp2MosGoyunU/v31HsXA6pmQvpGQuq2s4llclwYRS2Zts3p9ywIJWqmw/qmw7s3RBtHQ/o2Erm1chnFcfn1kfo10jsGkvsmwzq2Uyo14spF8tqWUzpmMwn1oom1Uhpl8pnlUfoFYgp10nqWArrmYyt3E8r2kzq2Uts20yqGEhpVwZqF4ZqmEbwng0u3EvrGUirWYlwXo4u3Qxtm0psmYhr2IbqFwVtWokuGwlqVwVsWMcvW8os2YfqV0Ytmspw3o5u3M0xHw+x4BBxHw9vnY2t3Auu3IvwXczvHEtsGUgsmYgtWoit2sjsWUeum8qvXItuG0punAssmkltGoosmgmtWkmtWgkt2kktWchtGYgtGYfs2UfsWQes2YhuGont2wpr2cmsmoqt20rt20rtmwpuG0qrF4bpVcUr18ctWQgsGIfs2Qium0sunAwunEzunEzrGw6oV4mmlgfxIZQvYNOs3g/uXtCu3pEr203qWYuqmQqo18jqGQorWgvsm44snA7rGo1qWcypGIts3M/mFkmqms52Jpr15ltx4pfu35TpGg6tHVGsHA/pmQxoF4pnFchoFojpl4nrmcvrmYwqWIvolwqqWYzp2Uyp2QynlknnlklqmIunVIenlMeplwlq2Irsms0t3E7q2gwpmIosWswq2Ijpl4aqF4XrmUfwHgyuG8rqGEes2wpw3w6vHUyu3Its2chr2QbqF0UsWcfuGwjqFsSrWAXvXAntmkhpFgStGsmxn46uHEwu3U1xn9AxH0+wHg5vHQ0vXMyv3Uxum8qrWIbrmIauG0lt20lrmQdum8qvHEsuW4qvHIvtWspsmgmq2EfsmcjsGQftGchtGggtGcfs2UetWghtWghtGciuGwntmsos2kns2knunEts2onsWgktmomsWQfqVsWrl8ar18brV4bsGIfuWwsuW8xuXAyuG8yqGs5oV8nmlkftHZAz5RgvoNLu3xEs3I7q2gxq2YurWctqmQpp2Inrmoxr2s1q2k0tHI9qmgzrGo1tXQ/pWQxnV0sxIZX0ZNnxIZez5Foqm1Du31SuXlLqmg5pWExnlgmnlckoVomq2QvqWMupmAspF8tqWQyqGQypmIxoFspo1wqrGIvo1cjnVEco1ggsGcut3A3tXA4q2gvp2MoqGMmqWIipV0YplwVrWMcvXMttG0opF0ZtG0qwns3tm8svHItt2skrmIZq2AWrmQatGkeqV4SqFwQvXInum8kp10UsGchw3s3uHIvuHMxxH09wXo6v3g5wXg6wnc4wHQyvHErsGQcrWIYv3UtuXEps2kiunAruG4quG4qtGsos2knsmgnq2EgsWcjsGUhr2MesWUdtGggtmois2Yet2sks2ciuW0otWomsWcksWgku3MttGwmsGgismkjsGYermEarmAZqlsWr2AdrmAetWopuW8wunE0uXA0r3NBnF0lmFkhomQuxYhUvoFMtnZBrWs2qmYvqGMpq2UprGYqpF4iqmYsrWkxvHpFs3M+qmg0r2w4undDqWYznVopuHdJyotfwIJZzI9nqm5EtnlOvX5St3RHrGc4nFUkmlIgn1klqWQup2Mto18qqGMwo18sqGMwqWQwo10po1smrWMuqF0omU4ZnFIarGMqtG42tHE6qWcvqWQrqWImqmEhqV8aqF4Wr2YdvXQstGwlo10WsWokwXk0uG4ouW0lt2sisWQZr2IYrGIYsWYbqV0RolcJu28iuW4ipFoRq2Icv3k0v3o3vXk3wn08wXo6v3c4wHc4vnQ1vXIvuW8rsWYeq2AXunAnuG0mtGgjv3MvuW4quW8rtmsptmsptGonr2YitGwlr2YgqmAcrmIesWQgtWkhr2QauW4ktWoium0ouGwos2cjrmIftmomt24otm0ns2slsGcgsWYfqF0Wql0YsmUisGMhs2gounAxvHM1vHM1tntJkVYelVkgnmEqx4pXwYBQsW49rGg2r2k0qWIqqWEnqmMnoFoep2Inq2cttXQ/rGw6pGIvrWg2u3VCtG06o1wsr2s8vXxQuXpQy41iuH1QtntOvn5RyIRYsGo8olkpnVQin1kkqGMtqWYvol8rp2Mvnlsln1wmrmkyqGEqpV0mqWErpVsmmU4anVMcqmIqs245tHE+rGk1qGItqmEnqV8fsGQfrWIZrGUbvncuuHEoqmIasWkhwHcvvXMqtmogtWkdt2oduGsfrWMarWIYsWUZolUIsGQXtWofqmAXsGciwns5wX07wX08xYBAxH4+vHQ0vnY2vXQyvXQwu3IttGskrGIauGwkuWslt2kkv3Atu20qu28tum4rt20otm4os2sjtW8krWYeqV8crGEhrWAgsWcfrGIVtmwft2siuGomuWoouGkmtGYjtmkmt2wotWsmtGwmsWkjrmYgqmEbqWAbsWclsGUjs2kou3ExvXMzvHIyu4FPmFwmm18nsXQ9xIhVv39PsW8+qmc1rmgzr2cwr2YsrmcroFoeqGIntHA2tnVAsXE/oV8srWk0uXI9t247q2MxsGo6uHVHwYFUzZBkyo5ivoJVtnRIxYFUuXJFqmIzmFEgnlompWIspWQupGIvomAtnFkkm1cirWozqWMtpFwmpl4ppVwomE8Zn1UdqGAptHA6sG06sW47q2Qwp1wkplsesmYjrmQeq2Qdt3EqtnApp2EbsGokvnYwv3YvtWsjsWcdtGkevXInsGUdrmMZt2sfplkMrV8TsWUar2Udtm4pxH06wXs6wHs6xX8+x4BAvHU1vHMzvnQzvHMvvXMvtmslsGYeuW0luGsluWsnu20qvnAuvG8tuW4ruG0otWolsGcgt28ktGwksmYkrmEiq18dr2UeqV8UsmgbuW0ltmgmuGkouGkmuWsot2wouW4qtmwotGsmsGgirmMerGEcq2AbrWMgrmQisWcnuW8vvHIyvHIyxYpXpGcxo2Yvu39Kx4pYvn5OsG08qGUyqmUwsGkysGkvsGovn1kepmEmuHQ5w4JMu3tInVsnq2Yxtm45tm05sWg0rmc2sG08uXhIvn9RzpBjyIhbsW5Bu3ZJunNGsGo7mFQjoV4somEuoF8spmQyo2AunVonlVIeqmYxpmEroVolo10opF0om1Idn1QcrGQst3A6rmk1s248sGg2olcho1kes2kprmQhqWEds20ounQvpmEcsGsmvHUxu3Mvtm4ptm0mtWsjuXAmrGIYr2MZtmofplkNqlwQsWQasWUduG8pxH05wHk4u3UzwXo5yIFBv3g3vHUywHk2unEtvHItt2wmsWYft2sltmkkt2snum8rvnIwum4suW4ruG0ptGcirWEbsWcet2sjum0rsWQlrWEfrWMdp10UsWcduG8otWont2optmkmuGonum4qt24qtm0ptW0osWYhr2Qfq2AbqF0YrWIfsGQitmkpu3Awu3EyvHEy1Jhjt3lDqGo1rHA8uHxKyYlZwX5Ormo5rGgzsmw2rWcurGYrolwhpmAls240vXpFtHNBnlsoqWQvtGs3t205tWw3rmc0qmYzqmc2r209zIpb0pBism5AsGs9sWs9qmY3o2EwpmU0p2g3oWIwpmQzpmMypWIwl1QhpmEuoVwonlgkoVsnoFklnlUhnVMbr2YutG44rmk1sWw6s2s4pFkkpVoht24wqmEhq2IhuXAvuXEwqWIgsGonuHIvt3AttW4qtGwmtm0ltGohqmAVrGAVtWkdplgMpVcMsGQatWkiuG4pw3s4wns5uXIvv3g2xH08vnc1u3Qxwns4unEtu3EtuW4pr2Ufum4pt2smt2snum8rvHAuvXEvuW0quGsntWcjsGMermEatGYgumwpuGsptmonrWMepl0XrGQesGoksWkosWYlsWUhuW0puW4qs2omtWsnuG4qs2gksWUhrF8bp1oXrWEesmYjtWkpuGwtu28wv3I00JJcxYZQtXdCsnVCqGw6uHhHzYtasW49rGg1s245rmgwp2EopmAlqWMosGowr2w3sW89qWUzrWYytmw4tWo1tWs2r2cyq2Uwp2Qwrms5vXtKv3xMtXBBrmo6uXNEvXlKunhJtndIxYhYq209o2EwqGU0p2UzpGEvpmEvnlknnlgmpV4snlclnVUim1EarGMqsGo0rmo1sGs4sGg2p10ppFoit24zqWAirGIhtmsqtWoqr2UlsGclvXUyuXEtvHMusGcgsmkgum8lsWYbrmIWsWMXqFoOplkOsWQctWkhtmsmwHc0wXk2unIvv3g1wns4vHUyuXIvvnc0t28ruW8quG0ormMeu3Art2wouG0pt2wouG0qvXEvu24rumwpt2klsmQgsGIdr2IcuWsoumwqt2oosWckq2MermUhsWomtGsqsGUkq2Adt2wouG0ptmwotWwotWomsmcjsGIfrV8cp1kWsGQgtmootGcnt2oru24vvnEzu3tDuHhCuntGx4lWvIBNqWo5unhIr207qGYxrms1sWw0qWQqp2Emp2Emrmgus3A7s3A+o18tpl8ts2o2tGk0tWw2r2gyrGYwrGgxr2w4sW48s249t3JBsWw7vnlIwH1OvHlMzIxfzpBirnBBpGExqWU0qGU0p2IxrWg3o14smVQipV4solspoFglnlQfqWEqrWcxsm05sWw5rWYzqF4ppVwksGgsqGAirWIhtGclrmIgsWYjsGcjwXczu3EsuG4ms2kgr2QZuG0irmEYrmIWsWMXp1kNqVwRsWQbs2cftWolvHIvu3IvunEtvnYzwHk2unMwt3AtuHEut24qt20pt2wns2gjuW0oum8qu3Art2wotGsnuW8qvHEsu20puWsmtWcir2IdrF8at2onumwqtWkmsWYjr2YirmUhsmontGwqsmkmrWIetGgkt2sot20puXAss2gkr2QgrV8cq10ao1UStGYjuGwqsWUltmkquWwuum0vtXU7p2Uur286u3xJxYhVpWY0sW89sG88qGYxrGkyr2oyq2UrpmAlo10hrGUpt3I7sm89mFQhn1gms2o3tGk1s2k0q2QuqWMtq2cwrWk0pmEvpF8trWg2qmUzr2s5qGU0wX9P4Z9x3Z5xtnRHp2MxqGMxp2IxpmEwqmU0o14sllAeoVoopmAro1wnnlUfpV4oqGItsWw6r2o4rmYzqWAqrWMqrWUoo1wdrGEftGckr2IfsWYismcjw3g0u3Aqs2gftmsftWodtGkbrF8TsGIWtWcbq10RqlwRsWUcsmYetmolunAsu3IuunEtv3czwXo2unMwtG0qt3Ast28ruG4puW4puGsmt2oluGsmuG0otmwnsWkjuXEru3ErvG8ru24puGolsGMfql8btWomt2snsmYjsGYisWgkr2YismkltWsosWcjrWAdtGckt2wouG4qvHIus2klsWYir2Qhql0ao1UTs2UivW8ttmcntmgquWwuum0vtnQ6qmgwu3pEwYJNwIRPrW47rGw4r285pmUvrGozqmcuqmYqpmEkol0fpmAirWgxsWw6oVspnlclsWk3smk2rmYyp2Eso14pp2QuqWYwn1snol4pq2czqmUxq2czqGQzwX1OxYJUwn9StXJDqWYzqWQyq2Y0pl8upl8uoVspl1AenlgkpF4poVslnVUhoFkloVsor2o4sm07sWo2rGMrsWctsGgppV8drWQhtmoor2QirmMhsWckwng1t20os2ggtGkfuW0itWkcrmAUr2EVumwgsWMYqlwSs2YdtGchvG8rtGklu3AsuG4qwnk1w3s4v3g0tm8rt3AsuXAst20pt2wntWgjtmkitWkitmojuG4ns2sjuHAotmwluG0muGwluWwmtGklpVsYuXArt24psGcisWgksmklsGUhs2kltWomrmEerl8cs2UitWklu3EtvHIusmglsWYksWUjqV0boVMRrF4bvG4st2got2kquGstvnE1sW4zrGgxv3xGyYlTvH9JsnQ/qWo0snI8pWUvsHA3rGowqmgspmIlo14foVscpmAouHNAs2w6oVoosWg2sWk2rWYyqGMupWItqWcyqGYwnVkkpWEsqmYxq2cyrGg0nlknuHREv3xNsm5Aq2c4qWQxq2UysGo3pl8tp2AvpV4smFEemlQgpV8qo10nolomoVknoFoosGw6sWw4r2cxsmgvrWQorWYkq2Uhr2clt20urGMjpFwbrWQiwXk2uXAss2kitGkhtmshtWoer2IWrmAUtmgcsGIYrF0UsWQcs2UgwXMvtmomt2wotWomwHYywno2wXo2tW8rt3AsvHMvu3Etum8qtWgjuGojtWkht2wkuG8msGgft3AnuXAns2kgtmkivW8ptWomolkWuHAruXIssmoksGcis2klsmcjs2citmolsWMerF0armAdr2MfuW0qvXIvs2onsGYkr2Qiql8dpVgWq1wZuWspumsrt2gquGstvnA1qmQoolwir2oyt3U+qmszq2w1sXE7t3VAqmgysnA5q2kwq2kvqGgqpWIjn1sbpF8munVAwXtGpV8rrGQxsWk2r2c0rGYxrGcxrmk0qWQvnVkkpWEsqGUvr2s2sm05nVoouHVFxoNVt3VIqWc4pGEwo18tsGs5p2EvqmMxpl8tmVMemFIdpF8ppmEqpF4poFoooV0rtXE+rmk0qmMstmwzq2Ikq2QirGUhrWUkuG8wq2QjoVkZrmYlwXo3t28qr2Ufr2QcvXMqtGgdsGIWrmATs2UZsWMZrWAXtWghtWgiu24quW4puW8qtWsmvHIuwnk1wXk1tm8ruXEtu3Euum8rum0pt2oluGwltGgguG0kuXEns2wju3QrvnYstm0jsWYetmoitm0mqWIds2wmtm4otWwmsWYitGgktmsntmoltGkir2MdqlwZrl8csmMgtmckvXEttmwpr2Ujq2Aeql4cqlwasGEguWsqt2cot2gqtmgrumswpV0hnVUZpF0isGswpWMopmYttXQ8tW86qmIutG85rGozqWswqGsupWYnn14eo2AjtXA3vnlCpV8pqWEtsmk1sWg0smg0smgztGo1q2MuoVwnpWEro2AorWozr2s4pmQ0uHZIunpOwYNYtHdJoGIyoF8vrWs6pGAvq2Y0qWMumVMdk04YomAopWMrpGArm1YjnVgmsWw6sGs1p2AprWUrqGAjrGQjrmQjrWMhunAurmUjoloWr2Uhx304tmslr2McrGAYwXUsuGwfrWEQqmAQrGETs2gbrGEWs2ogtmwktm0mt28ouHArvHMvvnUxxXw5xXs5uG4suG4sum8tum4rtmkltmkluG0mtWsjuG8nt28ns2sjt28nvXQsuW8nr2UdsmcetWsirWUcs2ohtm0kt2wkr2MdsGMetWoltmsnsmgkrWMfql8crF0at2UitmUiumsotmsnsmglrmEfq1sar14cs2QluWoruGkruWksuWkuuWkupl0hnVcboVwfrmsurWsvqWkvsXA3sWwzqGEpr2oypmUspmgtqWwvqWssoWAhpmAksWsxtm83p18pqF8qtWw4smw3s2s3sWo1sGo1qWQuo14ppmMsn1wkqmcvsm86r208snBDtnVJxYVZvH1PpWY3o2IzqGY2pGAvrmc1rmgznVcikUwWoV4nqGYvpWEsnVgmoFootG07smw3q2MtqmIpqWAkq2MksWcmqWEeuHAtr2ckoVgUrmUgyX86tmslsmYesGQcv3Mqu24jr2MSqF0Oql8RtWodrWIXq2EXtGohuG4ntWwmsmoku3IuvnUxw3k2xHo4u3EvvHIwvHEvum0qtmglt2omuW4nuXAot24muXEptm4os2skvnQuvnItsWQfs2cht20mr2UdtGoiu3Eptmsjr2IcsGMetmsmtGkktWsnrWQgrGEcq10Yt2UhumgkuWsntGkksGcjsmYirV0asWEetWcmumwquGkptmcpumouuWkun1oenVcboV0hqGUpr2swp2Urq2gvrmkvrGYrs280rGsvqWourG0xrGswo2AkpF4jsGguuHE3smsyoloksGs2sm04rms2rWo1q2k0pmQvn10np2YuoF4lqGUts3A7sG08sGw+rmo+vntNw4FSqmg5p2Q0qmc2p2Iwq2QyrGYxnlgjk04YoF0mqGYvq2czn1knoVops2w6t3E+rmYxrWQtplwirGMms2kpq2MfsWomsWomoFkVsGgix344tGokrGEbsGUdwHUttmofsGMUrWESq18RtWoer2QYq2AVsmcetWsjtWwktWslvXQwvnUxvXQxwnk3wXk2wXc1vXIwuWwqtWckt2oluW8ouHAotGwkuXEpuXErqWEbv3Uvv3MvsGIetGciu28qr2Qes2chv3MttWkjr2IdsmYhtmwnt24pt24ormQfrGAbrmEctWUhvW0pu24psmcirmMetGcirmAbrF4atWckumwquWoptGUmuWktu2svnlodnFcbn1sfol4jrWkurGkvqmYsrGYsrmkttnM1r24wpGUnq2wvtHE3qWUrpWAlrmcttG40uHM6o14nqWUvsW45rWw2rWw3qmo1pWUvn14npWUrn10kol8orWk0sGo6r2k6sWs9sGo8vHdIrmo6qGQ0q2Y1qGExrGUyqmMvolwnlVAbp2Mtp2QurWY0n1gmoFgnr2c3u3RCsGc0q2IsqmAnsWgrsWcoq2QhrGYhtW4qpV4asGgjwno0tm0nqF4YsWcgwnYvtWofrmITrmESr2MVtWodt2wfrWIWtGkftWohsWYfu3Arwnk1vHQwu3Qwv3g1v3c0v3Uzv3Mxu24st2kmt2snt28otG0ls2wjsmsjunIsrGQeuXArwnUxqlwZs2QiumwpsGMfs2Yhu24ptmkksWQfsmUgs2kkuXAruXErsWgiq18asWQgtmcjvm8ruWwosGQgsGQgsmYhr2EcrmAbtGYitmglumwptGYltmYpu2suoV8hm1gbnVoeol4jqGQprmkvqmMprGYrsG0vsW8wsG8wnVwepGImtHE3q2Yuo2EmqGYrq2kusm82oF4moV4orWs2r204rWs4q2k2pmMwoV8oomEooV8mmlcfrmo1tGw7sGk5qWIynFUlsWo6sGs6q2Y1qWMypV0sp18tp18tpV8qmFMepGArqWQwqmMxoloqpFwsr2c3t28+rmUzqF8pp10ltGsvsGcpqWIgrWgjuXQvqWQesWslwns1smokrGQerWIcwHUvs2cdr2EVq10QsmYYtWoct2wfr2QYs2ges2cer2MbsGUgvXUxvHUxvXYyvnc0v3g1vXQyvnIwum0qtmglum4rtG0mr2khsWwjqWMbtGwmrWUfvHEtxHYzrl8dsGAfvG0rsmQhs2UiuWsouGomtGcjsmYhsGUgtGslvHQutWolrWAdsWMhuWsou20rt2kns2UismYitWgksGMfr2IdtGcit2omuWsps2UkuWkrvG0voWEhm1ocnl0gpGElpGAlqWEoq2QqqWYqsG4yrWsvrWsvmlgboV0itG82sGszpWUrpGYqqGgtqGguo2Mpnl0kqGYvrWo1qmc0qWMypV8tpWErpGEppWIpoV0mq2YxtG07tGw8pV0tnVQkqWEwrGY1rGU1qGAwn1gmoVoopl8tpmArllAbo10or2k0rGUzo1sqpV0trWU1tW09rmUyp10oqV8ntGswqmIkqGEfr2olvXgzqWQfs20nxHw2sGgir2chrWQcu3Aor2Qbr2MXqV0QsWYYtWocuG0fsmcbtWogsWUdrWIaql8ZuHAru3QwuHEuvXYzwHg1vHIwu28tum0rtmgluGwotm4or2kjtW8ormggrmYeqGAatm0ownQxs2MitGQkwHEwsGIgsmQitGYjtGYjtWgkuGsosGUgtGokuG8psmcjr2EfsmQitmgnum4ttmkosWMisWMhtWcktmkltGgjtmkkuGsmt2onsmQjuWorvG0vomIimlkaomAiqWUppF4iolkgrGYspmMos3I3sXE2s3I4ol4lm1YdrWgvsW40rm40pmgupGcsomMppmctoF4mp2QtrWg0q2QyqV8upF0qol0nqGMspWEoo18nrmk1tW8+tW8/qWIyoVooq2YyrWg2q2Y0qWMxolwqolsppl8tqWMwm1QioFkmrGYzq2MxpF0rpF0rpl4us2w6rWUxqF8qrGQru3I4rGMmqWIhsmwptXArpV4asGolxH03sGgirmYesGYetmwkrmMbrmMXr2QXr2UXtGoctmwes2kctGwfrWQZq2EYo1oTtW8qvngztW8rvHYzwHk2u3Mwt2wqum0rsmQhtWgluHAquHAquHEqsGkgsGggp18Xp14YvnIuuWoouGgov3EvsWQir2MhsWMhtWcktmglu20qtWgktGcjt2sms2cjrmAesmUjsWYmuW0utWcorl8gr2AetWckt2sntWoltmgluGoot2kntWYlu2wtvGwvpmYmllYWn10esm0vo10foVkeqWMoqGYtomMqvX9GwH9IrGcwnlkgqmYsrm4ysnI3qmoxoGAmomIopmQroF0lp2Mrr2k0rWUyplwqoVgmo1smqWEsp2EqoFsmsGs5sm49qmU2r2s6qmYyrGk0rGk2qmY0qWUzol4sn1knolwqqWMxnVYkoFgmrGQyqF8soVknpF0rqGAvrGUzqmIuqGArsGgwvXQ5sWgrq2MktG4rtnAso1wZr2cjvncxsWkir2YesWgfsWgftm0jtmshtWofq2IUsGcZuG8hrmUXs2sdrmYbq2EYpFwVtnArvHcyunQwvXc0wHk2wXo3uG4svnEut2kms2Yit2wouXEru3MtsmoismsirmceoFcPu28qvnAsumspu24ssWUjsWUismQhtWcktWYjt2gltWYjs2Yium4quGonr2Eer2MftWsptmwrsGMjr2AesGEes2YhtGojsmgisWQhvW8tuWspsWEjuGgrvW0xpWUlk1IRmlgYs24upl8gpFwgpF0jqmkwomQu1JVf0pBctXA7qmUurGovrm8xr20zq2YvoVwkp2IpqGMqo14lqWQrsGs1r2gzpV0qnlUiolgkq2ItqWMtmlUiqWUzs3A/tHFBsG08sG46snA8rGo2qWc0qWc0oV4snFgmol0rqWIwpV0rolknt248rWQxoVkmqGEurGUzsGk3q2MvqWErrmYttGwws2otrmcntG0tu3Qyo1wZqF8cwHgyuG8psGYesWgermUatmwiu3EntWofpl4QrmYYt28hrGQWsWkcs2sgr2YdrWUfunUwu3YxtW8ruHIvwnw5wns4vnQyv3IvuGontWcksGUhvXMuunErtG0ksmshs2who1oRtmwkum0oumwpum4rrWMhsWUitWckuGonsmQhsmIgtGUismMhuGontWcjtGYgr2Ufs2wmsmomr2MfsGIds2QesmUdtW0is2wjql0bu2wsuWsrrF0ft2cru2swo2Mjk1MTmFUWrmkpp2Aho1sfol0ipGQqqWs12JhlzYtZsm46sW02rGkvrGwuq2ctrGMrpl0lqGIprGYto10mpmEqrGkyrGgzol0pm1Mfn1Qgs2k1rWcymVMgpGAuuHVFtnREuXdFtnZCsnI+rWw4qmk2qWg1oV0qm1cko14sqmUzqmMxolootGw6rWQwnlUhp18srmc1rmc1qGAtqmIsrmYts2svsWottGsttWwtt28upl4boloVuHAquXApt24ks2sermMYtWsgvHIouG8krmYYrWUXs2sdqmMVs2wguXEntGwksWkiuXMuu3UwvXYztm8swHo3wXo3wXg1vHEtuGwnsmUgrGEcwHUwvXMtsmsirmcetm8kp18VsWgeuW8num4ouG8rqF8crGIetWomvW8ttWYlsWEgtGQjsGAftWYktGUgtGcftGkhtGwls2slrGAbql0WtGYetWoft3AitG0irGAfuGorvG0vrV0gtmcsvW80pGQnl1cal1QYqWQmp2Ajolwgol8jpWMps3M6yopUtHM+pGItpmMtpmMrrWoxqmUqq2MoqmEoqGEpqmIso1wnqGItsGw3rWo1oV8pm1cgoFkgs2w1sWs1mVYhn10quHZFt3VEt3dGs3NBqmk4rGo4rms4qmYyoFwnmlUho10pqmQyp2Ixn1oprWc2q2IwnFIfp18srmg2qGMxp2Euq2Mvq2ItrmQtsWcutm0ytm4xunEwrGIdoFcNuG8luG8luW8ltGkfsWMZuWsfum8ju3EksGcZqmETsWgarGMWtGsgunEnuXAotm0nt28rvXQww3o2tWwovXYyvngzwnw1vHMrum4mtGcfsGQcvXMrvnUttW0ls2sjt28mqmEZrGMau3Epu3AquW8urGQkp18dsGYkuGwqu20stmcns2Qkrl4dsWIer2EZtmgftmkitmomtm0orWMeo1kSrmUcs2sgtW8itG0jrmQhuG4svG8vrV8isGMovXI3pGUpnF0hmFYao18ipV4hoVwepGEjqGYprm4ytHM6p2cupGQromAoqWYurWkvrGctrmctrWYtpmEop2Eppl8pqWUus3A5r202o2EqnFkgpV8lsm00tnM8nlslqGYytnRDtHJCtnVFuHhJs3FCsW49s289qGQwnVkknVcipmArrWg1q2c1oFwrq2Y2q2Mwn1YipFwprGUzpl8trWYzrGUwp14oplwkrWMruXI4t3E0uXAurmQeo1sQs2sftm0jt20jrmIYsWIXt2keum4huW4gsGYYrmQWs2kbrmMXs2ogvnQsu3Equ3EsuG8quW8qw3g0vHIuvHUwu3YwxYA5unIqu28mtGces2cfv3UtvXQstGwks2sjtm4mqGAYqWEZvHIqvHEqvXMwtm0srWUhrmYhtGomum4rtWgns2UjrV8csGIdrV8XsGMZtGcgtGgks2klrmUhpFwVrWYcsGgeuG8mtm4nrmcitGonuWwsrmEisWUovXQ5omMnnl8inFwepGEjpmAgn1sZpWMhq2opsG8xsnI2qmsxpmcsoWAlrGovrGktsGsxrGYtqmUsp2MppWIoqGQqrGgvtHE4rWozol8onloipmAms200tXE6qmcxr2w4uXdFunhIt3ZItHRGu3pNt3VEuXZFq2c0mVYhm1YhpWArrmo2sWw6o14tqmQ0qF8toFYip10qrWQyp2AtqmQwq2UvqWIrpl0lrGMrt3A1tG0wunEwr2Uep14Ts2oftm4krmUbrWIYsmQat2ketmoeum4hs2kcsmgbtmsgrmQZr2UcvXMrvHIsvXIttW0ns2klwHUxwXYyv3cywHs1xH04unEru28ot2kjsmYfu3EqvXMss2sjsGghs2skqWEaqmIbuG0mum8pu3EuvnQxtGsksmkitWsltGkltWkmtWglrWAcsWQermIYrWIXsWUes2gjtGklrmQfpFsVrWQcsGYdtmsjunAqs2sltGoluWwptGUlt2osvHI1omImnV4hnVwdo14fq2Ukol0Zol8aqWckqWkou3w+sXI2qWktqGcrs3A1s280s283tHE6rWsxo2ImomEjoWAjr20wtnM4sG00pGApol4lpmEnqmUrs243sGs1u3hDu3lIyYhXxoZYrW5Cqmo+uXhJwoFQqGc0l1UgnlslpWIrsGw2sm05oFspp2EvqF8sqV4qq2EsqmEtp2ArrGYwrGYwrGYvq2Qrr2Yts2wyuXI1s2wprmYfpl0Ts2ohuXEoqV8WrWEYsmQbum0it2sftmofs2gcsmcdtWogsGQbr2UdvHEsvXItuW4puG8pt20nu3Arv3UxvnYyvXczwHk0v3Yxu28qvG8qtmoluW4pvnQvt28ptm4osWkkrGQfr2Yhum8rt2wouW8rvHMut20ltGoit20mt2wos2glsGQhrF8bsWUfsWcdrGQZrmUes2kktGkltGkkp1wXqF0WtWkhtWgjt2smtGsms2gktGYktGUluGoru28xpWUonFwdnlwcoVwbq2Qhp2Idol8apGIfpWMjwYBCtHU5o2InpWInuHQ5t3I3tHE5uHdArm40nl8jn18gn18esXAxuHU5uHM6p2Eqol0lqWQrp2Ipsm00rmoyt3M/sW89woFRz5BjtXZNrG1DuHpL0JFgtXVClVQgo2EspGEqq2YwtW86qGItpV0rqF4pq2EsrGMtpF0noFokrGYwrGcvrWgvr2gvr2gvs2wztm8ztGwqsGciqF8Wsmkgt28np14WrWIatGceum0jum4jsGMatGkfsmYdsmYetWkhsWYgum8qu3ArtGoktm4muW4ntmwlvXItv3cxvXYyvnczwnk1um8ruWwotWomuW4qv3Uxu3IuuG8rsmkltWwor2YiuW4qtGkluG0pv3QvuG4msWcgt20mu3AstmsosmYkrGAer2QgrWQcrGUcs2sktGsnsmcjs2cjrF8ap1wUtmkitmgjtWgktGkltGgksWIfsWMgtWgmuG0sqGcqnl4enFsan1oZqGEeqmQhq2ckpmMinVodsm81t3Y9oF4lnFkgsWwzt3E4tXI6snA5q2wxnF0goGAhomIir24tt3Q2tXE2n1kioFskrGcuqWQrr2oxsGw1tHE7r206v35O3p5zyYtit3pRuHxO1ZdnwYNRnl0qomArpGEqpF8ptW85rWcyoVsmp14pr2YwrWUvpV4ooVkjq2UtrmgvrWcusGkxsGgys2w0tG4ytGwsrmYhp18XsGkht3Eppl4YrGIatGgftmoft2sfrmIYtWkgtGghrmEbuWwnsmciuW4nu3Ept20muHAou3EpsmcgvHEqw3k0wXs1u3QwuXAtum8st2kntmomu3AswXczu3IuuXAssmkluXAstGomt2wotGkltmsowHUxum8qsmcjtGkku28suWwssWQlrmEhrWIfq2EbrWUduHAqtWsnr2QgsWUhsmQfrF8ZtWgjt2gltmkmsWYks2Ykr2EesGEerWAdtmwppmYoomEgn1wboVwbqGEfrGUks24urWksnFkfqWguuHY/qGYvpGEqqWYttXE4s284r201rGowpWQppWQno2IkrWwuuHU6sW00o14on1kkrmkyrmkxrGcur2wzunhBtXNAvX1N1pds0pRsyItjv4JX1JZpw4RUpWUzo2EtqGUwo18pqmUvq2YxnVcio1smr2cxrmYwo1sloFgiqWErrmcwsGkxs2ozsmkzsmszsmswuHAwrGQfp18Ys2wkuXMrqGEbq2Iar2MbtWkfu24jr2IZsmYeum4nsmQgum0ps2citWojt20kt20lvHQswHcvs2gfum8nv3YvvXYwv3k0uXEtu3EutmontWomu3Asv3UxvHMvtWwosmklt24qt24quW4qt2wotGknuW0ruG0psmcjsWYit2sruWwusWMlr2Eir2EgrWMdrGIatmsmtmonr2IgrWActGcisWQfvG4quGonumsrs2cmsmUjsWMgrmAcr2IduW8q]]
FILE: [[images/processing/rotation/rotation-tests.factor]] [[! Copyright (C) 2009 Kobi Lurie, Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors fry images.loader
images.processing.rotation kernel literals math sequences
tools.test images.processing.rotation.private ;
IN: images.processing.rotation.tests
: first-row ( seq^2 -- seq ) first ;
: first-col ( seq^2 -- item ) harvest [ first ] map ;
: last-row ( seq^2 -- item ) last ;
: last-col ( seq^2 -- item ) harvest [ last ] map ;
: end-of-first-row ( seq^2 -- item ) first-row last ;
: first-of-first-row ( seq^2 -- item ) first-row first ;
: end-of-last-row ( seq^2 -- item ) last-row last ;
: first-of-last-row ( seq^2 -- item ) last-row first ;
<<
: clone-image ( image -- new-image )
clone [ clone ] change-bitmap ;
>>
: pasted-image ( -- image )
"vocab:images/processing/rotation/test-bitmaps/PastedImage.bmp"
load-image clone-image ;
: pasted-image90 ( -- image )
"vocab:images/processing/rotation/test-bitmaps/PastedImage90.bmp"
load-image clone-image ;
: lake-image ( -- image )
"vocab:images/processing/rotation/test-bitmaps/lake.bmp"
load-image clone-image image>pixel-rows ;
[ t ] [ pasted-image dup clone-image 4 [ 90 rotate ] times = ] unit-test
[ t ] [ pasted-image dup clone-image 2 [ 180 rotate ] times = ] unit-test
[ t ] [ pasted-image dup clone-image 270 rotate 90 rotate = ] unit-test
[ t ] [
pasted-image dup clone-image dup { 90 180 90 } [ rotate drop ] with each =
] unit-test
[ t ] [
pasted-image 90 rotate
pasted-image90 =
] unit-test
[ t ] [
"vocab:images/processing/rotation/test-bitmaps/small.bmp"
load-image 90 rotate
"vocab:images/processing/rotation/test-bitmaps/small-rotated.bmp"
load-image =
] unit-test
[ t ] [
lake-image
[ first-of-first-row ]
[ 90 (rotate) end-of-first-row ] bi =
] unit-test
[ t ]
[ lake-image [ first-row ] [ 90 (rotate) last-col ] bi = ] unit-test
[ t ]
[ lake-image [ last-col ] [ 90 (rotate) last-row reverse ] bi = ] unit-test
[ t ]
[ lake-image [ last-row ] [ 90 (rotate) first-col ] bi = ] unit-test
[ t ]
[ lake-image [ first-col ] [ 90 (rotate) first-row reverse ] bi = ] unit-test
]]
FILE: [[images/processing/rotation/authors.txt]] [[Kobi Lurie
Doug Coleman
]]
FILE: [[images/jpeg/jpeg.factor]] [[! Copyright (C) 2009 Marc Fauconneau.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays byte-arrays combinators
compression.huffman fry grouping images images.loader
images.processing io io.binary io.encodings.binary
io.streams.byte-array io.streams.limited io.streams.throwing
kernel locals math math.bitwise math.blas.matrices
math.blas.vectors math.constants math.functions math.matrices
math.order math.vectors memoize namespaces sequences
sequences.deep ;
QUALIFIED-WITH: bitstreams bs
IN: images.jpeg
SINGLETON: jpeg-image
TUPLE: loading-jpeg < image
{ headers }
{ bitstream }
{ color-info initial: { f f f f } }
{ quant-tables initial: { f f } }
{ huff-tables initial: { f f f f } }
{ components } ;
{ "jpg" "jpeg" } [ jpeg-image ?register-image-class ] each
<PRIVATE
: <loading-jpeg> ( headers bitstream -- image )
loading-jpeg new swap >>bitstream swap >>headers ;
SINGLETONS: SOF DHT DAC RST SOI EOI SOS DQT DNL DRI DHP EXP
APP JPG COM TEM RES ;
! ISO/IEC 10918-1 Table B.1
:: >marker ( byte -- marker )
byte
{
{ [ dup 0xCC = ] [ { DAC } ] }
{ [ dup 0xC4 = ] [ { DHT } ] }
{ [ dup 0xC9 = ] [ { JPG } ] }
{ [ dup -4 shift 0xC = ] [ SOF byte 4 bits 2array ] }
{ [ dup 0xD8 = ] [ { SOI } ] }
{ [ dup 0xD9 = ] [ { EOI } ] }
{ [ dup 0xDA = ] [ { SOS } ] }
{ [ dup 0xDB = ] [ { DQT } ] }
{ [ dup 0xDC = ] [ { DNL } ] }
{ [ dup 0xDD = ] [ { DRI } ] }
{ [ dup 0xDE = ] [ { DHP } ] }
{ [ dup 0xDF = ] [ { EXP } ] }
{ [ dup -4 shift 0xD = ] [ RST byte 4 bits 2array ] }
{ [ dup -4 shift 0xE = ] [ APP byte 4 bits 2array ] }
{ [ dup 0xFE = ] [ { COM } ] }
{ [ dup -4 shift 0xF = ] [ JPG byte 4 bits 2array ] }
{ [ dup 0x01 = ] [ { TEM } ] }
[ { RES } ]
}
cond nip ;
TUPLE: jpeg-chunk length type data ;
: <jpeg-chunk> ( type length data -- jpeg-chunk )
jpeg-chunk new
swap >>data
swap >>length
swap >>type ;
TUPLE: jpeg-color-info
h v quant-table dc-huff-table ac-huff-table { diff initial: 0 } id ;
: <jpeg-color-info> ( h v quant-table -- jpeg-color-info )
jpeg-color-info new
swap >>quant-table
swap >>v
swap >>h ;
: jpeg> ( -- jpeg-image ) jpeg-image get ;
: apply-diff ( dc color -- dc' )
[ diff>> + dup ] [ diff<< ] bi ;
: fetch-tables ( component -- )
[ [ jpeg> quant-tables>> nth ] change-quant-table drop ]
[ [ jpeg> huff-tables>> nth ] change-dc-huff-table drop ]
[ [ 2 + jpeg> huff-tables>> nth ] change-ac-huff-table drop ] tri ;
: read4/4 ( -- a b ) read1 16 /mod ;
! headers
: decode-frame ( header -- )
data>>
binary
[
read1 8 assert=
2 read be>
2 read be>
swap 2array jpeg> dim<<
read1
[
read1 read4/4 read1 <jpeg-color-info>
swap [ >>id ] keep jpeg> color-info>> set-nth
] times
] with-byte-reader ;
: decode-quant-table ( chunk -- )
dup data>>
binary
[
length>>
2 - 65 /
[
read4/4 [ 0 assert= ] dip
64 read
swap jpeg> quant-tables>> set-nth
] times
] with-byte-reader ;
: decode-huff-table ( chunk -- )
data>> [ binary <byte-reader> ] [ length ] bi limit-stream [
[ input-stream get stream>> [ count>> ] [ limit>> ] bi < ]
[
read4/4 swap 2 * +
16 read
dup [ ] [ + ] map-reduce read
binary [ [ read [ B{ } ] unless* ] { } map-as ] with-byte-reader
swap jpeg> huff-tables>> set-nth
] while
] stream-throw-on-eof ;
: decode-scan ( chunk -- )
data>>
binary
[
read1 <iota>
[ drop
read1 jpeg> color-info>> nth clone
read1 16 /mod [ >>dc-huff-table ] [ >>ac-huff-table ] bi*
] map jpeg> components<<
read1 0 assert=
read1 63 assert=
read1 16 /mod [ 0 assert= ] bi@
] with-byte-reader ;
: singleton-first ( seq -- elt )
[ length 1 assert= ] [ first ] bi ;
ERROR: not-a-baseline-jpeg-image ;
: baseline-parse ( -- )
jpeg> headers>> [ type>> { SOF 0 } = ] any? [ not-a-baseline-jpeg-image ] unless
jpeg> headers>>
{
[ [ type>> { SOF 0 } = ] filter singleton-first decode-frame ]
[ [ type>> { DQT } = ] filter [ decode-quant-table ] each ]
[ [ type>> { DHT } = ] filter [ decode-huff-table ] each ]
[ [ type>> { SOS } = ] filter singleton-first decode-scan ]
} cleave ;
: parse-marker ( -- marker )
read1 0xFF assert=
read1 >marker ;
: parse-headers ( -- chunks )
[ parse-marker dup { SOS } = not ]
[
2 read be>
dup 2 - read <jpeg-chunk>
] [ produce ] keep dip swap suffix ;
MEMO: zig-zag ( -- zz )
{
{ 0 1 5 6 14 15 27 28 }
{ 2 4 7 13 16 26 29 42 }
{ 3 8 12 17 25 30 41 43 }
{ 9 11 18 24 31 40 44 53 }
{ 10 19 23 32 39 45 52 54 }
{ 20 22 33 38 46 51 55 60 }
{ 21 34 37 47 50 56 59 61 }
{ 35 36 48 49 57 58 62 63 }
} flatten ;
MEMO: yuv>bgr-matrix ( -- m )
{
{ 1 2.03211 0 }
{ 1 -0.39465 -0.58060 }
{ 1 0 1.13983 }
} ;
: wave ( x u -- n ) swap 2 * 1 + * pi * 16 / cos ;
:: dct-vect ( u v -- basis )
{ 8 8 } coord-matrix [ { u v } [ wave ] 2map product ] map^2
1 u v [ 0 = [ 2 sqrt / ] when ] bi@ 4 / m*n ;
MEMO: dct-matrix ( -- m ) 64 <iota> [ 8 /mod dct-vect flatten ] map ;
: mb-dim ( component -- dim ) [ h>> ] [ v>> ] bi 2array ;
! : blocks ( component -- seq )
! mb-dim ! coord-matrix flip concat [ [ { 2 2 } v* ] [ v+ ] bi* ] with map ;
: all-macroblocks ( quot: ( mb -- ) -- )
[
jpeg>
[ dim>> 8 v/n ]
[ color-info>> sift { 0 0 } [ mb-dim vmax ] reduce v/ ] bi
[ ceiling ] map
coord-matrix flip concat
]
[ each ] bi* ; inline
: reverse-zigzag ( b -- b' ) zig-zag swap [ nth ] curry map ;
: idct-factor ( b -- b' ) dct-matrix v.m ;
MEMO: dct-matrix-blas ( -- m ) dct-matrix >float-blas-matrix ;
: V.M ( x A -- x.A ) Mtranspose swap M.V ;
: idct-blas ( b -- b' ) >float-blas-vector dct-matrix-blas V.M ;
: idct ( b -- b' ) idct-factor ;
:: draw-block ( block x,y color-id jpeg-image -- )
block dup length>> sqrt >fixnum group flip
dup matrix-dim coord-matrix flip
[
[ '[ _ [ second ] [ first ] bi ] dip nth nth ]
[ x,y v+ color-id jpeg-image draw-color ] bi
] with each^2 ;
: sign-extend ( bits v -- v' )
swap [ ] [ 1 - 2^ < ] 2bi
[ -1 swap shift 1 + + ] [ drop ] if ;
: read1-jpeg-dc ( decoder -- dc )
[ read1-huff dup ] [ bs>> bs:read ] bi sign-extend ;
: read1-jpeg-ac ( decoder -- run/ac )
[ read1-huff 16 /mod dup ] [ bs>> bs:read ] bi sign-extend 2array ;
:: decode-block ( color -- pixels )
color dc-huff-table>> read1-jpeg-dc color apply-diff
64 0 <array> :> coefs
0 coefs set-nth
0 :> k!
[
color ac-huff-table>> read1-jpeg-ac
[ first 1 + k + k! ] [ second k coefs set-nth ] [ ] tri
{ 0 0 } = not
k 63 < and
] loop
coefs color quant-table>> v*
reverse-zigzag idct ;
:: draw-macroblock-yuv420 ( mb blocks -- )
mb { 16 16 } v* :> pos
0 blocks nth pos { 0 0 } v+ 0 jpeg> draw-block
1 blocks nth pos { 8 0 } v+ 0 jpeg> draw-block
2 blocks nth pos { 0 8 } v+ 0 jpeg> draw-block
3 blocks nth pos { 8 8 } v+ 0 jpeg> draw-block
4 blocks nth 8 group 2 matrix-zoom concat pos 1 jpeg> draw-block
5 blocks nth 8 group 2 matrix-zoom concat pos 2 jpeg> draw-block ;
:: draw-macroblock-yuv444 ( mb blocks -- )
mb { 8 8 } v* :> pos
3 <iota> [ [ blocks nth pos ] [ jpeg> draw-block ] bi ] each ;
:: draw-macroblock-y ( mb blocks -- )
mb { 8 8 } v* :> pos
0 blocks nth pos 0 jpeg> draw-block
64 0 <array> pos 1 jpeg> draw-block
64 0 <array> pos 2 jpeg> draw-block ;
! %fixme: color hack
! color h>> 2 =
! [ 8 group 2 matrix-zoom concat ] unless
! pos { 8 8 } v* color jpeg> draw-block ;
: decode-macroblock ( -- blocks )
jpeg> components>>
[
[ mb-dim first2 * ]
[ [ decode-block ] curry replicate ] bi
] map concat ;
: cleanup-bitstream ( bytes -- bytes' )
binary [
[
{ 0xFF } read-until
read1 [ 0x00 = and ] keep swap
]
[ drop ] produce
swap >marker { EOI } assert=
swap suffix
{ 0xFF } join
] with-byte-reader ;
: setup-bitmap ( image -- )
dup dim>> 16 v/n [ ceiling ] map 16 v*n >>dim
BGR >>component-order
ubyte-components >>component-type
f >>upside-down?
dup dim>> first2 * 3 * 0 <array> >>bitmap
drop ;
ERROR: unsupported-colorspace ;
SINGLETONS: YUV420 YUV444 Y MAGIC! ;
:: detect-colorspace ( jpeg-image -- csp )
jpeg-image color-info>> sift :> colors
MAGIC!
colors length 1 = [ drop Y ] when
colors length 3 =
[
colors [ mb-dim { 1 1 } = ] all?
[ drop YUV444 ] when
colors unclip
[ [ mb-dim { 1 1 } = ] all? ]
[ mb-dim { 2 2 } = ] bi* and
[ drop YUV420 ] when
] when ;
! this eats ~50% cpu time
: draw-macroblocks ( mbs -- )
jpeg> detect-colorspace
{
{ YUV420 [ [ first2 draw-macroblock-yuv420 ] each ] }
{ YUV444 [ [ first2 draw-macroblock-yuv444 ] each ] }
{ Y [ [ first2 draw-macroblock-y ] each ] }
[ unsupported-colorspace ]
} case ;
! this eats ~25% cpu time
: color-transform ( yuv -- rgb )
{ 128 0 0 } v+ yuv>bgr-matrix swap m.v
[ 0 max 255 min >fixnum ] map ;
: baseline-decompress ( -- )
jpeg> bitstream>> cleanup-bitstream { 255 255 255 255 } append
>byte-array bs:<msb0-bit-reader> jpeg> bitstream<<
jpeg>
[ bitstream>> ]
[ [ [ <huffman-decoder> ] with map ] change-huff-tables drop ] bi
jpeg> components>> [ fetch-tables ] each
[ decode-macroblock 2array ] collector
[ all-macroblocks ] dip
jpeg> setup-bitmap draw-macroblocks
jpeg> bitmap>> 3 <groups> [ color-transform ] map! drop
jpeg> [ >byte-array ] change-bitmap drop ;
ERROR: not-a-jpeg-image ;
: loading-jpeg>image ( loading-jpeg -- image )
dup jpeg-image [
baseline-parse
baseline-decompress
] with-variable ;
: load-jpeg ( stream -- loading-jpeg )
[
parse-marker { SOI } = [ not-a-jpeg-image ] unless
parse-headers
contents <loading-jpeg>
] with-input-stream ;
PRIVATE>
M: jpeg-image stream>image ( stream jpeg-image -- bitmap )
drop load-jpeg loading-jpeg>image ;
]]
FILE: [[ori/ori-tests.factor]] [[IN: ori.tests
USING: ori tools.test ;
\ pitch-up must-infer
\ pitch-down must-infer
\ turn-left must-infer
\ turn-right must-infer
\ roll-left must-infer
\ roll-right must-infer
]]
FILE: [[ori/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[ori/ori.factor]] [[
USING: kernel namespaces make accessors
math math.constants math.functions math.matrices math.vectors
sequences splitting grouping self math.trig ;
IN: ori
TUPLE: ori val ;
C: <ori> ori
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: ori> ( -- val ) self> val>> ;
: >ori ( val -- ) self> val<< ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: make-matrix ( quot width -- matrix ) [ { } make ] dip group ; inline
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! These rotation matrices are from
! `Computer Graphics: Principles and Practice'
: Rz ( angle -- Rx ) deg>rad
[ dup cos , dup sin neg , 0 ,
dup sin , dup cos , 0 ,
0 , 0 , 1 , ] 3 make-matrix nip ;
: Ry ( angle -- Ry ) deg>rad
[ dup cos , 0 , dup sin ,
0 , 1 , 0 ,
dup sin neg , 0 , dup cos , ] 3 make-matrix nip ;
: Rx ( angle -- Rz ) deg>rad
[ 1 , 0 , 0 ,
0 , dup cos , dup sin neg ,
0 , dup sin , dup cos , ] 3 make-matrix nip ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: apply-rotation ( rotation -- ) ori> swap m. >ori ;
: rotate-x ( angle -- ) Rx apply-rotation ;
: rotate-y ( angle -- ) Ry apply-rotation ;
: rotate-z ( angle -- ) Rz apply-rotation ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: pitch-up ( angle -- ) neg rotate-x ;
: pitch-down ( angle -- ) rotate-x ;
: turn-left ( angle -- ) rotate-y ;
: turn-right ( angle -- ) neg rotate-y ;
: roll-left ( angle -- ) neg rotate-z ;
: roll-right ( angle -- ) rotate-z ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! roll-until-horizontal
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: V ( -- V ) { 0 1 0 } ;
: X ( -- 3array ) ori> [ first ] map ;
: Y ( -- 3array ) ori> [ second ] map ;
: Z ( -- 3array ) ori> [ third ] map ;
: set-X ( seq -- ) ori> [ set-first ] 2each ;
: set-Y ( seq -- ) ori> [ set-second ] 2each ;
: set-Z ( seq -- ) ori> [ set-third ] 2each ;
: roll-until-horizontal ( -- )
V Z cross normalize set-X
Z X cross normalize set-Y ;
]]
FILE: [[triggers/triggers.factor]] [[! Copyright (C) 2008 Alex Chapman
! See http://factorcode.org/license.txt for BSD license.
USING: assocs digraphs kernel namespaces sequences ;
IN: triggers
: triggers ( -- triggers )
\ triggers global [ drop H{ } clone ] cache ;
: trigger-graph ( trigger -- graph )
triggers [ drop <digraph> ] cache ;
: reset-trigger ( trigger -- )
<digraph> swap triggers set-at ;
: add-trigger ( key quot trigger -- )
! trigger should be a symbol. Note that symbols with the same name but
! different vocab are not equal
trigger-graph add-vertex ;
: before ( key1 key2 trigger -- )
trigger-graph add-edge ;
: after ( key1 key2 trigger -- )
swapd before ;
: call-trigger ( trigger -- )
trigger-graph topological-sorted-values [ call ] each ;
]]
FILE: [[triggers/summary.txt]] [[triggers allow you to register code to be 'triggered'
]]
FILE: [[triggers/authors.txt]] [[Alex Chapman
]]
FILE: [[triggers/triggers-tests.factor]] [[USING: triggers kernel tools.test ;
IN: triggers.tests
SYMBOL: test-trigger
test-trigger reset-trigger
: add-test-trigger test-trigger add-trigger ;
[ ] [ test-trigger call-trigger ] unit-test
[ "op called" ] [ "op" [ "op called" ] add-test-trigger test-trigger call-trigger ] unit-test
[ "first called" "second called" ] [
test-trigger reset-trigger
"second op" [ "second called" ] add-test-trigger
"first op" [ "first called" ] add-test-trigger
test-trigger call-trigger
] unit-test
]]
FILE: [[ldap/ldap.factor]] [[! Copyright (C) 2007 Elie CHAFTARI
! See http://factorcode.org/license.txt for BSD license.
!
! Tested with OpenLDAP 2.2.7.0.21 on Mac OS X 10.4.9 PowerPC
USING: alien alien.c-types assocs continuations hashtables io kernel
ldap.libldap math namespaces sequences ;
IN: ldap
SYMBOL: message
SYMBOL: ldp
! =========================================================
! Error interpretation routines
! =========================================================
: result-to-error ( ld res freeit -- num )
ldap_result2error ;
: err-to-string ( err -- str )
ldap_err2string ;
: check-result ( result -- )
dup zero? [ drop ] [
err-to-string throw
] if ;
: result-type ( result -- )
result-types >hashtable at print ;
! =========================================================
! Initialization routines
! =========================================================
! deprecated in favor of ldap_initialize
: open ( host port -- ld )
ldap_open ;
! deprecated in favor of ldap_initialize
: init ( host port -- ld )
ldap_init ;
: initialize ( ld url -- )
dupd ldap_initialize swap *void* ldp set check-result ;
: get-option ( ld option outvalue -- )
ldap_get_option check-result ;
: set-option ( ld option invalue -- )
ldap_set_option check-result ;
! =========================================================
! Bind operations
! =========================================================
: simple-bind ( ld who passwd -- id )
ldap_simple_bind ;
: simple-bind-s ( ld who passwd -- )
ldap_simple_bind_s check-result ;
: unbind-s ( ld -- )
ldap_unbind_s check-result ;
: with-bind ( ld who passwd quot -- )
-roll [ simple-bind-s [ ldp get unbind-s ] [ ] cleanup ] with-scope ; inline
! =========================================================
! Search operations
! =========================================================
: search ( ld base scope filter attrs attrsonly -- id )
ldap_search ;
: search-s ( ld base scope filter attrs attrsonly res -- )
ldap_search_s check-result ;
! =========================================================
! Return results of asynchronous operation routines
! =========================================================
: result ( ld msgid all timeout result -- )
[ ldap_result ] keep *void* message set result-type ;
: parse-result ( ld result errcodep matcheddnp errmsgp referralsp serverctrlsp freeit -- )
ldap_parse_result check-result ;
: count-messages ( ld result -- count )
ldap_count_messages ;
: first-message ( ld result -- message )
ldap_first_message ;
: next-message ( ld message -- message )
ldap_next_message ;
: msgtype ( msg -- num )
ldap_msgtype ;
: msgid ( msg -- num )
ldap_msgid ;
: count-entries ( ld result -- count )
ldap_count_entries ;
: first-entry ( ld result -- entry )
ldap_first_entry ;
: next-entry ( ld entry -- entry )
ldap_next_entry ;
: first-attribute ( ld entry berptr -- str )
ldap_first_attribute ;
: next-attribute ( ld entry ber -- str )
ldap_next_attribute ;
: get-values ( ld entry attr -- values )
ldap_get_values ;
: get-dn ( ld entry -- str )
ldap_get_dn ;
! =========================================================
! Public routines
! =========================================================
: get-message ( -- message )
message get ;
: get-ldp ( -- ldp )
ldp get ;
]]
FILE: [[ldap/ldap-tests.factor]] [[USING: alien alien.c-types io kernel ldap ldap.libldap
namespaces prettyprint tools.test ;
IN: ldap.tests
"void*" <c-object> "ldap://localhost:389" initialize
get-ldp LDAP_OPT_PROTOCOL_VERSION LDAP_VERSION3 <int> set-option
[ 3 ] [
get-ldp LDAP_OPT_PROTOCOL_VERSION "int*" <c-object> [ get-option ] keep
*int
] unit-test
[
get-ldp "cn=jimbob,dc=example,dc=com" "secret" [
! get-ldp "dc=example,dc=com" LDAP_SCOPE_ONELEVEL "(objectclass=*)" f 0
! "void*" <c-object> [ search-s ] keep *int .
[ 2 ] [
get-ldp "dc=example,dc=com" LDAP_SCOPE_SUBTREE "(objectclass=*)" f 0
search
] unit-test
! get-ldp LDAP_RES_ANY 0 f "void*" <c-object> result .
get-ldp LDAP_RES_ANY LDAP_MSG_ALL f "void*" <c-object> result
! get-message *int .
"Message ID: " write
get-message msgid .
get-ldp get-message get-dn .
"Entries count: " write
get-ldp get-message count-entries .
SYMBOL: entry
SYMBOL: attr
"Attribute: " write
get-ldp get-message first-entry entry set get-ldp entry get
"void*" <c-object> first-attribute dup . attr set
"Value: " write
get-ldp entry get attr get get-values *char* .
get-ldp get-message first-message msgtype result-type
get-ldp get-message next-message msgtype result-type
] with-bind
] drop
]]
FILE: [[ldap/summary.txt]] [[OpenLDAP binding
]]
FILE: [[ldap/libldap/libldap.factor]] [[! Copyright (C) 2007 Elie CHAFTARI
! See http://factorcode.org/license.txt for BSD license.
!
! Tested with OpenLDAP 2.2.7.0.21 on Mac OS X 10.4.9 PowerPC
!
! export LD_LIBRARY_PATH=/opt/local/lib
USING: alien alien.syntax combinators kernel system ;
IN: ldap.libldap
<< "libldap" {
{ [ win32? ] [ "libldap.dll" stdcall ] }
{ [ macosx? ] [ "libldap.dylib" cdecl ] }
{ [ unix? ] [ "libldap.so" cdecl ] }
} cond add-library >>
: LDAP_VERSION1 1 ; inline
: LDAP_VERSION2 2 ; inline
: LDAP_VERSION3 3 ; inline
: LDAP_VERSION_MIN LDAP_VERSION2 ; inline
: LDAP_VERSION LDAP_VERSION2 ; inline
: LDAP_VERSION_MAX LDAP_VERSION3 ; inline
: LDAP_PORT 389 ; inline ! ldap:/// default LDAP port
: LDAPS_PORT 636 ; inline ! ldaps:/// default LDAP over TLS port
: LDAP_SCOPE_BASE 0x0000 ; inline
: LDAP_SCOPE_BASEOBJECT LDAP_SCOPE_BASE ; inline
: LDAP_SCOPE_ONELEVEL 0x0001 ; inline
: LDAP_SCOPE_ONE LDAP_SCOPE_ONELEVEL ; inline
: LDAP_SCOPE_SUBTREE 0x0002 ; inline
: LDAP_SCOPE_SUB LDAP_SCOPE_SUBTREE ; inline
: LDAP_SCOPE_SUBORDINATE 0x0003 ; inline ! OpenLDAP extension
: LDAP_SCOPE_CHILDREN LDAP_SCOPE_SUBORDINATE ; inline
: LDAP_SCOPE_DEFAULT -1 ; inline ! OpenLDAP extension
: LDAP_RES_ANY -1 ; inline
: LDAP_RES_UNSOLICITED 0 ; inline
! how many messages to retrieve results for
: LDAP_MSG_ONE 0x00 ; inline
: LDAP_MSG_ALL 0x01 ; inline
: LDAP_MSG_RECEIVED 0x02 ; inline
! the possible result types returned
: LDAP_RES_BIND 0x61 ; inline
: LDAP_RES_SEARCH_ENTRY 0x64 ; inline
: LDAP_RES_SEARCH_REFERENCE 0x73 ; inline
: LDAP_RES_SEARCH_RESULT 0x65 ; inline
: LDAP_RES_MODIFY 0x67 ; inline
: LDAP_RES_ADD 0x69 ; inline
: LDAP_RES_DELETE 0x6b ; inline
: LDAP_RES_MODDN 0x6d ; inline
: LDAP_RES_COMPARE 0x6f ; inline
: LDAP_RES_EXTENDED 0x78 ; inline
: LDAP_RES_EXTENDED_PARTIAL 0x79 ; inline
: result-types ( -- seq ) {
{ 0x61 "LDAP_RES_BIND" }
{ 0x64 "LDAP_RES_SEARCH_ENTRY" }
{ 0x73 "LDAP_RES_SEARCH_REFERENCE" }
{ 0x65 "LDAP_RES_SEARCH_RESULT" }
{ 0x67 "LDAP_RES_MODIFY" }
{ 0x69 "LDAP_RES_ADD" }
{ 0x6b "LDAP_RES_DELETE" }
{ 0x6d "LDAP_RES_MODDN" }
{ 0x6f "LDAP_RES_COMPARE" }
{ 0x78 "LDAP_RES_EXTENDED" }
{ 0x79 "LDAP_RES_EXTENDED_PARTIAL" }
} ;
: LDAP_OPT_PROTOCOL_VERSION 0x0011 ; inline
C-STRUCT: ldap
{ "char" "ld_lberoptions" }
{ "int" "ld_deref" }
{ "int" "ld_timelimit" }
{ "int" "ld_sizelimit" }
{ "int" "ld_errno" }
{ "char*" "ld_error" }
{ "char*" "ld_matched" }
{ "int" "ld_refhoplimit" }
{ "ulong" "ld_options" } ;
LIBRARY: libldap
! ===============================================
! ldap.h
! ===============================================
! Will be depreciated in a later release (ldap_init() is preferred)
FUNCTION: void* ldap_open ( char* host, int port ) ;
FUNCTION: void* ldap_init ( char* host, int port ) ;
FUNCTION: int ldap_initialize ( ldap* ld, char* url ) ;
FUNCTION: int ldap_get_option ( void* ld, int option, void* outvalue ) ;
FUNCTION: int ldap_set_option ( void* ld, int option, void* invalue ) ;
FUNCTION: int ldap_simple_bind ( void* ld, char* who, char* passwd ) ;
FUNCTION: int ldap_simple_bind_s ( void* ld, char* who, char* passwd ) ;
FUNCTION: int ldap_unbind_s ( void* ld ) ;
FUNCTION: int ldap_result2error ( void* ld, void* res, int freeit ) ;
FUNCTION: char* ldap_err2string ( int err ) ;
FUNCTION: int ldap_search ( void* ld, char* base, int scope, char* filter,
char* attrs, int attrsonly ) ;
FUNCTION: int ldap_search_s ( void* ld, char* base, int scope, char* filter,
char* attrs, int attrsonly, void* res ) ;
FUNCTION: int ldap_result ( void* ld, int msgid, int all, void* timeout,
void* result ) ;
FUNCTION: int ldap_parse_result ( void* ld, void* result, int* errcodep,
char* matcheddnp, char* errmsgp,
char* referralsp, void* serverctrlsp,
int freeit ) ;
FUNCTION: int ldap_count_messages ( void* ld, void* result ) ;
FUNCTION: void* ldap_first_message ( void* ld, void* result ) ;
FUNCTION: void* ldap_next_message ( void* ld, void* message ) ;
FUNCTION: int ldap_msgtype ( void* msg ) ;
FUNCTION: int ldap_msgid ( void* msg ) ;
FUNCTION: int ldap_count_entries ( void* ld, void* result ) ;
FUNCTION: void* ldap_first_entry ( void* ld, void* result ) ;
FUNCTION: void* ldap_next_entry ( void* ld, void* entry ) ;
FUNCTION: char* ldap_first_attribute ( void* ld, void* entry, void* berptr ) ;
FUNCTION: char* ldap_next_attribute ( void* ld, void* entry, void* ber ) ;
FUNCTION: char** ldap_get_values ( void* ld, void* entry, char* attr ) ;
FUNCTION: char* ldap_get_dn ( void* ld, void* entry ) ;
]]
FILE: [[ldap/libldap/authors.txt]] [[Elie Chaftari
]]
FILE: [[ldap/libldap/tags.txt]] [[bindings
]]
FILE: [[ldap/authors.txt]] [[Elie Chaftari
]]
FILE: [[ldap/conf/createdit.ldif]] [[# this is a comment # MUST be in FIRST column - very picky
## DEFINE DIT ROOT/BASE/SUFFIX ####
## uses RFC 2377 format
## replace example and com as necessary below
## or for experimentation leave as is
## dcObject is an AUXILLIARY objectclass and MUST
## have a STRUCTURAL objectclass (organization in this case)
# this is an ENTRY sequence and is preceded by a BLANK line
dn: dc=example,dc=com
dc: example
description: My wonderful company as much text as you want to place in this line up to 32K
continuation data for the line above must have &lt;CR> or &lt;CR>&lt;LF> i.e. ENTER works
on both Windows and *nix system - new line MUST begin with ONE SPACE
objectClass: dcObject
objectClass: organization
o: Example, Inc.
## FIRST Level hierarchy - people
## uses mixed upper and lower case for objectclass
# this is an ENTRY sequence and is preceded by a BLANK line
dn: ou=people, dc=example,dc=com
ou: people
description: All people in organisation
objectclass: organizationalunit
## SECOND Level hierarchy
## ADD a single entry under FIRST (people) level
# this is an ENTRY sequence and is preceded by a BLANK line
# the ou: Human Resources is the department name
dn: cn=Robert Forest,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: Robert Forest
sn: Forest
uid: 0
userpassword: rForest
carlicense: HISCAR 123
homephone: 555-111-2222
mail: r.forest@example.com
description: swell guy
# ou: Human Resources]]
FILE: [[ldap/conf/slapd.conf]] [[#
###### SAMPLE 1 - SIMPLE DIRECTORY ############
#
# NOTES: inetorgperson picks up attributes and objectclasses
# from all three schemas
#
# NB: RH Linux schemas in /etc/openldap
#
include /opt/local/etc/openldap/schema/core.schema
include /opt/local/etc/openldap/schema/cosine.schema
include /opt/local/etc/openldap/schema/inetorgperson.schema
# NO SECURITY - no access clause
# defaults to anonymous access for read
# only rootdn can write
# NO REFERRALS
# DON'T bother with ARGS file unless you feel strongly
# slapd scripts stop scripts need this to work
pidfile /opt/local/var/run/run/slapd.pid
# enable a lot of logging - we might need it
# but generates huge logs
loglevel -1
# NO dynamic backend modules
# NO TLS-enabled connections
# backend definition not required
#######################################################################
# bdb database definitions
#
# replace example and com below with a suitable domain
#
# If you don't have a domain you can leave it since example.com
# is reserved for experimentation or change them to my and inc
#
#######################################################################
database bdb
suffix "dc=example, dc=com"
# root or superuser
rootdn "cn=jimbob, dc=example, dc=com"
rootpw secret
# The database directory MUST exist prior to running slapd AND
# change path as necessary
directory /opt/local/var/run/openldap-data
# Indices to maintain for this directory
# unique id so equality match only
index uid eq
# allows general searching on commonname, givenname and email
index cn,gn,mail eq,sub
# allows multiple variants on surname searching
index sn eq,sub,subany,subfinal
# optimise department searches
index ou eq
# shows use of default index parameter
index default eq,sub
# indices missing - uses default eq,sub
index telephonenumber
]]
FILE: [[ldap/conf/addentry.ldif]] [[## ADD a single entry to people level
dn: cn=John Spider,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: John Spider
sn: Spider
uid: 1
userpassword: jSpider
carlicense: HISCAR 124
homephone: 555-111-2223
mail: j.spider@example.com
# ou: Sales
## ADD another single entry to people level
dn: cn=Sheri Matsumo,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: Sheri Matsumo
sn: Matsumo
uid: 2
userpassword: sMatsumo
carlicense: HERCAR 125
homephone: 555-111-2225
mail: s.matsumo@example.com
# ou: IT]]
FILE: [[ldap/tags.txt]] [[enterprise
network
]]
FILE: [[4DNav/4DNav-docs.factor]] base64[[ISBDb3B5cmlnaHQgKEMpIDIwMDggSmVhbi1GcmFu529pcyBCaWdvdC4KISBTZWUgaHR0cDovL2ZhY3RvcmNvZGUub3JnL2xpY2Vuc2UudHh0IGZvciBCU0QgbGljZW5zZS4KVVNJTkc6IGhlbHAubWFya3VwIGhlbHAuc3ludGF4IGtlcm5lbCBxdW90YXRpb25zIHN0cmluZ3MgOwpJTjogNEROYXYKCgpIRUxQOiBtZW51LTNECnsgJHZhbHVlcwogICAgIHsgImdhZGdldCIgImdhZGdldCIgfQp9CnsgJGRlc2NyaXB0aW9uICJUaGUgbWVudSBkZWRpY2F0ZWQgdG8gM0QgbW92ZW1lbnRzIG9mIHRoZSBjYW1lcmEiIH0gOwoKSEVMUDogbWVudS00RAp7ICR2YWx1ZXMKICAgIAogICAgIHsgImdhZGdldCIgImdhZGdldCIgfQp9CnsgJGRlc2NyaXB0aW9uICJUaGUgbWVudSBkZWRpY2F0ZWQgdG8gNEQgbW92ZW1lbnRzIG9mIHNwYWNlIiB9IDsKCkhFTFA6IG1lbnUtYmFyCnsgJHZhbHVlcwogICAgCiAgICAgeyAiZ2FkZ2V0IiAiZ2FkZ2V0IiB9Cn0KeyAkZGVzY3JpcHRpb24gInJldHVybiBnYWRnZXQgY29udGFpbmluZyBtZW51IGJ1dHRvbnMiIH0gOwoKSEVMUDogbW9kZWwtcHJvamVjdGlvbgp7ICR2YWx1ZXMKICAgICB7ICJ4IiAiaW50ZXJnZXIiIH0KICAgICB7ICJzcGFjZSIgInNwYWNlIiB9Cn0KeyAkZGVzY3JpcHRpb24gIlByb2plY3Qgc3BhY2UgZm9sbG93aW5nIGNvb3JkaW5hdGUgeCIgfSA7CgpIRUxQOiBtdnQtM0QtMQp7ICR2YWx1ZXMKICAgIAogICAgIHsgInF1b3QiICJxdW90YXRpb24iIH0KfQp7ICRkZXNjcmlwdGlvbiAicmV0dXJuIGEgcXVvdGF0aW9uIHRvIG9yaWVudGF0ZSBzcGFjZSB0byBzZWUgaXQgZnJvbSBmaXJzdCBwb2ludCBvZiB2aWV3IiB9IDsKCkhFTFA6IG12dC0zRC0yCnsgJHZhbHVlcwogICAgCiAgICAgeyAicXVvdCIgInF1b3RhdGlvbiIgfQp9CnsgJGRlc2NyaXB0aW9uICJyZXR1cm4gYSBxdW90YXRpb24gdG8gb3JpZW50YXRlIHNwYWNlIHRvIHNlZSBpdCBmcm9tIHNlY29uZCBwb2ludCBvZiB2aWV3IiB9IDsKCkhFTFA6IG12dC0zRC0zCnsgJHZhbHVlcwogICAgCiAgICAgeyAicXVvdCIgInF1b3RhdGlvbiIgfQp9CnsgJGRlc2NyaXB0aW9uICJyZXR1cm4gYSBxdW90YXRpb24gdG8gb3JpZW50YXRlIHNwYWNlIHRvIHNlZSBpdCBmcm9tIHRoaXJkIHBvaW50IG9mIHZpZXciIH0gOwoKSEVMUDogbXZ0LTNELTQKeyAkdmFsdWVzCiAgICAKICAgICB7ICJxdW90IiAicXVvdGF0aW9uIiB9Cn0KeyAkZGVzY3JpcHRpb24gInJldHVybiBhIHF1b3RhdGlvbiB0byBvcmllbnRhdGUgc3BhY2UgdG8gc2VlIGl0IGZyb20gZmlyc3QgcG9pbnQgb2YgdmlldyIgfSA7CgpIRUxQOiBsb2FkLW1vZGVsLWZpbGUKeyAkZGVzY3JpcHRpb24gImxvYWQgc3BhY2UgZnJvbSBmaWxlIiB9IDsKCkhFTFA6IHJvdGF0aW9uLTRECnsgJHZhbHVlcwogICAgIHsgIm0iICJhIHJvdGF0aW9uIG1hdHJpeCIgfQp9CnsgJGRlc2NyaXB0aW9uICJBcHBseSBhIDREIHJvdGF0aW9uIG1hdHJpeCIgfSA7CgpIRUxQOiB0cmFuc2xhdGlvbi00RAp7ICR2YWx1ZXMKICAgICB7ICJ2IiAidmVjdG9yIiB9Cn0KeyAkZGVzY3JpcHRpb24gIkFwcGx5IGEgNEQgdHJhbnNsYXRpb24iIH0gOwoKCkFSVElDTEU6ICJpbXBsZW1lbnRhdGlvbiBkZXRhaWxzIiAiSG93IDRETmF2IGlzIGRvbmUiCiI0RE5hdiBpcyBidWlsZCB1c2luZyA6IgoKeyAkc3Vic2VjdGlvbnMKICAgICI0RE5hdi5jYW1lcmEiCiAgICAiYWRzb2RhLW1haW4tcGFnZSIKfQo7CgpBUlRJQ0xFOiAiU3BhY2UgZmlsZSIgIkNyZWF0ZSBhIG5ldyBzcGFjZSBmaWxlIgoiVG8gYnVpbGQgYSBuZXcgc3BhY2UsIGNyZWF0ZSBhbiBYTUwgZmlsZSB1c2luZyAiIHsgJHZvY2FiLWxpbmsgImFkc29kYSIgfSAiIG1vZGVsIGRlc2NyaXB0aW9uLiBBIHNvbGlkIGlzIG5vdCBjYXJhY3Rlcml6ZWQgYnkgaXRzIGNvcm5lcnMgYnV0IGlzIGRlZmluZWQgYXMgdGhlIGludGVyc2VjdGlvbiBvZiBoeXBlcnBsYW5lcy4iCgokbmwKIkFuIGV4YW1wbGUgaXM6Igp7ICRjb2RlICIiIgo8bW9kZWw+CjxzcGFjZT4KIDxkaW1lbnNpb24+NDwvZGltZW5zaW9uPgogPHNvbGlkPgogICAgIDxuYW1lPjRjdWJlMTwvbmFtZT4KICAgICA8ZGltZW5zaW9uPjQ8L2RpbWVuc2lvbj4KICAgICA8ZmFjZT4xLDAsMCwwLDEwMDwvZmFjZT4KICAgICA8ZmFjZT4tMSwwLDAsMCwtMTUwPC9mYWNlPgogICAgIDxmYWNlPjAsMSwwLDAsMTAwPC9mYWNlPgogICAgIDxmYWNlPjAsLTEsMCwwLC0xNTA8L2ZhY2U+CiAgICAgPGZhY2U+MCwwLDEsMCwxMDA8L2ZhY2U+CiAgICAgPGZhY2U+MCwwLC0xLDAsLTE1MDwvZmFjZT4KICAgICA8ZmFjZT4wLDAsMCwxLDEwMDwvZmFjZT4KICAgICA8ZmFjZT4wLDAsMCwtMSwtMTUwPC9mYWNlPgogICAgIDxjb2xvcj4xLDAsMDwvY29sb3I+CiA8L3NvbGlkPgogPHNvbGlkPgogICAgIDxuYW1lPjR0cmlhbmN1YmU8L25hbWU+CiAgICAgPGRpbWVuc2lvbj40PC9kaW1lbnNpb24+CiAgICAgPGZhY2U+MSwwLDAsMCwxNjA8L2ZhY2U+CiAgICAgPGZhY2U+LTAuNDk5OTk5OTk5OTk5OTk5OCwtMC44NjYwMjU0MDM3ODQ0Mzg3LDAsMCwtMTMwPC9mYWNlPgogICAgIDxmYWNlPi0wLjUwMDAwMDAwMDAwMDAwMDQsMC44NjYwMjU0MDM3ODQ0Mzg0LDAsMCwtMTMwPC9mYWNlPgogICAgIDxmYWNlPjAsMCwxLDAsMTQwPC9mYWNlPgogICAgIDxmYWNlPjAsMCwtMSwwLC0xODA8L2ZhY2U+CiAgICAgPGZhY2U+MCwwLDAsMSwxMTA8L2ZhY2U+CiAgICAgPGZhY2U+MCwwLDAsLTEsLTE4MDwvZmFjZT4KICAgICA8Y29sb3I+MCwxLDA8L2NvbG9yPgogPC9zb2xpZD4KIDxzb2xpZD4KICAgICA8bmFtZT50cmlhbmdvbmU8L25hbWU+CiAgICAgPGRpbWVuc2lvbj40PC9kaW1lbnNpb24+CiAgICAgPGZhY2U+MSwwLDAsMCw2MDwvZmFjZT4KICAgICA8ZmFjZT4wLjUsMC44NjYwMjU0MDM3ODQ0Mzg2LDAsMCw2MDwvZmFjZT4KICAgICA8ZmFjZT4tMC41LDAuODY2MDI1NDAzNzg0NDM4NywwLDAsLTIwPC9mYWNlPgogICAgIDxmYWNlPi0xLjAsMCwwLDAsLTEwMDwvZmFjZT4KICAgICA8ZmFjZT4tMC41LC0wLjg2NjAyNTQwMzc4NDQzODQsMCwwLC0xMDA8L2ZhY2U+CiAgICAgPGZhY2U+MC41LC0wLjg2NjAyNTQwMzc4NDQzODcsMCwwLC0yMDwvZmFjZT4KICAgICA8ZmFjZT4wLDAsMSwwLDEyMDwvZmFjZT4KICAgICA8ZmFjZT4wLDAsLTAuNDk5OTk5OTk5OTk5OTk5OCwtMC44NjYwMjU0MDM3ODQ0Mzg3LC0xMjA8L2ZhY2U+CiAgICAgPGZhY2U+MCwwLC0wLjUwMDAwMDAwMDAwMDAwMDQsMC44NjYwMjU0MDM3ODQ0Mzg0LC0xMjA8L2ZhY2U+CiAgICAgPGNvbG9yPjAsMSwxPC9jb2xvcj4KIDwvc29saWQ+CiA8bGlnaHQ+CiAgICAgPGRpcmVjdGlvbj4xLDEsMSwxPC9kaXJlY3Rpb24+CiAgICAgPGNvbG9yPjAuMiwwLjIsMC42PC9jb2xvcj4KIDwvbGlnaHQ+CiA8Y29sb3I+MC44LDAuOSwwLjk8L2NvbG9yPgo8L3NwYWNlPgo8L21vZGVsPiIiIiB9IDsKCkFSVElDTEU6ICJUT0RPIiAiVG9kbyIKeyAkbGlzdCAKICAgICJBIHZvY2FiIHRvIGluaXRpYWxpemUgcGFyYW1ldGVycyIKICAgICJhbiBlZGl0b3IgbW9kZSIgCiAgICAgICAgeyAkbGlzdCAiYWRkIGEgZmFjZSB0byBhIHNvbGlkIgogICAgICAgICAgICAgICAgImFkZCBhIHNvbGlkIHRvIHRoZSBzcGFjZSIKICAgICAgICAgICAgICAgICJtb3ZlIGEgZmFjZSIKICAgICAgICAgICAgICAgICJtb3ZlIGEgc29saWQiCiAgICAgICAgICAgICAgICAic2VsZWN0IGEgc29saWQgaW4gYSBsaXN0IgogICAgICAgICAgICAgICAgInNlbGVjdCBhIGZhY2UiCiAgICAgICAgICAgICAgICAiZGlzcGxheSBzZWxlY3RlZCBmYWNlIgogICAgICAgICAgICAgICAgImVkaXQgYSBzb2xpZCBjb2xvciIKICAgICAgICAgICAgICAgICJhZGQgYSBsaWdodCIKICAgICAgICAgICAgICAgICJlZGl0IGEgbGlnaHQgY29sb3IiCiAgICAgICAgICAgICAgICAibW92ZSBhIGxpZ2h0IgogICAgICAgICAgICAgICAgfQogICAgImFkZCBhIHRvb2wgd2ljaCBnaXZlIGFuIGh5cGVycGxhbmUgbm9ybWFsIHZlY3RvciB3aXRoIGVub3VnaHQgcG9pbnRzLiBXaWxsIHVzZSBhZHNvZGEuaW50ZXJzZWN0LWh5cGVycGxhbmVzIHdpdGggeyB7IDAgfSB7IDAgfSB7IDEgfSB9ICIKICAgICJkZWNvcnJlbGF0ZSAzRCBjYW1lcmEgYW5kIGFjdGl2YXRlIHRoZW0gd2l0aCBzZWxlY3QgYnV0dG9ucyIKCn0gOwoKCkFSVElDTEU6ICI0RE5hdiIgIlRoZSA0RE5hdiBhcHAiCnsgJHZvY2FiLWxpbmsgIjRETmF2IiB9CiRubAp7ICRoZWFkaW5nICI0RCBOYXZpZ2F0b3IiIH0KIjRETmF2IGlzIGEgc2ltcGxlIHRvb2wgdG8gdmlzdWFsaXplIDQgZGltZW5zaW9ubmFsIG9iamVjdHMuIgokbmwKIkl0IHVzZXMgIiB7ICR2b2NhYi1saW5rICJhZHNvZGEiIH0gIiBsaWJyYXJ5IHRvIGRpc3BsYXkgYSA0RCBzcGFjZSBhbmQgbmF2aWdhdGUgdGhydSBpdC4iCiRubAoiSXQgd2lsbCBkaXNwbGF5OiIKeyAkbGlzdAogICAgeyAiYSBtZW51IHdpbmRvdyIgfQogICAgeyAgIjQgdmlzdWFsaXphdGlvbiB3aW5kb3dzIiB9Cn0KIkVhY2ggdmlzdWFsaXphdGlvbiB3aW5kb3cgcmVwcmVzZW50cyB0aGUgcHJvamVjdGlvbiBvZiB0aGUgNEQgc3BhY2Ugb24gYSBwYXJ0aWN1bGFyIDNEIHNwYWNlLiIKCnsgJGhlYWRpbmcgIlN0YXJ0IiB9CiJ0eXBlOiIgeyAkY29kZSAiXCI0RE5hdlwiIHJ1biIgfSAKCnsgJGhlYWRpbmcgIk5hdmlnYXRpb24iIH0KIk1lbnUgd2luZG93IGlzIGRpdmlkZWQgaW4gNCBhcmVhcyIKeyAkbGlzdAogICAgeyAiYSBzcGFjZS1maWxlIGNob29zZXIgdG8gc2VsZWN0IHRoZSBmaWxlIHRvIGRpc3BsYXkiIH0KICAgIHsgImEgcGFyYW1ldHJpemF0aW9uIGFyZWEgdG8gc2VsZWN0IHRoZSBwcm9qZWN0aW9uIG1vZGUiIH0KICAgIHsgIjREIHN1Ym1lbnUgdG8gdHJhbnNsYXRlIGFuZCByb3RhdGUgdGhlIDREIHNwYWNlIiB9CiAgICB7ICIzRCBzdWJtZW51IHRvIG1vdmUgdGhlIGNhbWVyYSBpbiAzRCBzcGFjZS4gQ2FtZXJhcyBpbiBldmVyeSAzRCBzcGFjZXMgYXJlIG1hbmlwdWxhdGVkIGFzIGEgc2luZ2xlIG9uZSIgfQogICAgfQoKeyAkaGVhZGluZyAiTGlua3MiIH0KeyAkc3Vic2VjdGlvbnMKICAgICJTcGFjZSBmaWxlIgogICAgIlRPRE8iCiAgICAiaW1wbGVtZW50YXRpb24gZGV0YWlscyIKfQoKOwoKQUJPVVQ6ICI0RE5hdiIK]]
FILE: [[4DNav/turtle/turtle.factor]] [[USING: kernel math arrays math.vectors math.matrices namespaces make
math.constants math.functions splitting grouping math.trig sequences
accessors 4DNav.deep models vars ;
IN: 4DNav.turtle
! replacement of self
VAR: self
: with-self ( quot obj -- ) [ >self call ] with-scope ; inline
: save-self ( quot -- ) self> [ self> clone >self call ] dip >self ; inline
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: turtle pos ori ;
: <turtle> ( -- turtle )
turtle new
{ 0 0 0 } clone >>pos
3 identity-matrix >>ori
;
TUPLE: observer < turtle projection-mode collision-mode ;
: <observer> ( -- object )
observer new
0 <model> >>projection-mode
f <model> >>collision-mode
;
: turtle-pos> ( -- val ) self> pos>> ;
: >turtle-pos ( val -- ) self> pos<< ;
: turtle-ori> ( -- val ) self> ori>> ;
: >turtle-ori ( val -- ) self> ori<< ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! These rotation matrices are from
! `Computer Graphics: Principles and Practice'
! waiting for deep-cleave-quots
! : Rz ( angle -- Rx ) deg>rad
! { { [ cos ] [ sin neg ] 0 }
! { [ sin ] [ cos ] 0 }
! { 0 0 1 }
! } deep-cleave-quots ;
! : Ry ( angle -- Ry ) deg>rad
! { { [ cos ] 0 [ sin ] }
! { 0 1 0 }
! { [ sin neg ] 0 [ cos ] }
! } deep-cleave-quots ;
! : Rx ( angle -- Rz ) deg>rad
! { { 1 0 0 }
! { 0 [ cos ] [ sin neg ] }
! { 0 [ sin ] [ cos ] }
! } deep-cleave-quots ;
: Rz ( angle -- Rx ) deg>rad
[ dup cos , dup sin neg , 0 ,
dup sin , dup cos , 0 ,
0 , 0 , 1 , ] 3 make-matrix nip ;
: Ry ( angle -- Ry ) deg>rad
[ dup cos , 0 , dup sin ,
0 , 1 , 0 ,
dup sin neg , 0 , dup cos , ] 3 make-matrix nip ;
: Rx ( angle -- Rz ) deg>rad
[ 1 , 0 , 0 ,
0 , dup cos , dup sin neg ,
0 , dup sin , dup cos , ] 3 make-matrix nip ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: apply-rotation ( rotation -- )
turtle-ori> swap m. >turtle-ori ;
: rotate-x ( angle -- ) Rx apply-rotation ;
: rotate-y ( angle -- ) Ry apply-rotation ;
: rotate-z ( angle -- ) Rz apply-rotation ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: pitch-up ( angle -- ) neg rotate-x ;
: pitch-down ( angle -- ) rotate-x ;
: turn-left ( angle -- ) rotate-y ;
: turn-right ( angle -- ) neg rotate-y ;
: roll-left ( angle -- ) neg rotate-z ;
: roll-right ( angle -- ) rotate-z ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! roll-until-horizontal
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: V ( -- V ) { 0 1 0 } ;
: X ( -- 3array ) turtle-ori> [ first ] map ;
: Y ( -- 3array ) turtle-ori> [ second ] map ;
: Z ( -- 3array ) turtle-ori> [ third ] map ;
: set-X ( seq -- ) turtle-ori> [ set-first ] 2each ;
: set-Y ( seq -- ) turtle-ori> [ set-second ] 2each ;
: set-Z ( seq -- ) turtle-ori> [ set-third ] 2each ;
: roll-until-horizontal ( -- )
V Z cross normalize set-X
Z X cross normalize set-Y ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: distance ( turtle turtle -- n )
pos>> swap pos>> v- [ sq ] map-sum sqrt ;
: move-by ( point -- ) turtle-pos> v+ >turtle-pos ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: reset-turtle ( -- )
{ 0 0 0 } clone >turtle-pos 3 identity-matrix >turtle-ori ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: step-vector ( length -- array ) { 0 0 1 } n*v ;
: step-turtle ( length -- )
step-vector turtle-ori> swap m.v
turtle-pos> v+ >turtle-pos ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: strafe-up ( length -- )
90 pitch-up
step-turtle
90 pitch-down ;
: strafe-down ( length -- )
90 pitch-down
step-turtle
90 pitch-up ;
: strafe-left ( length -- )
90 turn-left
step-turtle
90 turn-right ;
: strafe-right ( length -- )
90 turn-right
step-turtle
90 turn-left ;
]]
FILE: [[4DNav/turtle/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[4DNav/turtle/turtle-docs.factor]] base64[[ISBDb3B5cmlnaHQgKEMpIDIwMDggSmVhbi1GcmFuw6dvaXMgQmlnb3QuCiEgU2VlIGh0dHA6Ly9mYWN0b3Jjb2RlLm9yZy9saWNlbnNlLnR4dCBmb3IgQlNEIGxpY2Vuc2UuClVTSU5HOiBhcnJheXMgaGVscC5tYXJrdXAgaGVscC5zeW50YXgga2VybmVsIHNlcXVlbmNlcyA7CklOOiA0RE5hdi50dXJ0bGUKCgpBUlRJQ0xFOiAiNEROYXYudHVydGxlIiAiVHVydGxlIgp7ICR2b2NhYi1saW5rICI0RE5hdi50dXJ0bGUiIH0KOwoKQUJPVVQ6ICI0RE5hdi50dXJ0bGUiCg==]]
FILE: [[4DNav/4DNav.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING: kernel
namespaces
accessors
assocs
make
math
math.functions
math.trig
math.parser
hashtables
sequences
combinators
continuations
colors
colors.constants
prettyprint
vars
quotations
io
io.directories
io.pathnames
help.markup
io.files
ui.gadgets.panes
ui
ui.gadgets
ui.traverse
ui.gadgets.borders
ui.gadgets.frames
ui.gadgets.tracks
ui.gadgets.labels
ui.gadgets.labeled
ui.gadgets.lists
ui.gadgets.buttons
ui.gadgets.packs
ui.gadgets.grids
ui.gadgets.corners
ui.gestures
ui.gadgets.scrollers
splitting
vectors
math.vectors
values
4DNav.turtle
4DNav.window3D
4DNav.deep
4DNav.space-file-decoder
models
fry
adsoda
adsoda.tools
;
QUALIFIED-WITH: ui.pens.solid s
QUALIFIED-WITH: ui.gadgets.wrappers w
IN: 4DNav
VALUE: selected-file
VALUE: translation-step
VALUE: rotation-step
3 \ translation-step set-value
5 \ rotation-step set-value
VAR: selected-file-model
VAR: observer3d
VAR: view1
VAR: view2
VAR: view3
VAR: view4
VAR: present-space
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! namespace utilities
: closed-quot ( quot -- quot )
namestack swap '[ namestack [ _ set-namestack @ ] dip set-namestack ] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! waiting for deep-cleave-quots
: 4D-Rxy ( angle -- Rx ) deg>rad
[ 1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , 1.0 , 0.0 , 0.0 ,
0.0 , 0.0 , dup cos , dup sin neg ,
0.0 , 0.0 , dup sin , dup cos , ] 4 make-matrix nip ;
: 4D-Rxz ( angle -- Ry ) deg>rad
[ 1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , dup cos , 0.0 , dup sin neg ,
0.0 , 0.0 , 1.0 , 0.0 ,
0.0 , dup sin , 0.0 , dup cos , ] 4 make-matrix nip ;
: 4D-Rxw ( angle -- Rz ) deg>rad
[ 1.0 , 0.0 , 0.0 , 0.0 ,
0.0 , dup cos , dup sin neg , 0.0 ,
0.0 , dup sin , dup cos , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 , ] 4 make-matrix nip ;
: 4D-Ryz ( angle -- Rx ) deg>rad
[ dup cos , 0.0 , 0.0 , dup sin neg ,
0.0 , 1.0 , 0.0 , 0.0 ,
0.0 , 0.0 , 1.0 , 0.0 ,
dup sin , 0.0 , 0.0 , dup cos , ] 4 make-matrix nip ;
: 4D-Ryw ( angle -- Ry ) deg>rad
[ dup cos , 0.0 , dup sin neg , 0.0 ,
0.0 , 1.0 , 0.0 , 0.0 ,
dup sin , 0.0 , dup cos , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 , ] 4 make-matrix nip ;
: 4D-Rzw ( angle -- Rz ) deg>rad
[ dup cos , dup sin neg , 0.0 , 0.0 ,
dup sin , dup cos , 0.0 , 0.0 ,
0.0 , 0.0 , 1.0 , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 , ] 4 make-matrix nip ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! UI
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: button* ( string quot -- button )
closed-quot <repeat-button> ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: model-projection-chooser ( -- gadget )
observer3d> projection-mode>>
{ { 1 "perspective" } { 0 "orthogonal" } }
<radio-buttons> ;
: collision-detection-chooser ( -- gadget )
observer3d> collision-mode>>
{ { t "on" } { f "off" } } <radio-buttons> ;
: model-projection ( x -- space )
present-space> swap space-project ;
: update-observer-projections ( -- )
view1> relayout-1
view2> relayout-1
view3> relayout-1
view4> relayout-1 ;
: update-model-projections ( -- )
0 model-projection <model> view1> model<<
1 model-projection <model> view2> model<<
2 model-projection <model> view3> model<<
3 model-projection <model> view4> model<< ;
: camera-action ( quot -- quot )
'[ drop _ observer3d>
with-self update-observer-projections ]
closed-quot ;
: win3D ( text gadget -- )
"navigateur 4D : " rot append open-window ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 4D object manipulation
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: (mvt-4D) ( quot -- )
present-space>
swap call space-ensure-solids
>present-space
update-model-projections
update-observer-projections ; inline
: rotation-4D ( m -- )
'[ _ [ [ middle-of-space dup vneg ] keep
swap space-translate ] dip
space-transform
swap space-translate
] (mvt-4D) ;
: translation-4D ( v -- ) '[ _ space-translate ] (mvt-4D) ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! menu
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: menu-rotations-4D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
<pile> 1 >>fill
"XY +" [ drop rotation-step 4D-Rxy rotation-4D ]
button* add-gadget
"XY -" [ drop rotation-step neg 4D-Rxy rotation-4D ]
button* add-gadget
@top-left grid-add
<pile> 1 >>fill
"XZ +" [ drop rotation-step 4D-Rxz rotation-4D ]
button* add-gadget
"XZ -" [ drop rotation-step neg 4D-Rxz rotation-4D ]
button* add-gadget
@top grid-add
<pile> 1 >>fill
"YZ +" [ drop rotation-step 4D-Ryz rotation-4D ]
button* add-gadget
"YZ -" [ drop rotation-step neg 4D-Ryz rotation-4D ]
button* add-gadget
@center grid-add
<pile> 1 >>fill
"XW +" [ drop rotation-step 4D-Rxw rotation-4D ]
button* add-gadget
"XW -" [ drop rotation-step neg 4D-Rxw rotation-4D ]
button* add-gadget
@top-right grid-add
<pile> 1 >>fill
"YW +" [ drop rotation-step 4D-Ryw rotation-4D ]
button* add-gadget
"YW -" [ drop rotation-step neg 4D-Ryw rotation-4D ]
button* add-gadget
@right grid-add
<pile> 1 >>fill
"ZW +" [ drop rotation-step 4D-Rzw rotation-4D ]
button* add-gadget
"ZW -" [ drop rotation-step neg 4D-Rzw rotation-4D ]
button* add-gadget
@bottom-right grid-add
;
: menu-translations-4D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
<pile> 1 >>fill
<shelf> 1 >>fill
"X+" [ drop { 1 0 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
"X-" [ drop { -1 0 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
"YZW" <label> add-gadget
@bottom-right grid-add
<pile> 1 >>fill
"XZW" <label> add-gadget
<shelf> 1 >>fill
"Y+" [ drop { 0 1 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
"Y-" [ drop { 0 -1 0 0 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
@top-right grid-add
<pile> 1 >>fill
"XYW" <label> add-gadget
<shelf> 1 >>fill
"Z+" [ drop { 0 0 1 0 } translation-step v*n
translation-4D ]
button* add-gadget
"Z-" [ drop { 0 0 -1 0 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
@top-left grid-add
<pile> 1 >>fill
<shelf> 1 >>fill
"W+" [ drop { 0 0 0 1 } translation-step v*n
translation-4D ]
button* add-gadget
"W-" [ drop { 0 0 0 -1 } translation-step v*n
translation-4D ]
button* add-gadget
add-gadget
"XYZ" <label> add-gadget
@bottom-left grid-add
"X" <label> @center grid-add
;
: menu-4D ( -- gadget )
<shelf>
"rotations" <label> add-gadget
menu-rotations-4D add-gadget
"translations" <label> add-gadget
menu-translations-4D add-gadget
0.5 >>align
{ 0 10 } >>gap
;
! ------------------------------------------------------
: redraw-model ( space -- )
>present-space
update-model-projections
update-observer-projections ;
: load-model-file ( -- )
selected-file dup selected-file-model> set-model
read-model-file
redraw-model ;
: mvt-3D-X ( turn pitch -- quot )
'[ turtle-pos> norm neg reset-turtle
_ turn-left
_ pitch-up
step-turtle ] ;
: mvt-3D-1 ( -- quot ) 90 0 mvt-3D-X ; inline
: mvt-3D-2 ( -- quot ) 0 90 mvt-3D-X ; inline
: mvt-3D-3 ( -- quot ) 0 0 mvt-3D-X ; inline
: mvt-3D-4 ( -- quot ) 45 45 mvt-3D-X ; inline
: camera-button ( string quot -- button )
[ <label> ] dip camera-action <repeat-button> ;
! ----------------------------------------------------------
! file chooser
! ----------------------------------------------------------
: <run-file-button> ( file-name -- button )
dup '[ drop _ \ selected-file set-value load-model-file
]
closed-quot <roll-button> { 0 0 } >>align ;
: <list-runner> ( -- gadget )
"resource:extra/4DNav"
<pile> 1 >>fill
over dup directory-files
[ ".xml" tail? ] filter
[ append-path ] with map
[ <run-file-button> add-gadget ] each
swap <labeled-gadget> ;
! -----------------------------------------------------
: menu-rotations-3D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
"Turn\n left" [ rotation-step turn-left ]
camera-button @left grid-add
"Turn\n right" [ rotation-step turn-right ]
camera-button @right grid-add
"Pitch down" [ rotation-step pitch-down ]
camera-button @bottom grid-add
"Pitch up" [ rotation-step pitch-up ]
camera-button @top grid-add
<shelf> 1 >>fill
"Roll left\n (ctl)" [ rotation-step roll-left ]
camera-button add-gadget
"Roll right\n(ctl)" [ rotation-step roll-right ]
camera-button add-gadget
@center grid-add
;
: menu-translations-3D ( -- gadget )
3 3 <frame>
{ 1 1 } >>filled-cell
"left\n(alt)" [ translation-step strafe-left ]
camera-button @left grid-add
"right\n(alt)" [ translation-step strafe-right ]
camera-button @right grid-add
"Strafe up \n (alt)" [ translation-step strafe-up ]
camera-button @top grid-add
"Strafe down\n (alt)" [ translation-step strafe-down ]
camera-button @bottom grid-add
<pile> 1 >>fill
"Forward (ctl)" [ translation-step step-turtle ]
camera-button add-gadget
"Backward (ctl)"
[ translation-step neg step-turtle ]
camera-button add-gadget
@center grid-add
;
: menu-quick-views ( -- gadget )
<shelf>
"View 1 (1)" mvt-3D-1 camera-button add-gadget
"View 2 (2)" mvt-3D-2 camera-button add-gadget
"View 3 (3)" mvt-3D-3 camera-button add-gadget
"View 4 (4)" mvt-3D-4 camera-button add-gadget
;
: menu-3D ( -- gadget )
<pile>
<shelf>
menu-rotations-3D add-gadget
menu-translations-3D add-gadget
0.5 >>align
{ 0 10 } >>gap
add-gadget
menu-quick-views add-gadget ;
TUPLE: handler < w:wrapper table ;
: <handler> ( child -- handler ) handler w:new-wrapper ;
M: handler handle-gesture ( gesture gadget -- ? )
tuck table>> at dup [ call( gadget -- ) f ] [ 2drop t ] if ;
: add-keyboard-delegate ( obj -- obj )
<handler>
H{
{ T{ key-down f f "LEFT" }
[ [ rotation-step turn-left ] camera-action ] }
{ T{ key-down f f "RIGHT" }
[ [ rotation-step turn-right ] camera-action ] }
{ T{ key-down f f "UP" }
[ [ rotation-step pitch-down ] camera-action ] }
{ T{ key-down f f "DOWN" }
[ [ rotation-step pitch-up ] camera-action ] }
{ T{ key-down f { C+ } "UP" }
[ [ translation-step step-turtle ] camera-action ] }
{ T{ key-down f { C+ } "DOWN" }
[ [ translation-step neg step-turtle ]
camera-action ] }
{ T{ key-down f { C+ } "LEFT" }
[ [ rotation-step roll-left ] camera-action ] }
{ T{ key-down f { C+ } "RIGHT" }
[ [ rotation-step roll-right ] camera-action ] }
{ T{ key-down f { A+ } "LEFT" }
[ [ translation-step strafe-left ] camera-action ] }
{ T{ key-down f { A+ } "RIGHT" }
[ [ translation-step strafe-right ] camera-action ] }
{ T{ key-down f { A+ } "UP" }
[ [ translation-step strafe-up ] camera-action ] }
{ T{ key-down f { A+ } "DOWN" }
[ [ translation-step strafe-down ] camera-action ] }
{ T{ key-down f f "1" } [ mvt-3D-1 camera-action ] }
{ T{ key-down f f "2" } [ mvt-3D-2 camera-action ] }
{ T{ key-down f f "3" } [ mvt-3D-3 camera-action ] }
{ T{ key-down f f "4" } [ mvt-3D-4 camera-action ] }
} >>table
;
! --------------------------------------------
! print elements
! --------------------------------------------
! print-content
GENERIC: adsoda-display-model ( x -- )
M: light adsoda-display-model
"\n light : " .
{
[ direction>> "direction : " pprint . ]
[ color>> "color : " pprint . ]
} cleave
;
M: face adsoda-display-model
{
[ halfspace>> "halfspace : " pprint . ]
[ touching-corners>> "touching corners : " pprint . ]
} cleave
;
M: solid adsoda-display-model
{
[ name>> "solid called : " pprint . ]
[ color>> "color : " pprint . ]
[ dimension>> "dimension : " pprint . ]
[ faces>> "composed of faces : " pprint
[ adsoda-display-model ] each ]
} cleave
;
M: space adsoda-display-model
{
[ dimension>> "dimension : " pprint . ]
[ ambient-color>> "ambient-color : " pprint . ]
[ solids>> "composed of solids : " pprint
[ adsoda-display-model ] each ]
[ lights>> "composed of lights : " pprint
[ adsoda-display-model ] each ]
} cleave
;
! ----------------------------------------------
: menu-bar ( -- gadget )
<shelf>
"reinit" [ drop load-model-file ] button* add-gadget
selected-file-model> <label-control> add-gadget
;
: controller-window* ( -- gadget )
{ 0 1 } <track>
menu-bar f track-add
<list-runner>
<scroller>
f track-add
<shelf>
"Projection mode : " <label> add-gadget
model-projection-chooser add-gadget
f track-add
<shelf>
"Collision detection (slow and buggy ) : "
<label> add-gadget
collision-detection-chooser add-gadget
f track-add
<pile>
0.5 >>align
menu-4D add-gadget
COLOR: purple s:<solid> >>interior
"4D movements" <labeled-gadget>
f track-add
<pile>
0.5 >>align
{ 2 2 } >>gap
menu-3D add-gadget
COLOR: purple s:<solid> >>interior
"Camera 3D" <labeled-gadget>
f track-add
COLOR: gray s:<solid> >>interior
;
: viewer-windows* ( -- )
"YZW" view1> win3D
"XZW" view2> win3D
"XYW" view3> win3D
"XYZ" view4> win3D
;
: navigator-window* ( -- )
controller-window*
viewer-windows*
add-keyboard-delegate
"navigateur 4D" open-window
;
: windows ( -- ) [ [ navigator-window* ] with-scope ] with-ui ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init-variables ( -- )
"choose a file" <model> >selected-file-model
<observer> >observer3d
[ observer3d> >self
reset-turtle
45 turn-left
45 pitch-up
-300 step-turtle
] with-scope
;
: init-models ( -- )
0 model-projection observer3d> <window3D> >view1
1 model-projection observer3d> <window3D> >view2
2 model-projection observer3d> <window3D> >view3
3 model-projection observer3d> <window3D> >view4
;
: 4DNav ( -- )
init-variables
selected-file read-model-file >present-space
init-models
windows
;
MAIN: 4DNav
]]
FILE: [[4DNav/window3D/window3D-docs.factor]] base64[[ISBDb3B5cmlnaHQgKEMpIDIwMDggSmVhbi1GcmFuw6dvaXMgQmlnb3QuCiEgU2VlIGh0dHA6Ly9mYWN0b3Jjb2RlLm9yZy9saWNlbnNlLnR4dCBmb3IgQlNEIGxpY2Vuc2UuClVTSU5HOiBoZWxwLm1hcmt1cCBoZWxwLnN5bnRheCBrZXJuZWwgOwpJTjogNEROYXYud2luZG93M0QKCgoKQVJUSUNMRTogIjRETmF2LndpbmRvdzNEIiAiV2luZG93M0QiCnsgJHZvY2FiLWxpbmsgIjRETmF2LndpbmRvdzNEIiB9CjsKCkFCT1VUOiAiNEROYXYud2luZG93M0QiCg==]]
FILE: [[4DNav/window3D/window3D.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING: kernel
ui.gadgets
ui.render
opengl
opengl.gl
opengl.glu
4DNav.camera
4DNav.turtle
math
values
alien.c-types
accessors
namespaces
adsoda
models
prettyprint
;
IN: 4DNav.window3D
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! drawing functions
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: window3D < gadget observer ;
: <window3D> ( model observer -- gadget )
window3D new
swap 2dup
projection-mode>> add-connection
2dup
collision-mode>> add-connection
>>observer
swap <model> >>model
t >>root?
;
M: window3D pref-dim* ( gadget -- dim ) drop { 300 300 } ;
M: window3D draw-gadget* ( gadget -- )
GL_PROJECTION glMatrixMode
glLoadIdentity
0.6 0.6 0.6 .9 glClearColor
dup observer>> projection-mode>> value>> 1 =
[ 60.0 1.0 0.1 3000.0 gluPerspective ]
[ -400.0 400.0 -400.0 400.0 0.0 4000.0 glOrtho ] if
dup observer>> collision-mode>> value>>
\ remove-hidden-solids?
set-value
dup observer>> do-look-at
GL_MODELVIEW glMatrixMode
glLoadIdentity
0.9 0.9 0.9 1.0 glClearColor
1.0 glClearDepth
GL_LINE_SMOOTH glEnable
GL_BLEND glEnable
GL_DEPTH_TEST glEnable
GL_LEQUAL glDepthFunc
GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA glBlendFunc
GL_LINE_SMOOTH_HINT GL_NICEST glHint
1.25 glLineWidth
GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT bitor
glClear
glLoadIdentity
GL_LIGHTING glEnable
GL_LIGHT0 glEnable
GL_COLOR_MATERIAL glEnable
GL_FRONT GL_AMBIENT_AND_DIFFUSE glColorMaterial
! *************************
control-value
[ space->GL ] when*
! *************************
;
M: window3D graft* drop ;
M: window3D model-changed nip relayout ;
]]
FILE: [[4DNav/window3D/authors.txt]] [[Jeff Bigot
]]
FILE: [[4DNav/camera/camera-docs.factor]] base64[[ISBDb3B5cmlnaHQgKEMpIDIwMDggSmVhbi1GcmFuw6dvaXMgQmlnb3QuCiEgU2VlIGh0dHA6Ly9mYWN0b3Jjb2RlLm9yZy9saWNlbnNlLnR4dCBmb3IgQlNEIGxpY2Vuc2UuClVTSU5HOiBoZWxwLm1hcmt1cCBoZWxwLnN5bnRheCBrZXJuZWwgOwpJTjogNEROYXYuY2FtZXJhCgpIRUxQOiBjYW1lcmEtZXllCnsgJHZhbHVlcwogICAgCiAgICAgeyAicG9pbnQiICJwb3NpdGlvbiIgfQp9CnsgJGRlc2NyaXB0aW9uICJyZXR1cm4gdGhlIHBvc2l0aW9uIG9mIHRoZSBjYW1lcmEiIH0gOwoKSEVMUDogY2FtZXJhLWZvY3VzCnsgJHZhbHVlcwogICAgCiAgICAgeyAicG9pbnQiICJwb3NpdGlvbiIgfQp9CnsgJGRlc2NyaXB0aW9uICJyZXR1cm4gdGhlIHBvaW50IHRoZSBjYW1lcmEgbG9va3MgYXQiIH0gOwoKSEVMUDogY2FtZXJhLXVwCnsgJHZhbHVlcwogICAgCiAgICAgeyAiZGlydmVjIiAidXBzaWRlIGRpcmVjdGlvbiIgfQp9CnsgJGRlc2NyaXB0aW9uICJJbiBvcmRlciB0byBwcmVjaXNlIHRoZSByb2xpbmcgcG9zaXRpb24gb2YgY2FtZXJhIGdpdmUgYW4gdXB3YXJkIHZlY3RvciIgfSA7CgpIRUxQOiBkby1sb29rLWF0CnsgJHZhbHVlcwogICAgIHsgImNhbWVyYSIgImRpcmVjdGlvbiIgfQp9CnsgJGRlc2NyaXB0aW9uICJXb3JkIHRvIHVzZSBpbiByZXBsYWNlbWVudCBvZiBnbC1sb29rLWF0IHdoZW4gdXNpbmcgYSBjYW1lcmEiIH0gOwoKQVJUSUNMRTogIjRETmF2LmNhbWVyYSIgIkNhbWVyYSIKeyAkdm9jYWItbGluayAiNEROYXYuY2FtZXJhIiB9CiRubAoiQSBjYW1lcmEgaXMgZGVmaW5lZCBieToiCnsgJGxpc3QKeyAiYSBwb3NpdGlvbiAoIiB7ICRsaW5rIGNhbWVyYS1leWUgfSAiKSIgfQp7ICJhIGZvY3VzIGRpcmVjdGlvbiAoIiB7ICRsaW5rIGNhbWVyYS1mb2N1cyB9ICIpIiB9CnsgImFuIGF0dGl0dWRlIGluZm9ybWF0aW9uICgiIHsgJGxpbmsgY2FtZXJhLXVwIH0gIikiIH0KfQoiVXNlICIgeyAkbGluayBkby1sb29rLWF0IH0gIiBpbiBvcGVuZ2wgc3RhdGVtZW50IGluIHBsYWNlbWVudCBvZiBnbC1sb29rLWF0IgokbmwKIkEgY2FtZXJhIGlzIGEgIiB7ICR2b2NhYi1saW5rICI0RE5hdi50dXJ0bGUiIH0gIiBvYmplY3QuIEl0cyBhIHNwZWNpYWwgdm9jYWIgdG8gaGFuZGxlIG1vdXZlbWVudHMgb2YgYSAzRCBvYmplY3Q6Igp7ICRsaXN0CnsgIlRvIGRlZmluZSBhIGNhbWVyYSIKewogICAgJHVuY2hlY2tlZC1leGFtcGxlCiAgICAKIlZBUjogbXktY2FtZXJhIgoiOiBpbml0LW15LWNhbWVyYSAoIC0tICkiCiIgICAgPHR1cnRsZT4gPm15LWNhbWVyYSIKIiAgICBbIG15LWNhbWVyYT4gPnNlbGYiCiIgICAgICByZXNldC10dXJ0bGUgIgoiICAgIF0gd2l0aC1zY29wZSA7Igp9IH0KeyAiVG8gbW92ZSBpdCIKewogICAgJHVuY2hlY2tlZC1leGFtcGxlCgoiICAgIFsgbXktY2FtZXJhPiA+c2VsZiIKIiAgICAgIDQ1IHBpdGNoLXVwICIKIiAgICAgIDUgc3RlcC10dXJ0bGUiIAoiICAgIF0gd2l0aC1zY29wZSAiCn0gfQp7ICJvciIKewogICAgJHVuY2hlY2tlZC1leGFtcGxlCgoiICAgIFsgbXktY2FtZXJhPiA+c2VsZiIKIiAgICAgIDUgc3RyYWZlLWxlZnQiCiIgICAgXSB3aXRoLXNjb3BlICIKfQp9CnsKInRvIHVzZSBpdCBpbiBhbiBvcGVuZ2wgc3RhdGVtZW50Igp7CiAgICAkdW5jaGVja2VkLWV4YW1wbGUKICAibXktY2FtZXJhPiBkby1sb29rLWF0IgoKfQp9Cn0KCgo7CgpBQk9VVDogIjRETmF2LmNhbWVyYSIK]]
FILE: [[4DNav/camera/authors.txt]] [[Adam Wendt
]]
FILE: [[4DNav/camera/camera.factor]] [[USING: kernel namespaces math.vectors opengl opengl.glu 4DNav.turtle ;
IN: 4DNav.camera
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: camera-eye ( -- point ) turtle-pos> ;
: camera-focus ( -- point )
[ 1 step-turtle turtle-pos> ] save-self ;
: camera-up ( -- dirvec )
[ 90 pitch-up turtle-pos> 1 step-turtle turtle-pos> swap v- ]
save-self ;
: do-look-at ( camera -- )
[ >self camera-eye camera-focus camera-up gl-look-at ]
with-scope ;
]]
FILE: [[4DNav/prismetriagone.xml]] [[<model>
<space>
<name>Prismetragone</name>
<dimension>4</dimension>
<solid>
<name>triangone</name>
<dimension>4</dimension>
<face>1,0,0,0,60</face>
<face>0.5,0.8660254037844386,0,0,60</face>
<face>-0.5,0.8660254037844387,0,0,-20</face>
<face>-1.0,0,0,0,-100</face>
<face>-0.5,-0.8660254037844384,0,0,-100</face>
<face>0.5,-0.8660254037844387,0,0,-20</face>
<face>0,0,1,0,120</face>
<face>0,0,-0.4999999999999998,-0.8660254037844387,-120</face>
<face>0,0,-0.5000000000000004,0.8660254037844384,-120</face>
<color>0,1,1</color>
</solid>
<light>
<direction>1,1,1,1</direction>
<color>0.2,0.2,0.6</color>
</light>
<color>0.8,0.9,0.9</color>
</space>
</model>
]]
FILE: [[4DNav/deep/deep.factor]] [[USING: macros quotations math math.functions math.trig
sequences.deep kernel make fry combinators grouping ;
IN: 4DNav.deep
! USING: bake ;
! MACRO: deep-cleave-quots ( seq -- quot )
! [ [ quotation? ] deep-filter ]
! [ [ dup quotation? [ drop , ] when ] deep-map ]
! bi '[ _ cleave _ bake ] ;
: make-matrix ( quot width -- matrix )
[ { } make ] dip group ; inline
]]
FILE: [[4DNav/deep/deep-docs.factor]] base64[[ISBDb3B5cmlnaHQgKEMpIDIwMDggSmVhbi1GcmFu529pcyBCaWdvdC4KISBTZWUgaHR0cDovL2ZhY3RvcmNvZGUub3JnL2xpY2Vuc2UudHh0IGZvciBCU0QgbGljZW5zZS4KVVNJTkc6IGhlbHAubWFya3VwIGhlbHAuc3ludGF4IGtlcm5lbCBxdW90YXRpb25zIHNlcXVlbmNlcyA7CklOOiA0RE5hdi5kZWVwCgohIEhFTFA6IGRlZXAtY2xlYXZlLXF1b3RzCiEgeyAkdmFsdWVzCiEgICAgIHsgInNlcSIgc2VxdWVuY2UgfQohICAgICB7ICJxdW90IiBxdW90YXRpb24gfQohIH0KISB7ICRkZXNjcmlwdGlvbiAiQSB3b3JkIHRvIGJ1aWxkIGEgc29xdWVuY2UgZnJvbSBhIHNlcXVlbmNlIG9mIHF1b3RhdGlvbiIgfQohIAohIHsgJGV4YW1wbGVzCiEgIkl0IGlzIHVzZWZ1bCB0byBidWlsZCBtYXRyaXgiCiEgeyAkZXhhbXBsZSAiVVNJTkc6IG1hdGggbWF0aC50cmlnIDsgIgohICAgICAiIDMwIGRlZz5yYWQgIgohICAgICIgIHsgIHsgWyBjb3MgXSBbIHNpbiBuZWcgXSAgIDAgfSAiCiEgICAgIiAgICAgeyBbIHNpbiBdIFsgY29zIF0gICAgICAgMCB9ICIKISAgICAiICAgICB7ICAgMCAgICAgICAwICAgICAgICAgICAxIH0gIgohICAgICIgIH0gZGVlcC1jbGVhdmUtcXVvdHMgIiAKISAgICAgIiAiCiEgCiEgCiEgfSB9CiEgOwoKQVJUSUNMRTogIjRETmF2LmRlZXAiICJEZWVwIgp7ICR2b2NhYi1saW5rICI0RE5hdi5kZWVwIiB9CjsKCkFCT1VUOiAiNEROYXYuZGVlcCIK]]
FILE: [[4DNav/file-chooser/authors.txt]] [[Jeff Bigot
]]
FILE: [[4DNav/file-chooser/file-chooser.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING:
kernel
io.files
io.backend
io.directories
io.files.info
io.pathnames
sequences
models
strings
ui
ui.operations
ui.commands
ui.gestures
ui.gadgets
ui.gadgets.buttons
ui.gadgets.lists
ui.gadgets.labels
ui.gadgets.tracks
ui.gadgets.packs
ui.gadgets.panes
ui.gadgets.scrollers
prettyprint
combinators
accessors
values
tools.walker
fry
;
IN: 4DNav.file-chooser
TUPLE: file-chooser < track
path
extension
selected-file
presenter
hook
list
;
: find-file-list ( gadget -- list )
[ file-chooser? ] find-parent list>> ;
file-chooser H{
{ T{ key-down f f "UP" }
[ find-file-list select-previous ] }
{ T{ key-down f f "DOWN" }
[ find-file-list select-next ] }
{ T{ key-down f f "PAGE_UP" }
[ find-file-list list-page-up ] }
{ T{ key-down f f "PAGE_DOWN" }
[ find-file-list list-page-down ] }
{ T{ key-down f f "RET" }
[ find-file-list invoke-value-action ] }
{ T{ button-down }
request-focus }
{ T{ button-down f 1 }
[ find-file-list invoke-value-action ] }
} set-gestures
: list-of-files ( file-chooser -- seq )
[ path>> value>> directory-entries ] [ extension>> ] bi
'[ [ name>> _ [ tail? ] with any? ]
[ directory? ] bi or ] filter
;
: update-filelist-model ( file-chooser -- )
[ list-of-files ] [ model>> ] bi set-model ;
: init-filelist-model ( file-chooser -- file-chooser )
dup list-of-files <model> >>model ;
: (fc-go) ( file-chooser button quot -- )
[ [ file-chooser? ] find-parent dup path>> ] dip
call
normalize-path swap set-model
update-filelist-model
drop ; inline
: fc-go-parent ( file-chooser button -- )
[ dup value>> parent-directory ] (fc-go) ;
: fc-go-home ( file-chooser button -- )
[ home ] (fc-go) ;
: fc-change-directory ( file-chooser file -- )
dupd [ path>> value>> normalize-path ] [ name>> ] bi*
append-path over path>> set-model
update-filelist-model
;
: fc-load-file ( file-chooser file -- )
over [ name>> ] [ selected-file>> ] bi* set-model
[ [ path>> value>> ] [ selected-file>> value>> ] bi append ] [ hook>> ] bi
call( path -- )
; inline
! : fc-ok-action ( file-chooser -- quot )
! dup selected-file>> value>> "" =
! [ drop [ drop ] ] [
! [ path>> value>> ]
! [ selected-file>> value>> append ]
! [ hook>> prefix ] tri
! [ drop ] prepend
! ] if ;
: line-selected-action ( file-chooser -- )
dup list>> list-value
dup directory?
[ fc-change-directory ] [ fc-load-file ] if ;
: present-dir-element ( element -- string )
[ name>> ] [ directory? ] bi [ "-> " prepend ] when ;
: <file-list> ( file-chooser -- list )
dup [ nip line-selected-action ] curry
[ present-dir-element ] rot model>> <list> ;
: <file-chooser> ( hook path extension -- gadget )
{ 0 1 } file-chooser new-track
swap >>extension
swap <model> >>path
"" <model> >>selected-file
swap >>hook
init-filelist-model
dup <file-list> >>list
"choose a file in directory " <label> f track-add
dup path>> <label-control> f track-add
dup extension>> ", " join "limited to : " prepend
<label> f track-add
<shelf>
"selected file : " <label> add-gadget
over selected-file>> <label-control> add-gadget
f track-add
<shelf>
over [ swap fc-go-parent ] curry "go up"
swap <border-button> add-gadget
over [ swap fc-go-home ] curry "go home"
swap <border-button> add-gadget
! over [ swap fc-ok-action ] curry "OK"
! swap <bevel-button> add-gadget
! [ drop ] "Cancel" swap <bevel-button> add-gadget
f track-add
dup list>> <scroller> 1 track-add
;
M: file-chooser pref-dim* drop { 400 200 } ;
: file-chooser-window ( -- )
[ . ] home { "xml" "txt" } <file-chooser>
"Choose a file" open-window ;
]]
FILE: [[4DNav/multi solids.xml]] [[<model>
<space>
<name>multi solids</name>
<dimension>4</dimension>
<solid>
<name>4cube1</name>
<dimension>4</dimension>
<face>1,0,0,0,100</face>
<face>-1,0,0,0,-150</face>
<face>0,1,0,0,100</face>
<face>0,-1,0,0,-150</face>
<face>0,0,1,0,100</face>
<face>0,0,-1,0,-150</face>
<face>0,0,0,1,100</face>
<face>0,0,0,-1,-150</face>
<color>1,0,0</color>
</solid>
<solid>
<name>4triancube</name>
<dimension>4</dimension>
<face>1,0,0,0,160</face>
<face>-0.4999999999999998,-0.8660254037844387,0,0,-130</face>
<face>-0.5000000000000004,0.8660254037844384,0,0,-130</face>
<face>0,0,1,0,140</face>
<face>0,0,-1,0,-180</face>
<face>0,0,0,1,110</face>
<face>0,0,0,-1,-180</face>
<color>0,1,0</color>
</solid>
<solid>
<name>triangone</name>
<dimension>4</dimension>
<face>1,0,0,0,60</face>
<face>0.5,0.8660254037844386,0,0,60</face>
<face>-0.5,0.8660254037844387,0,0,-20</face>
<face>-1.0,0,0,0,-100</face>
<face>-0.5,-0.8660254037844384,0,0,-100</face>
<face>0.5,-0.8660254037844387,0,0,-20</face>
<face>0,0,1,0,120</face>
<face>0,0,-0.4999999999999998,-0.8660254037844387,-120</face>
<face>0,0,-0.5000000000000004,0.8660254037844384,-120</face>
<color>0,1,1</color>
</solid>
<light>
<direction>1,1,1,1</direction>
<color>0.2,0.2,0.6</color>
</light>
<color>0.8,0.9,0.9</color>
</space>
</model>
]]
FILE: [[4DNav/triancube.xml]] [[<model>
<space>
<name>triancube</name>
<dimension>4</dimension>
<solid>
<name>triancube</name>
<dimension>4</dimension>
<face>1,0,0,0,160</face>
<face>-0.4999999999999998,-0.8660254037844387,0,0,-130</face>
<face>-0.5000000000000004,0.8660254037844384,0,0,-130</face>
<face>0,0,1,0,140</face>
<face>0,0,-1,0,-180</face>
<face>0,0,0,1,110</face>
<face>0,0,0,-1,-180</face>
<color>0,1,0</color>
</solid>
<light>
<direction>1,1,1,1</direction>
<color>0.2,0.2,0.6</color>
</light>
<color>0.8,0.9,0.9</color>
</space>
</model>
]]
FILE: [[4DNav/summary.txt]] [[Simple tool to navigate through a 4D space with projections on 4 3D spaces
]]
FILE: [[4DNav/hypercube.xml]] [[<model>
<space>
<name>hypercube</name>
<dimension>4</dimension>
<solid>
<name>4cube1</name>
<dimension>4</dimension>
<face>1,0,0,0,100</face>
<face>-1,0,0,0,-150</face>
<face>0,1,0,0,100</face>
<face>0,-1,0,0,-150</face>
<face>0,0,1,0,100</face>
<face>0,0,-1,0,-150</face>
<face>0,0,0,1,100</face>
<face>0,0,0,-1,-150</face>
<color>1,0,0</color>
</solid>
<solid>
<name>4cube1</name>
<dimension>4</dimension>
<face>1,0,0,0,100</face>
<face>-1,0,0,0,-150</face>
<face>0,1,0,0,100</face>
<face>0,-1,0,0,-150</face>
<face>0,0,1,0,100</face>
<face>0,0,-1,0,-150</face>
<face>0,0,0,1,100</face>
<face>0,0,0,-1,-150</face>
<color>1,0,0</color>
</solid>
<light>
<direction>1,1,1,1</direction>
<color>0.2,0.2,0.6</color>
</light>
<color>0.8,0.9,0.9</color>
</space>
</model>
]]
FILE: [[4DNav/deploy.factor]] [[USING: tools.deploy.config ;
H{
{ deploy-c-types? t }
{ deploy-word-props? t }
{ deploy-name "4DNav" }
{ deploy-ui? t }
{ deploy-math? t }
{ deploy-threads? t }
{ deploy-reflection 3 }
{ deploy-unicode? t }
{ deploy-io 3 }
{ "stop-after-last-window?" t }
{ deploy-word-defs? t }
}
]]
FILE: [[4DNav/space-file-decoder/space-file-decoder.factor]] [[! Copyright (C) 2008 Jeff Bigot
! See http://factorcode.org/license.txt for BSD license.
USING: adsoda xml xml.traversal xml.syntax accessors
combinators sequences math.parser kernel splitting values
continuations ;
IN: 4DNav.space-file-decoder
: decode-number-array ( x -- y )
"," split [ string>number ] map ;
TAGS: adsoda-read-model ( tag -- model )
TAG: dimension adsoda-read-model
children>> first string>number ;
TAG: direction adsoda-read-model
children>> first decode-number-array ;
TAG: color adsoda-read-model
children>> first decode-number-array ;
TAG: name adsoda-read-model
children>> first ;
TAG: face adsoda-read-model
children>> first decode-number-array ;
TAG: solid adsoda-read-model
<solid> swap
{
[ "dimension" tag-named adsoda-read-model >>dimension ]
[ "name" tag-named adsoda-read-model >>name ]
[ "color" tag-named adsoda-read-model >>color ]
[ "face"
tags-named [ adsoda-read-model cut-solid ] each ]
} cleave
ensure-adjacencies
;
TAG: light adsoda-read-model
<light> swap
{
[ "direction" tag-named adsoda-read-model >>direction ]
[ "color" tag-named adsoda-read-model >>color ]
} cleave
;
TAG: space adsoda-read-model
<space> swap
{
[ "dimension" tag-named adsoda-read-model >>dimension ]
[ "name" tag-named adsoda-read-model >>name ]
[ "color" tag-named
adsoda-read-model >>ambient-color ]
[ "solid" tags-named
[ adsoda-read-model suffix-solids ] each ]
[ "light" tags-named
[ adsoda-read-model suffix-lights ] each ]
} cleave
;
: read-model-file ( path -- x )
[
[ file>xml "space" tag-named adsoda-read-model ]
[ 2drop <space> ] recover
] [ <space> ] if*
;
]]
FILE: [[4DNav/space-file-decoder/space-file-decoder-docs.factor]] base64[[ISBDb3B5cmlnaHQgKEMpIDIwMDggSmVhbi1GcmFuw6dvaXMgQmlnb3QuCiEgU2VlIGh0dHA6Ly9mYWN0b3Jjb2RlLm9yZy9saWNlbnNlLnR4dCBmb3IgQlNEIGxpY2Vuc2UuClVTSU5HOiBoZWxwLm1hcmt1cCBoZWxwLnN5bnRheCBrZXJuZWwgOwpJTjogNEROYXYuc3BhY2UtZmlsZS1kZWNvZGVyCgoKCkhFTFA6IHJlYWQtbW9kZWwtZmlsZQp7ICR2YWx1ZXMKICAgIAogICAgIHsgInBhdGgiICJwYXRoIHRvIHRoZSBmaWxlIHRvIHJlYWQiIH0KICAgICB7ICJ4IiAidmFsdWUiIH0KfQp7ICRkZXNjcmlwdGlvbiAiUmVhZCBhIGZpbGUgY29udGFpbmluZyB0aGUgeG1sIGRlc2NyaXB0aW9uIG9mIHRoZSBtb2RlbCIgfSA7CgpBUlRJQ0xFOiAiNEROYXYuc3BhY2UtZmlsZS1kZWNvZGVyIiAiU3BhY2UgWE1MZmlsZSBkZWNvZGVyIgp7ICR2b2NhYi1saW5rICI0RE5hdi5zcGFjZS1maWxlLWRlY29kZXIiIH0KOwoKQUJPVVQ6ICI0RE5hdi5zcGFjZS1maWxlLWRlY29kZXIiCg==]]
FILE: [[4DNav/space-file-decoder/authors.txt]] [[Jeff Bigot
]]
FILE: [[4DNav/light_test.xml]] [[<model>
<space>
<name>multi solids</name>
<dimension>4</dimension>
<solid>
<name>4cube1</name>
<dimension>4</dimension>
<face>1,0,0,0,100</face>
<face>-1,0,0,0,-150</face>
<face>0,1,0,0,100</face>
<face>0,-1,0,0,-150</face>
<face>0,0,1,0,100</face>
<face>0,0,-1,0,-150</face>
<face>0,0,0,1,100</face>
<face>0,0,0,-1,-150</face>
<color>1,1,1</color>
</solid>
<solid>
<name>4triancube</name>
<dimension>4</dimension>
<face>1,0,0,0,160</face>
<face>-0.4999999999999998,-0.8660254037844387,0,0,-130</face>
<face>-0.5000000000000004,0.8660254037844384,0,0,-130</face>
<face>0,0,1,0,140</face>
<face>0,0,-1,0,-180</face>
<face>0,0,0,1,110</face>
<face>0,0,0,-1,-180</face>
<color>1,1,1</color>
</solid>
<solid>
<name>triangone</name>
<dimension>4</dimension>
<face>1,0,0,0,60</face>
<face>0.5,0.8660254037844386,0,0,60</face>
<face>-0.5,0.8660254037844387,0,0,-20</face>
<face>-1.0,0,0,0,-100</face>
<face>-0.5,-0.8660254037844384,0,0,-100</face>
<face>0.5,-0.8660254037844387,0,0,-20</face>
<face>0,0,1,0,120</face>
<face>0,0,-0.4999999999999998,-0.8660254037844387,-120</face>
<face>0,0,-0.5000000000000004,0.8660254037844384,-120</face>
<color>1,1,1</color>
</solid>
<light>
<direction>1,0,0,0</direction>
<color>0,0,0,0.6</color>
</light>
<light>
<direction>0,1,0,0</direction>
<color>0,0.6,0,0</color>
</light>
<light>
<direction>0,0,1,0</direction>
<color>0,0,0.6,0</color>
</light>
<light>
<direction>0,0,0,1</direction>
<color>0.6,0.6,0.6</color>
</light>
<color>0.99,0.99,0.99</color>
</space>
</model>
]]
FILE: [[4DNav/authors.txt]] [[Jeff Bigot
]]
FILE: [[4DNav/tags.txt]] [[4D viewer]]
FILE: [[oracle/liboci/liboci.factor]] [[! Copyright (C) 2007 Elie CHAFTARI
! See http://factorcode.org/license.txt for BSD license.
!
! Adapted from oci.h and ociap.h
! Tested with Oracle version - 10.1.0.3 Instant Client
!
! DYLD_LIBRARY_PATH="/usr/local/oracle/instantclient10_1"
! export DYLD_LIBRARY_PATH
USING: alien alien.syntax combinators kernel system ;
IN: oracle.liboci
"oci" {
{ [ os winnt? ] [ "oci.dll" stdcall ] }
{ [ os macosx? ] [ "$DYLD_LIBRARY_PATH/libclntsh.dylib" cdecl ] }
{ [ os unix? ] [ "$DYLD_LIBRARY_PATH/libclntsh.so.10.1" cdecl ] }
} cond add-library
! ===============================================
! Attribute Types
! ===============================================
: OCI_ATTR_USERNAME 22 ; inline ! username attribute
: OCI_ATTR_PASSWORD 23 ; inline ! password attribute
! ===============================================
! Various Modes
! ===============================================
: OCI_DEFAULT 0x00 ; inline ! default value for parameters and attributes
: OCI_THREADED 0x01 ; inline ! appl. in threaded environment
: OCI_OBJECT 0x02 ; inline ! application in object environment
! ===============================================
! Execution Modes
! ===============================================
: OCI_DESCRIBE_ONLY 0x10 ; inline ! only describe the statement
! ===============================================
! Credential Types
! ===============================================
: OCI_CRED_RDBMS 1 ; inline ! database username/password
: OCI_CRED_EXT 2 ; inline ! externally provided credentials
: OCI_CRED_PROXY 3 ; inline ! proxy authentication
! ===============================================
! Error Return Values
! ===============================================
: OCI_SUCCESS 0 ; inline ! maps to SQL_SUCCESS of SAG CLI
: OCI_SUCCESS_WITH_INFO 1 ; inline ! maps to SQL_SUCCESS_WITH_INFO
: OCI_RESERVED_FOR_INT_USE 200 ; inline ! reserved
: OCI_NO_DATA 100 ; inline ! maps to SQL_NO_DATA
: OCI_ERROR -1 ; inline ! maps to SQL_ERROR
: OCI_INVALID_HANDLE -2 ; inline ! maps to SQL_INVALID_HANDLE
: OCI_NEED_DATA 99 ; inline ! maps to SQL_NEED_DATA
: OCI_STILL_EXECUTING -3123 ; inline ! OCI would block error
! ===============================================
! Parsing Syntax Types
! ===============================================
: OCI_V7_SYNTAX 2 ; inline ! V815 language - for backwards compatibility
: OCI_V8_SYNTAX 3 ; inline ! V815 language - for backwards compatibility
: OCI_NTV_SYNTAX 1 ; inline ! Use what so ever is the native lang of server
! ===============================================
! Scrollable Cursor Fetch Options
! For non-scrollable cursor, the only valid
! (and default) orientation is OCI_FETCH_NEXT
! ===============================================
: OCI_FETCH_CURRENT 0x01 ; inline ! refetching current position
: OCI_FETCH_NEXT 0x02 ; inline ! next row
: OCI_FETCH_FIRST 0x04 ; inline ! first row of the result set
: OCI_FETCH_LAST 0x08 ; inline ! the last row of the result set
: OCI_FETCH_PRIOR 0x10 ; inline ! the previous row relative to current
: OCI_FETCH_ABSOLUTE 0x20 ; inline ! absolute offset from first
: OCI_FETCH_RELATIVE 0x40 ; inline ! offset relative to current
: OCI_FETCH_RESERVED_1 0x80 ; inline ! reserved
! ===============================================
! Handle Types
! ===============================================
: OCI_HTYPE_ENV 1 ; inline ! environment handle
: OCI_HTYPE_ERROR 2 ; inline ! error handle
: OCI_HTYPE_SVCCTX 3 ; inline ! service handle
: OCI_HTYPE_STMT 4 ; inline ! statement handle
: OCI_HTYPE_BIND 5 ; inline ! bind handle
: OCI_HTYPE_DEFINE 6 ; inline ! define handle
: OCI_HTYPE_DESCRIBE 7 ; inline ! describe handle
: OCI_HTYPE_SERVER 8 ; inline ! server handle
: OCI_HTYPE_SESSION 9 ; inline ! authentication handle
! ===============================================
! Attribute Types
! ===============================================
: OCI_ATTR_FNCODE 1 ; inline ! the OCI function code
: OCI_ATTR_OBJECT 2 ; inline ! is the environment initialized in object mode
: OCI_ATTR_NONBLOCKING_MODE 3 ; inline ! non blocking mode
: OCI_ATTR_SQLCODE 4 ; inline ! the SQL verb
: OCI_ATTR_ENV 5 ; inline ! the environment handle
: OCI_ATTR_SERVER 6 ; inline ! the server handle
: OCI_ATTR_SESSION 7 ; inline ! the user session handle
: OCI_ATTR_TRANS 8 ; inline ! the transaction handle
: OCI_ATTR_ROW_COUNT 9 ; inline ! the rows processed so far
: OCI_ATTR_SQLFNCODE 10 ; inline ! the SQL verb of the statement
: OCI_ATTR_PREFETCH_ROWS 11 ; inline ! sets the number of rows to prefetch
: OCI_ATTR_NESTED_PREFETCH_ROWS 12 ; inline ! the prefetch rows of nested table
: OCI_ATTR_PREFETCH_MEMORY 13 ; inline ! memory limit for rows fetched
: OCI_ATTR_NESTED_PREFETCH_MEMORY 14 ; inline ! memory limit for nested rows
: OCI_ATTR_CHAR_COUNT 15 ; inline ! this specifies the bind and define size in characters
! ===============================================
! OCI integer types
! ===============================================
TYPEDEF: ushort ub2
TYPEDEF: short sb2
TYPEDEF: uint ub4
TYPEDEF: int sb4
! ===============================================
! Input data types (ocidfn.h)
! ===============================================
: SQLT_CHR 1 ; inline ! (ORANET TYPE) character string
: SQLT_NUM 2 ; inline ! (ORANET TYPE) oracle numeric
: SQLT_INT 3 ; inline ! (ORANET TYPE) integer
: SQLT_FLT 4 ; inline ! (ORANET TYPE) Floating point number
: SQLT_STR 5 ; inline ! zero terminated string
: SQLT_ODT 156 ; inline ! OCIDate type
! ===============================================
! Input datetimes and intervals (ocidfn.h)
! ===============================================
: SQLT_DATE 184 ; inline ! ANSI Date
: SQLT_TIME 185 ; inline ! TIME
: SQLT_TIME_TZ 186 ; inline ! TIME WITH TIME ZONE
: SQLT_TIMESTAMP 187 ; inline ! TIMESTAMP
: SQLT_TIMESTAMP_TZ 188 ; inline ! TIMESTAMP WITH TIME ZONE
: SQLT_INTERVAL_YM 189 ; inline ! INTERVAL YEAR TO MONTH
: SQLT_INTERVAL_DS 190 ; inline ! INTERVAL DAY TO SECOND
: SQLT_TIMESTAMP_LTZ 232 ; inline ! TIMESTAMP WITH LOCAL TZ
! ===============================================
! Opaque pointer types
! ===============================================
TYPEDEF: void dvoid
TYPEDEF: void oci_env
TYPEDEF: void oci_server
TYPEDEF: void oci_error
TYPEDEF: void oci_svc_ctx
TYPEDEF: void oci_session
TYPEDEF: void oci_stmt
LIBRARY: oci
! ===============================================
! ociap.h
! ===============================================
FUNCTION: int OCIInitialize ( ub4 mode, void* ctxp, void* malocfp, void* ralocfp, dvoid* mfreefp ) ;
FUNCTION: int OCITerminate ( ub4 mode ) ;
FUNCTION: int OCIEnvInit ( void* envhpp, ub4 mode, size_t xtramem_sz, dvoid* usrmempp ) ;
FUNCTION: int OCIEnvCreate ( dvoid* envhpp, ub4 mode, void* ctxp, void* malocfp, void* ralocfp, void* mfreefp, size_t xtramemz, dvoid* usrmempp ) ;
FUNCTION: int OCIHandleAlloc ( void* parenth, dvoid* hndlpp, ub4 type, size_t xtramem_sz, dvoid* usrmempp ) ;
FUNCTION: int OCIServerAttach ( void* srvhp, void* errhp, char* dblink, sb4 dblink_len, ub4 mode ) ;
FUNCTION: int OCIServerDetach ( void* srvhp, void* errhp, ub4 mode ) ;
FUNCTION: int OCIHandleFree ( dvoid* p0, ub4 p1 ) ;
FUNCTION: int OCILogon ( void* envhp, void* errhp, dvoid* svchpp, uchar* username, ub4 uname_len, uchar* passwd, ub4 password_len, uchar* dsn, ub4 dsn_len ) ;
FUNCTION: int OCILogoff ( void* p0, void* p1 ) ;
FUNCTION: void OCIErrorGet ( void* handlp, ub4 recordno, char* sqlstate, sb4* errcodep, uchar* bufp, ub4 bufsize, ub4 type ) ;
FUNCTION: int OCIStmtPrepare ( void* stmtp, void* errhp, uchar* stmt, ub4 stmt_len, ub4 language, ub4 mode ) ;
FUNCTION: int OCIStmtExecute ( void* svchp, void* stmtp1, void* errhp, ub4 iters, ub4 rowoff, void* snap_in, void* snap_out, ub4 mode ) ;
FUNCTION: int OCIParamGet ( void* hndlp, ub4 htype, void* errhp, dvoid* parmdpp, ub4 pos ) ;
FUNCTION: int OCIAttrGet ( void* trgthndlp, ub4 trghndltyp, void* attributep, ub4* sizep, ub4 attrtype, void* errhp ) ;
FUNCTION: int OCIAttrSet ( dvoid* trgthndlp, ub4 trgthndltyp, dvoid* attributep, ub4 size, ub4 attrtype, oci_error* errhp ) ;
FUNCTION: int OCIDefineByPos ( void* stmtp, dvoid* defnpp, void* errhp, ub4 position, void* valuep, sb4 value_sz, ub2 dty, sb2* indp, ub2* rlenp, ub2* rcodep, ub4 mode ) ;
FUNCTION: int OCIStmtFetch ( void* stmthp, void* errhp, ub4 p2, ub2 p3, ub4 p4 ) ;
FUNCTION: int OCITransStart ( void* svchp, void* errhp, ushort p2, ushort p3 ) ;
FUNCTION: int OCITransCommit ( void* svchp, void* errhp, ushort p2 ) ;
FUNCTION: int OCITransRollback ( void* svchp, void* errhp, ushort p2 ) ;
FUNCTION: int OCISessionBegin ( oci_svc_ctx* svchp, oci_error* errhp, oci_session* usrhp, ub4 credt, ub4 mode ) ;
FUNCTION: int OCISessionEnd ( oci_svc_ctx* svchp, oci_error* errhp, oci_session* usrhp, ub4 mode ) ;
FUNCTION: int OCIServerVersion ( void* handlp, void* errhp, uchar* bufsz, int bufsz, short hndltype ) ;
]]
FILE: [[oracle/liboci/authors.txt]] [[Elie Chaftari
]]
FILE: [[oracle/summary.txt]] [[Oracle database bindings
]]
FILE: [[oracle/oracle-tests.factor]] [[USING: oracle oracle.liboci prettyprint tools.test
kernel ;
[
"testuser" "testpassword" "//localhost/test1" log-on .
allocate-statement-handle
"CREATE TABLE TESTTABLE ( COL1 VARCHAR(40), COL2 NUMBER)" prepare-statement
[ t ] [ execute-statement ] unit-test
"INSERT INTO TESTTABLE (COL1, COL2) VALUES('hello', 50)" prepare-statement
[ t ] [ execute-statement ] unit-test
"INSERT INTO TESTTABLE (COL1, COL2) VALUES('hi', 60)" prepare-statement
[ t ] [ execute-statement ] unit-test
"INSERT INTO TESTTABLE (COL1, COL2) VALUES('bye', 70)" prepare-statement
[ t ] [ execute-statement ] unit-test
"COMMIT" prepare-statement
[ t ] [ execute-statement ] unit-test
"SELECT * FROM TESTTABLE" prepare-statement
1 SQLT_STR define-by-position run-query
[ V{ "hello" "hi" "bye" "50" "60" "70" } ] [
2 SQLT_STR define-by-position run-query gather-results
] unit-test
clear-result
"UPDATE TESTTABLE SET COL2 = 10 WHERE COL1='hi'" prepare-statement
[ t ] [ execute-statement ] unit-test
"COMMIT" prepare-statement
[ t ] [ execute-statement ] unit-test
"SELECT * FROM TESTTABLE WHERE COL1 = 'hi'" prepare-statement
[ V{ "10" } ] [
2 SQLT_STR define-by-position run-query gather-results
] unit-test
clear-result
"DROP TABLE TESTTABLE" prepare-statement
execute-statement
free-statement-handle log-off clean-up terminate
] drop
]]
FILE: [[oracle/oracle.factor]] [[! Copyright (C) 2007 Elie CHAFTARI
! See http://factorcode.org/license.txt for BSD license.
!
! Adapted from oci.h and ociap.h
! Tested with Oracle version - 10.1.0.3 Instant Client
USING: alien alien.c-types alien.strings combinators kernel math
namespaces oracle.liboci prettyprint sequences
io.encodings.ascii accessors ;
IN: oracle
SYMBOL: env
SYMBOL: err
SYMBOL: srv
SYMBOL: svc
SYMBOL: ses
SYMBOL: stm
SYMBOL: buf
SYMBOL: res
SYMBOL: con
TUPLE: connection username password db ;
C: <connection> connection
! =========================================================
! Error-handling routines
! =========================================================
: get-oci-error ( object -- * )
1 f "uint*" <c-object> dup >r 512 "uchar" <c-array> dup >r
512 OCI_HTYPE_ERROR OCIErrorGet r> r> *uint drop
ascii alien>string throw ;
: check-result ( result -- )
{
{ OCI_SUCCESS [ ] }
{ OCI_ERROR [ err get get-oci-error ] }
{ OCI_INVALID_HANDLE [ "invalid handle" throw ] }
[ "operation failed" throw ]
} case ;
: check-status ( status -- bool )
{
{ OCI_SUCCESS [ t ] }
{ OCI_ERROR [ err get get-oci-error ] }
{ OCI_INVALID_HANDLE [ "invalid handle" throw ] }
{ OCI_NO_DATA [ f ] }
[ "operation failed" throw ]
} case ;
! =========================================================
! Initialization and handle-allocation routines
! =========================================================
! Legacy initialization routine
: oci-initialize ( -- )
OCI_DEFAULT f f f f OCIInitialize check-result ;
! Legacy initialization routine
: oci-env-init ( -- )
"void*" <c-object> dup OCI_DEFAULT 0 f OCIEnvInit
check-result *void* env set ;
: create-environment ( -- )
"void*" <c-object> dup OCI_DEFAULT f f f f 0 f OCIEnvCreate
check-result *void* env set ;
: allocate-error-handle ( -- )
env get
"void*" <c-object> tuck OCI_HTYPE_ERROR 0 f OCIHandleAlloc
check-result *void* err set ;
: allocate-service-handle ( -- )
env get
"void*" <c-object> tuck OCI_HTYPE_SVCCTX 0 f OCIHandleAlloc
check-result *void* svc set ;
: allocate-session-handle ( -- )
env get
"void*" <c-object> tuck OCI_HTYPE_SESSION 0 f OCIHandleAlloc
check-result *void* ses set ;
: allocate-server-handle ( -- )
env get
"void*" <c-object> tuck OCI_HTYPE_SERVER 0 f OCIHandleAlloc
check-result *void* srv set ;
: init ( -- )
oci-initialize
oci-env-init
allocate-error-handle
allocate-service-handle
allocate-session-handle
allocate-server-handle ;
! =========================================================
! Single user session logon routine
! =========================================================
: oci-log-on ( -- )
env get err get svc get
con get username>> dup length swap ascii malloc-string swap
con get password>> dup length swap ascii malloc-string swap
con get db>> dup length swap ascii malloc-string swap
OCILogon check-result ;
! =========================================================
! Attach to server and attribute-setting routines
! =========================================================
: attach-to-server ( -- )
srv get err get con get db>> dup length OCI_DEFAULT
OCIServerAttach check-result ;
: set-service-attribute ( -- )
svc get OCI_HTYPE_SVCCTX srv get 0 OCI_ATTR_SERVER err get OCIAttrSet check-result ;
: set-username-attribute ( -- )
ses get OCI_HTYPE_SESSION con get username>> dup length swap ascii malloc-string swap
OCI_ATTR_USERNAME err get OCIAttrSet check-result ;
: set-password-attribute ( -- )
ses get OCI_HTYPE_SESSION con get password>> dup length swap ascii malloc-string swap
OCI_ATTR_PASSWORD err get OCIAttrSet check-result ;
: set-attributes ( -- )
set-service-attribute
set-username-attribute
set-password-attribute ;
! =========================================================
! Session startup routines
! =========================================================
: begin-session ( -- )
svc get err get ses get OCI_CRED_RDBMS OCI_DEFAULT OCISessionBegin check-result ;
: set-authentication-handle ( -- )
svc get OCI_HTYPE_SVCCTX ses get 0 OCI_ATTR_SESSION err get OCIAttrSet check-result ;
! =========================================================
! Statement preparation and execution routines
! =========================================================
: allocate-statement-handle ( -- )
env get
"void*" <c-object> tuck OCI_HTYPE_STMT 0 f OCIHandleAlloc
check-result *void* stm set ;
: prepare-statement ( statement -- )
>r stm get err get r> dup length swap ascii malloc-string swap
OCI_NTV_SYNTAX OCI_DEFAULT OCIStmtPrepare check-result ;
: calculate-size ( type -- size )
{
{ SQLT_INT [ "int" heap-size ] }
{ SQLT_FLT [ "float" heap-size ] }
{ SQLT_CHR [ "char" heap-size ] }
{ SQLT_NUM [ "int" heap-size 10 * ] }
{ SQLT_STR [ 64 ] }
{ SQLT_ODT [ 256 ] }
} case ;
: define-by-position ( position type -- )
>r >r stm get f <void*> err get
r> r> dup calculate-size >r [ "char" malloc-array dup buf set ] keep 1+
r> f f f OCI_DEFAULT OCIDefineByPos check-result ;
: execute-statement ( -- bool )
svc get stm get err get 1 0 f f OCI_DEFAULT OCIStmtExecute check-status ;
: fetch-statement ( -- bool )
stm get err get 1 OCI_FETCH_NEXT OCI_DEFAULT OCIStmtFetch check-status ;
: free-statement-handle ( -- )
stm get OCI_HTYPE_STMT OCIHandleFree check-result ;
! =========================================================
! Log off and detach from server routines
! =========================================================
: end-session ( -- )
svc get err get ses get OCI_DEFAULT OCISessionEnd check-result ;
: detach-from-server ( -- )
srv get err get OCI_DEFAULT OCIServerDetach check-result ;
: log-off ( -- )
end-session
detach-from-server ;
! =========================================================
! Clean-up and termination routines
! =========================================================
: free-service-handle ( -- )
svc get OCI_HTYPE_SVCCTX OCIHandleFree check-result ;
: free-server-handle ( -- )
srv get OCI_HTYPE_SERVER OCIHandleFree check-result ;
: free-error-handle ( -- )
err get OCI_HTYPE_ERROR OCIHandleFree check-result ;
: free-environment-handle ( -- )
env get OCI_HTYPE_ENV OCIHandleFree check-result ;
: clean-up ( -- )
free-service-handle
free-server-handle
free-error-handle
free-environment-handle ;
: terminate ( -- )
OCI_DEFAULT OCITerminate check-result ;
! =========================================================
! Utility routines
! =========================================================
: server-version ( -- )
srv get err get 512 "uchar" malloc-array dup >r 512 OCI_HTYPE_SERVER
OCIServerVersion check-result r> ascii alien>string . ;
! =========================================================
! Public routines
! =========================================================
: log-on ( username password db -- )
<connection> con set
init attach-to-server set-attributes
begin-session set-authentication-handle
V{ } clone res set ;
: fetch-each ( object -- object )
fetch-statement [
buf get ascii alien>string res get swap suffix res set
fetch-each
] [ ] if ;
: run-query ( object -- object )
execute-statement [
buf get ascii alien>string res get swap suffix res set
fetch-each
] [ ] if ;
: gather-results ( -- seq )
res get ;
: show-result ( -- )
res get [ . ] each ;
: clear-result ( -- )
V{ } clone res set ;
]]
FILE: [[oracle/authors.txt]] [[Elie Chaftari
]]
FILE: [[oracle/tags.txt]] [[database
]]
FILE: [[irc/ui/ircui-rc]] [[! Default system ircui-rc file
! Copy into .ircui-rc in your home directory and then change username and such
! To find your home directory, type "home ." into a Factor listener
USING: irc.client irc.ui ;
"irc.freenode.org" 8001 "factor-irc" f ! server port nick password
{ "#concatenative" "#terrorisland" } ! all the channels you want to autojoin
server-open
]]
FILE: [[irc/ui/ui.factor]] [[! Copyright (C) 2008 William Schlieper
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel threads combinators concurrency.mailboxes
sequences strings hashtables splitting fry assocs hashtables colors
sorting unicode math.order
ui ui.gadgets ui.gadgets.panes ui.gadgets.editors
ui.gadgets.scrollers ui.commands ui.gadgets.frames ui.gestures
ui.gadgets.tabs ui.gadgets.grids ui.gadgets.packs ui.gadgets.labels
io io.styles namespaces calendar calendar.format models continuations
irc.client irc.client.private irc.messages
irc.ui.commandparser irc.ui.load vocabs.loader classes prettyprint ;
RENAME: join sequences => sjoin
IN: irc.ui
SYMBOL: chat
SYMBOL: client
TUPLE: ui-window < tabbed client ;
M: ui-window ungraft*
client>> terminate-irc ;
TUPLE: irc-tab < frame chat client window ;
: write-color ( str color -- )
foreground associate format ;
CONSTANT: dark-red T{ rgba f 0.5 0.0 0.0 1 }
CONSTANT: dark-green T{ rgba f 0.0 0.5 0.0 1 }
CONSTANT: dark-blue T{ rgba f 0.0 0.0 0.5 1 }
: dot-or-parens ( string -- string )
[ "." ]
[ "(" prepend ")" append ] if-empty ;
GENERIC: write-irc ( irc-message -- )
M: ping write-irc
drop "* Ping" blue write-color ;
M: privmsg write-irc
"<" dark-blue write-color
[ irc-message-sender write ] keep
"> " dark-blue write-color
trailing>> write ;
M: notice write-irc
[ type>> dark-blue write-color ] keep
": " dark-blue write-color
trailing>> write ;
TUPLE: own-message message nick timestamp ;
: <own-message> ( message nick -- own-message )
now own-message boa ;
M: own-message write-irc
"<" dark-blue write-color
[ nick>> bold font-style associate format ] keep
"> " dark-blue write-color
message>> write ;
M: join write-irc
"* " dark-green write-color
irc-message-sender write
" has entered the channel." dark-green write-color ;
M: part write-irc
"* " dark-red write-color
[ irc-message-sender write ] keep
" has left the channel" dark-red write-color
trailing>> dot-or-parens dark-red write-color ;
M: quit write-irc
"* " dark-red write-color
[ irc-message-sender write ] keep
" has left IRC" dark-red write-color
trailing>> dot-or-parens dark-red write-color ;
M: kick write-irc
"* " dark-red write-color
[ irc-message-sender write ] keep
" has kicked " dark-red write-color
[ who>> write ] keep
" from the channel" dark-red write-color
trailing>> dot-or-parens dark-red write-color ;
M: mode write-irc
"* " dark-blue write-color
[ name>> write ] keep
" has applied mode " dark-blue write-color
[ mode>> write ] keep
" to " dark-blue write-color
parameter>> write ;
M: nick write-irc
"* " dark-blue write-color
[ irc-message-sender write ] keep
" is now known as " blue write-color
trailing>> write ;
M: unhandled write-irc
"UNHANDLED: " write
line>> dark-blue write-color ;
M: irc-end write-irc
drop "* You have left IRC" dark-red write-color ;
M: irc-disconnected write-irc
drop "* Disconnected" dark-red write-color ;
M: irc-connected write-irc
drop "* Connected" dark-green write-color ;
M: irc-chat-end write-irc
drop ;
M: irc-message write-irc
"UNIMPLEMENTED" write
[ class pprint ] keep
": " write
line>> dark-blue write-color ;
GENERIC: time-happened ( message -- timestamp )
M: irc-message time-happened timestamp>> ;
M: object time-happened drop now ;
: print-irc ( irc-message -- )
[ time-happened timestamp>hms write " " write ]
[ write-irc nl ] bi ;
: send-message ( message -- )
[ print-irc ]
[ chat get speak ] bi ;
GENERIC: handle-inbox ( tab message -- )
: value-labels ( assoc val -- seq )
'[ nip _ = ] assoc-filter keys sort-strings [ <label> ] map ;
: add-gadget-color ( pack seq color -- pack )
'[ _ >>color add-gadget ] each ;
M: object handle-inbox
nip print-irc ;
: display ( stream tab -- )
'[ _ [ [ t ]
[ _ dup chat>> hear handle-inbox ]
while ] with-output-stream ] "ircv" spawn drop ;
: <irc-pane> ( tab -- tab pane )
<scrolling-pane>
[ <pane-stream> swap display ] 2keep ;
TUPLE: irc-editor < editor outstream tab ;
: <irc-editor> ( tab pane -- tab editor )
irc-editor new-editor
swap <pane-stream> >>outstream ;
: editor-send ( irc-editor -- )
{ [ outstream>> ]
[ [ irc-tab? ] find-parent ]
[ editor-string ]
[ "" swap set-editor-string ] } cleave
'[ _ irc-tab set _ parse-message ] with-output-stream ;
irc-editor "general" f {
{ T{ key-down f f "RET" } editor-send }
{ T{ key-down f f "ENTER" } editor-send }
} define-command-map
: new-irc-tab ( chat ui-window class -- irc-tab )
new-frame
swap >>window
swap >>chat
<irc-pane> [ <scroller> @center grid-add ] keep
<irc-editor> <scroller> @bottom grid-add ;
M: irc-tab graft*
[ chat>> ] [ window>> client>> ] bi attach-chat ;
M: irc-tab ungraft*
chat>> detach-chat ;
TUPLE: irc-channel-tab < irc-tab userlist ;
: <irc-channel-tab> ( chat ui-window -- irc-tab )
irc-channel-tab new-irc-tab
<pile> [ <scroller> @right grid-add ] keep >>userlist ;
: update-participants ( tab -- )
[ userlist>> [ clear-gadget ] keep ]
[ chat>> participants>> ] bi
[ +operator+ value-labels dark-green add-gadget-color ]
[ +voice+ value-labels blue add-gadget-color ]
[ +normal+ value-labels black add-gadget-color ] tri drop ;
M: participant-changed handle-inbox
drop update-participants ;
TUPLE: irc-server-tab < irc-tab ;
: <irc-server-tab> ( chat -- irc-tab )
f irc-server-tab new-irc-tab ;
: <irc-nick-tab> ( chat ui-window -- irc-tab )
irc-tab new-irc-tab ;
M: irc-tab pref-dim*
drop { 480 480 } ;
: join-channel ( name ui-window -- )
[ dup <irc-channel-chat> ] dip
[ <irc-channel-tab> swap ] keep
add-page ;
: query-nick ( nick ui-window -- )
[ dup <irc-nick-chat> ] dip
[ <irc-nick-tab> swap ] keep
add-page ;
: irc-window ( ui-window -- )
[ ]
[ client>> profile>> server>> ] bi
open-window ;
: ui-connect ( profile -- ui-window )
<irc-client>
{ [ [ <irc-server-chat> ] dip attach-chat ]
[ chats>> +server-chat+ swap at <irc-server-tab> dup
"Server" associate ui-window new-tabbed [ swap window<< ] keep ]
[ >>client ]
[ connect-irc ] } cleave ;
: server-open ( server port nick password channels -- )
[ <irc-profile> ui-connect [ irc-window ] keep ] dip
[ over join-channel ] each drop ;
: main-run ( -- ) run-ircui ;
MAIN: main-run
"irc.ui.commands" require
]]
FILE: [[irc/ui/commandparser/commandparser.factor]] [[! Copyright (C) 2008 William Schlieper
! See http://factorcode.org/license.txt for BSD license.
USING: kernel vocabs.loader sequences strings splitting words irc.messages ;
IN: irc.ui.commandparser
: command ( string string -- string command )
[ "say" ] when-empty
dup "irc.ui.commands" lookup
[ nip ]
[ " " append prepend "quote" "irc.ui.commands" lookup ] if* ;
: parse-message ( string -- )
"/" ?head [ " " split1 swap command ] [ "say" command ] if execute ;
]]
FILE: [[irc/ui/load/load.factor]] [[! Copyright (C) 2008 William Schlieper
! See http://factorcode.org/license.txt for BSD license.
USING: kernel io.files io.pathnames parser editors sequences ;
IN: irc.ui.load
: file-or ( path path -- path ) [ [ exists? ] keep ] dip ? ;
: personal-ui-rc ( -- path ) home ".ircui-rc" append-path ;
: system-ui-rc ( -- path ) "extra/irc/ui/ircui-rc" resource-path ;
: ircui-rc ( -- path ) personal-ui-rc system-ui-rc file-or ;
: run-ircui ( -- ) ircui-rc run-file ;
]]
FILE: [[irc/ui/summary.txt]] [[A simple IRC client]]
FILE: [[irc/ui/commands/commands.factor]] [[! Copyright (C) 2008 William Schlieper
! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel sequences arrays irc.client
irc.messages irc.ui namespaces ;
IN: irc.ui.commands
: say ( string -- )
irc-tab get
[ window>> client>> profile>> nickname>> <own-message> print-irc ]
[ chat>> speak ] 2bi ;
: me ( string -- ) ! Placeholder until I make /me look different
"ACTION " 1 prefix prepend 1 suffix say ;
: join ( string -- )
irc-tab get window>> join-channel ;
: query ( string -- )
irc-tab get window>> query-nick ;
: whois ( string -- )
"WHOIS" swap { } clone swap <irc-client-message>
irc-tab get listener>> speak ;
: quote ( string -- )
drop ; ! THIS WILL CHANGE
]]
FILE: [[irc/ui/authors.txt]] [[William Schlieper
]]
FILE: [[io/sockets/headers/headers.factor]] [[! Copyright (C) 2007 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.syntax byte-arrays io
io.sockets kernel structs math math.parser
prettyprint sequences ;
IN: io.sockets.headers
C-STRUCT: etherneth
{ { "char" 6 } "dmac" }
{ { "char" 6 } "smac" }
{ "ushort" "type" } ;
: >mac-address ( byte-array -- string )
6 memory>byte-array
[ >hex 2 48 pad-left ] { } map-as ":" join ;
: etherneth. ( etherneth -- )
[ etherneth-dmac "Dest MAC: " write >mac-address . ] keep
[ etherneth-smac "Source MAC: " write >mac-address . ] keep
[ etherneth-type "Type : " write .h ] keep
drop ;
C-STRUCT: iph
{ "uchar" "hl|v" } ! hl is 4 bits, v is 4 bits
{ "uchar" "tos" }
{ "short" "len" }
{ "short" "id" }
{ "short" "off" }
{ "uchar" "ttl" }
{ "uchar" "p" }
{ "ushort" "ip_sum" }
{ "uint" "ip_src" }
{ "uint" "ip_dst" } ;
: iph-hl ( iph -- n )
iph-hl|v -4 shift ;
: iph-v ( iph -- n )
iph-hl|v 0x0f bitand ;
: set-iph-hl ( n iph -- )
[ iph-hl|v 0x0f bitand >r 4 shift r> bitor ] keep
set-iph-hl|v ;
: set-iph-v ( n iph -- )
[ iph-hl|v 0xf0 bitand bitor ] keep
set-iph-hl|v ;
C-STRUCT: icmph
{ "uchar" "type" }
{ "uchar" "code" }
{ "short" "chksum" }
{ "ushort" "id" }
{ "ushort" "seq" } ;
C-STRUCT: udph
{ "ushort" "sport" }
{ "ushort" "dport" }
{ "ushort" "len" }
{ "ushort" "check" } ;
C-STRUCT: tcph
{ "ushort" "sport" }
{ "ushort" "dport" }
{ "uint" "seq" }
{ "uint" "ack" }
{ "uchar" "x2|off" }
{ "uchar" "flags" }
{ "ushort" "win" }
{ "ushort" "sum" }
{ "ushort" "urp" } ;
: tcph-x2 ( iph -- n )
tcph-x2|off -4 shift ;
: tcph-off ( iph -- n )
tcph-x2|off 0x0f bitand ;
: set-tcph-x2 ( n iph -- )
[ tcph-x2|off 0x0f bitand >r 4 shift r> bitor ] keep
set-tcph-x2|off ;
: set-tcph-off ( n iph -- )
[ tcph-x2|off 0x0f bitand bitor ] keep
set-tcph-x2|off ;
]]
FILE: [[io/sockets/headers/bsd/bsd.factor]] [[! Copyright (C) 2007 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.syntax byte-arrays io
kernel math prettyprint ;
IN: io.sockets.headers.bsd
C-STRUCT: bpfh
{ "timeval" "timestamp" }
{ "ulong" "caplen" }
{ "ulong" "datalen" }
{ "ushort" "hdrlen" } ;
: bpfh. ( bpfh -- )
[
bpfh-timestamp "Timestamp: " write
"timeval" heap-size memory>byte-array .
] keep
[ bpfh-caplen "caplen: " write . ] keep
[ bpfh-datalen "datalen: " write . ] keep
[ bpfh-hdrlen "hdrlen: " write . ] keep
drop ;
]]
FILE: [[io/sockets/headers/bsd/authors.txt]] [[Doug Coleman
]]
FILE: [[io/sockets/headers/authors.txt]] [[Doug Coleman
]]
FILE: [[run-desc/run-desc.factor]] [[USING: io io.encodings.utf8 io.launcher kernel sequences ;
IN: run-desc
: run-desc ( desc -- result ) utf8 [ contents [ but-last ] [ f ] if* ] with-process-reader ;
]]
FILE: [[llvm/reader/add.bc]] base64[[QkPA3iEMAAAwAAAAARAAABAAAAAHgSORQcgESQYQMjmSAYQMJQUIGR4Ei2KADEUCQpILQmQQMhQ4CBhJCjJEJEgKkCEjRHKAjAwhhgqKCmQMHwAAUSAAAAkAAAAyIsgIIGWChAAmQ0gFCSZDxgVCMiYIiDkCMCCVAcAIAAAAAABDkgAAAAAAACAMBAAKAAAAEwRBBQLgEA4EAAAABQAAADYwSBRjAcFlAgF2AAXRTBEGAAAAAAAAAHEgAAACAAAABjAAwwAAAAAAAAAA]]
FILE: [[llvm/reader/reader.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.c-types alien.data alien.syntax
destructors kernel llvm.core llvm.engine llvm.jit llvm.wrappers
;
IN: llvm.reader
: buffer>module ( buffer -- module )
[
value>> f void* <ref> f void* <ref>
[ LLVMParseBitcode drop ] 2keep
void* deref [ llvm-throw ] when* void* deref
module new swap >>value
] with-disposal ;
: load-module ( path -- module )
<buffer> buffer>module ;
: load-into-jit ( path name -- )
[ load-module ] dip add-module ;
]]
FILE: [[llvm/reader/add.ll]] [[define i32 @add(i32 %x, i32 %y) {
entry:
%sum = add i32 %x, %y
ret i32 %sum
}
]]
FILE: [[llvm/reader/tags.txt]] [[not tested
]]
FILE: [[llvm/wrappers/wrappers.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.c-types alien.data alien.strings
io.encodings.utf8 destructors kernel
llvm.core llvm.engine ;
IN: llvm.wrappers
: llvm-throw ( c-string -- )
[ utf8 alien>string ] [ LLVMDisposeMessage ] bi throw ;
: <dispose> ( alien class -- disposable ) new swap >>value ;
TUPLE: module value disposed ;
M: module dispose* value>> LLVMDisposeModule ;
: <module> ( name -- module )
LLVMModuleCreateWithName module <dispose> ;
TUPLE: provider value module disposed ;
M: provider dispose* value>> LLVMDisposeModuleProvider ;
: (provider) ( module -- provider )
[ value>> LLVMCreateModuleProviderForExistingModule provider <dispose> ]
[ t >>disposed value>> ] bi
>>module ;
: <provider> ( module -- provider )
[ (provider) ] with-disposal ;
TUPLE: engine value disposed ;
M: engine dispose* value>> LLVMDisposeExecutionEngine ;
: (engine) ( provider -- engine )
[
value>> f void* <ref> f void* <ref>
[ swapd 0 swap LLVMCreateJITCompiler drop ] 2keep
void* deref [ llvm-throw ] when* void* deref
]
[ t >>disposed drop ] bi
engine <dispose> ;
: <engine> ( provider -- engine )
[ (engine) ] with-disposal ;
: (add-block) ( name -- basic-block )
"function" swap LLVMAppendBasicBlock ;
TUPLE: builder value disposed ;
M: builder dispose* value>> LLVMDisposeBuilder ;
: <builder> ( name -- builder )
(add-block) LLVMCreateBuilder [ swap LLVMPositionBuilderAtEnd ] keep
builder <dispose> ;
TUPLE: buffer value disposed ;
M: buffer dispose* value>> LLVMDisposeMemoryBuffer ;
: <buffer> ( path -- module )
f void* <ref> f void* <ref>
[ LLVMCreateMemoryBufferWithContentsOfFile drop ] 2keep
void* deref [ llvm-throw ] when* void* deref buffer <dispose> ;
]]
FILE: [[llvm/wrappers/wrappers-tests.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: destructors kernel llvm.wrappers sequences tools.test vocabs ;
{ } [ "test" <module> dispose ] unit-test
{ } [ "test" <module> <provider> dispose ] unit-test
{ } [ "llvm.jit" vocabs member? [ "test" <module> <provider> <engine> dispose ] unless ] unit-test
]]
FILE: [[llvm/wrappers/tags.txt]] [[not tested
]]
FILE: [[llvm/clang/ffi/platforms.txt]] [[unix]]
FILE: [[llvm/clang/ffi/ffi.factor]] [[USING: alien alien.c-types alien.libraries alien.syntax
classes.struct combinators system unix.types ;
IN: llvm.clang.ffi
<<
"libclang" {
{ [ os macosx? ] [ "libclang.dylib" ] }
{ [ os windows? ] [ "clang.dll" ] }
{ [ os unix? ] [ "/usrlibclang.so" ] }
} cond cdecl add-library
>>
LIBRARY: libclang
C-TYPE: CXTranslationUnitImpl
TYPEDEF: void* CXIndex
TYPEDEF: CXTranslationUnitImpl* CXTranslationUnit
TYPEDEF: void* CXClientData
STRUCT: CXUnsavedFile
{ Filename c-string }
{ Contents c-string }
{ Length ulong } ;
ENUM: CXAvailabilityKind
CXAvailability_Available
CXAvailability_Deprecated
CXAvailability_NotAvailable ;
STRUCT: CXString
{ data void* }
{ private_flags uint } ;
FUNCTION: c-string clang_getCString ( CXString string ) ;
FUNCTION: void clang_disposeString ( CXString string ) ;
FUNCTION: CXIndex clang_createIndex ( int excludeDeclarationsFromPCH,
int displayDiagnostics ) ;
FUNCTION: void clang_disposeIndex ( CXIndex index ) ;
TYPEDEF: void* CXFile
FUNCTION: CXString clang_getFileName ( CXFile SFile ) ;
FUNCTION: time_t clang_getFileTime ( CXFile SFile ) ;
FUNCTION: uint clang_isFileMultipleIncludeGuarded ( CXTranslationUnit tu, CXFile file ) ;
FUNCTION: CXFile clang_getFile ( CXTranslationUnit tu, c-string file_name ) ;
STRUCT: CXSourceLocation
{ ptr_data void*[2] }
{ int_data uint } ;
STRUCT: CXSourceRange
{ ptr_data void*[2] }
{ begin_int_data uint }
{ end_int_data uint } ;
FUNCTION: CXSourceLocation clang_getNullLocation ( ) ;
FUNCTION: uint clang_equalLocations ( CXSourceLocation loc1, CXSourceLocation loc2 ) ;
FUNCTION: CXSourceLocation clang_getLocation ( CXTranslationUnit tu, CXFile file, uint line, uint column ) ;
FUNCTION: CXSourceLocation clang_getLocationForOffset ( CXTranslationUnit tu,
CXFile file,
uint offset ) ;
FUNCTION: CXSourceRange clang_getNullRange ( ) ;
FUNCTION: CXSourceRange clang_getRange ( CXSourceLocation begin,
CXSourceLocation end ) ;
FUNCTION: void clang_getInstantiationLocation ( CXSourceLocation location,
CXFile* file,
uint* line,
uint* column,
uint* offset ) ;
FUNCTION: void clang_getSpellingLocation ( CXSourceLocation location,
CXFile* file,
uint* line,
uint* column,
uint* offset ) ;
FUNCTION: CXSourceLocation clang_getRangeStart ( CXSourceRange range ) ;
FUNCTION: CXSourceLocation clang_getRangeEnd ( CXSourceRange range ) ;
ENUM: CXDiagnosticSeverity
CXDiagnostic_Ignored
CXDiagnostic_Note
CXDiagnostic_Warning
CXDiagnostic_Error
CXDiagnostic_Fatal ;
TYPEDEF: void* CXDiagnostic
FUNCTION: uint clang_getNumDiagnostics ( CXTranslationUnit Unit ) ;
FUNCTION: CXDiagnostic clang_getDiagnostic ( CXTranslationUnit Unit,
uint Index ) ;
FUNCTION: void clang_disposeDiagnostic ( CXDiagnostic Diagnostic ) ;
ENUM: CXDiagnosticDisplayOptions
{ CXDiagnostic_DisplaySourceLocation 0x01 }
{ CXDiagnostic_DisplayColumn 0x02 }
{ CXDiagnostic_DisplaySourceRanges 0x04 }
{ CXDiagnostic_DisplayOption 0x08 }
{ CXDiagnostic_DisplayCategoryId 0x10 }
{ CXDiagnostic_DisplayCategoryName 0x20 } ;
FUNCTION: CXString clang_formatDiagnostic ( CXDiagnostic Diagnostic,
uint Options ) ;
FUNCTION: uint clang_defaultDiagnosticDisplayOptions ( ) ;
FUNCTION: CXDiagnosticSeverity clang_getDiagnosticSeverity ( CXDiagnostic ) ;
FUNCTION: CXSourceLocation clang_getDiagnosticLocation ( CXDiagnostic ) ;
FUNCTION: CXString clang_getDiagnosticSpelling ( CXDiagnostic ) ;
FUNCTION: CXString clang_getDiagnosticOption ( CXDiagnostic Diag, CXString* Disable ) ;
FUNCTION: uint clang_getDiagnosticCategory ( CXDiagnostic ) ;
FUNCTION: CXString clang_getDiagnosticCategoryName ( uint Category ) ;
FUNCTION: uint clang_getDiagnosticNumRanges ( CXDiagnostic ) ;
FUNCTION: CXSourceRange clang_getDiagnosticRange ( CXDiagnostic Diagnostic, uint Range ) ;
FUNCTION: uint clang_getDiagnosticNumFixIts ( CXDiagnostic Diagnostic ) ;
FUNCTION: CXString clang_getDiagnosticFixIt ( CXDiagnostic Diagnostic,
uint FixIt,
CXSourceRange* ReplacementRange ) ;
FUNCTION: CXString clang_getTranslationUnitSpelling ( CXTranslationUnit CTUnit ) ;
FUNCTION: CXTranslationUnit clang_createTranslationUnitFromSourceFile ( CXIndex CIdx,
c-string source_filename,
int num_clang_command_line_args,
char** clang_command_line_args,
uint num_unsaved_files,
CXUnsavedFile* unsaved_files ) ;
FUNCTION: CXTranslationUnit clang_createTranslationUnit ( CXIndex CIdx, c-string ast_filename ) ;
ENUM: CXTranslationUnit_Flags
{ CXTranslationUnit_None 0x00 }
{ CXTranslationUnit_DetailedPreprocessingRecord 0x01 }
{ CXTranslationUnit_Incomplete 0x02 }
{ CXTranslationUnit_PrecompiledPreamble 0x04 }
{ CXTranslationUnit_CacheCompletionResults 0x08 }
{ CXTranslationUnit_CXXPrecompiledPreamble 0x10 }
{ CXTranslationUnit_CXXChainedPCH 0x20 }
{ CXTranslationUnit_NestedMacroInstantiations 0x40 } ;
FUNCTION: uint clang_defaultEditingTranslationUnitOptions ( ) ;
FUNCTION: CXTranslationUnit clang_parseTranslationUnit ( CXIndex CIdx,
c-string source_filename,
char** command_line_args,
int num_command_line_args,
CXUnsavedFile* unsaved_files,
uint num_unsaved_files,
uint options ) ;
ENUM: CXSaveTranslationUnit_Flags CXSaveTranslationUnit_None ;
FUNCTION: uint clang_defaultSaveOptions ( CXTranslationUnit TU ) ;
FUNCTION: int clang_saveTranslationUnit ( CXTranslationUnit TU,
c-string FileName,
uint options ) ;
FUNCTION: void clang_disposeTranslationUnit ( CXTranslationUnit ) ;
ENUM: CXReparse_Flags CXReparse_None ;
FUNCTION: uint clang_defaultReparseOptions ( CXTranslationUnit TU ) ;
FUNCTION: int clang_reparseTranslationUnit ( CXTranslationUnit TU,
uint num_unsaved_files,
CXUnsavedFile* unsaved_files,
uint options ) ;
ENUM: CXTUResourceUsageKind
{ CXTUResourceUsage_AST 1 }
{ CXTUResourceUsage_Identifiers 2 }
{ CXTUResourceUsage_Selectors 3 }
{ CXTUResourceUsage_GlobalCompletionResults 4 }
{ CXTUResourceUsage_SourceManagerContentCache 5 }
{ CXTUResourceUsage_AST_SideTables 6 }
{ CXTUResourceUsage_SourceManager_Membuffer_Malloc 7 }
{ CXTUResourceUsage_SourceManager_Membuffer_MMap 8 }
{ CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc 9 }
{ CXTUResourceUsage_ExternalASTSource_Membuffer_MMap 10 }
{ CXTUResourceUsage_Preprocessor 11 }
{ CXTUResourceUsage_PreprocessingRecord 12 }
{ CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN 1 }
{ CXTUResourceUsage_MEMORY_IN_BYTES_END 12 }
{ CXTUResourceUsage_First 1 }
{ CXTUResourceUsage_Last 12 } ;
FUNCTION: c-string clang_getTUResourceUsageName ( CXTUResourceUsageKind kind ) ;
STRUCT: CXTUResourceUsageEntry
{ kind CXTUResourceUsageKind }
{ amount ulong } ;
STRUCT: CXTUResourceUsage
{ data void* }
{ numEntries uint }
{ entries CXTUResourceUsageEntry* } ;
FUNCTION: CXTUResourceUsage clang_getCXTUResourceUsage ( CXTranslationUnit TU ) ;
FUNCTION: void clang_disposeCXTUResourceUsage ( CXTUResourceUsage usage ) ;
ENUM: CXCursorKind
{ CXCursor_UnexposedDecl 1 }
{ CXCursor_StructDecl 2 }
{ CXCursor_UnionDecl 3 }
{ CXCursor_ClassDecl 4 }
{ CXCursor_EnumDecl 5 }
{ CXCursor_FieldDecl 6 }
{ CXCursor_EnumConstantDecl 7 }
{ CXCursor_FunctionDecl 8 }
{ CXCursor_VarDecl 9 }
{ CXCursor_ParmDecl 10 }
{ CXCursor_ObjCInterfaceDecl 11 }
{ CXCursor_ObjCCategoryDecl 12 }
{ CXCursor_ObjCProtocolDecl 13 }
{ CXCursor_ObjCPropertyDecl 14 }
{ CXCursor_ObjCIvarDecl 15 }
{ CXCursor_ObjCInstanceMethodDecl 16 }
{ CXCursor_ObjCClassMethodDecl 17 }
{ CXCursor_ObjCImplementationDecl 18 }
{ CXCursor_ObjCCategoryImplDecl 19 }
{ CXCursor_TypedefDecl 20 }
{ CXCursor_CXXMethod 21 }
{ CXCursor_Namespace 22 }
{ CXCursor_LinkageSpec 23 }
{ CXCursor_Constructor 24 }
{ CXCursor_Destructor 25 }
{ CXCursor_ConversionFunction 26 }
{ CXCursor_TemplateTypeParameter 27 }
{ CXCursor_NonTypeTemplateParameter 28 }
{ CXCursor_TemplateTemplateParameter 29 }
{ CXCursor_FunctionTemplate 30 }
{ CXCursor_ClassTemplate 31 }
{ CXCursor_ClassTemplatePartialSpecialization 32 }
{ CXCursor_NamespaceAlias 33 }
{ CXCursor_UsingDirective 34 }
{ CXCursor_UsingDeclaration 35 }
{ CXCursor_TypeAliasDecl 36 }
{ CXCursor_FirstDecl 1 }
{ CXCursor_LastDecl 36 }
{ CXCursor_FirstRef 40 }
{ CXCursor_ObjCSuperClassRef 40 }
{ CXCursor_ObjCProtocolRef 41 }
{ CXCursor_ObjCClassRef 42 }
{ CXCursor_TypeRef 43 }
{ CXCursor_CXXBaseSpecifier 44 }
{ CXCursor_TemplateRef 45 }
{ CXCursor_NamespaceRef 46 }
{ CXCursor_MemberRef 47 }
{ CXCursor_LabelRef 48 }
{ CXCursor_OverloadedDeclRef 49 }
{ CXCursor_LastRef 49 }
{ CXCursor_FirstInvalid 70 }
{ CXCursor_InvalidFile 70 }
{ CXCursor_NoDeclFound 71 }
{ CXCursor_NotImplemented 72 }
{ CXCursor_InvalidCode 73 }
{ CXCursor_LastInvalid 73 }
{ CXCursor_FirstExpr 100 }
{ CXCursor_UnexposedExpr 100 }
{ CXCursor_DeclRefExpr 101 }
{ CXCursor_MemberRefExpr 102 }
{ CXCursor_CallExpr 103 }
{ CXCursor_ObjCMessageExpr 104 }
{ CXCursor_BlockExpr 105 }
{ CXCursor_LastExpr 105 }
{ CXCursor_FirstStmt 200 }
{ CXCursor_UnexposedStmt 200 }
{ CXCursor_LabelStmt 201 }
{ CXCursor_LastStmt 201 }
{ CXCursor_TranslationUnit 300 }
{ CXCursor_FirstAttr 400 }
{ CXCursor_UnexposedAttr 400 }
{ CXCursor_IBActionAttr 401 }
{ CXCursor_IBOutletAttr 402 }
{ CXCursor_IBOutletCollectionAttr 403 }
{ CXCursor_LastAttr 403 }
{ CXCursor_PreprocessingDirective 500 }
{ CXCursor_MacroDefinition 501 }
{ CXCursor_MacroInstantiation 502 }
{ CXCursor_InclusionDirective 503 }
{ CXCursor_FirstPreprocessing 500 }
{ CXCursor_LastPreprocessing 503 } ;
STRUCT: CXCursor
{ kind CXCursorKind }
{ data void*[3] } ;
FUNCTION: CXCursor clang_getNullCursor ( ) ;
FUNCTION: CXCursor clang_getTranslationUnitCursor ( CXTranslationUnit ) ;
FUNCTION: uint clang_equalCursors ( CXCursor c1, CXCursor c2 ) ;
FUNCTION: uint clang_hashCursor ( CXCursor ) ;
FUNCTION: CXCursorKind clang_getCursorKind ( CXCursor ) ;
FUNCTION: uint clang_isDeclaration ( CXCursorKind ) ;
FUNCTION: uint clang_isReference ( CXCursorKind ) ;
FUNCTION: uint clang_isExpression ( CXCursorKind ) ;
FUNCTION: uint clang_isStatement ( CXCursorKind ) ;
FUNCTION: uint clang_isInvalid ( CXCursorKind ) ;
FUNCTION: uint clang_isTranslationUnit ( CXCursorKind ) ;
FUNCTION: uint clang_isPreprocessing ( CXCursorKind ) ;
FUNCTION: uint clang_isUnexposed ( CXCursorKind ) ;
ENUM: CXLinkageKind
CXLinkage_Invalid
CXLinkage_NoLinkage
CXLinkage_Internal
CXLinkage_UniqueExternal
CXLinkage_External ;
ENUM: CXLanguageKind
CXLanguage_Invalid
CXLanguage_C
CXLanguage_ObjC
CXLanguage_CPlusPlus ;
FUNCTION: CXLinkageKind clang_getCursorLinkage ( CXCursor cursor ) ;
FUNCTION: CXAvailabilityKind clang_getCursorAvailability ( CXCursor cursor ) ;
FUNCTION: CXLanguageKind clang_getCursorLanguage ( CXCursor cursor ) ;
C-TYPE: CXCursorSetImpl
TYPEDEF: CXCursorSetImpl* CXCursorSet
FUNCTION: CXCursorSet clang_createCXCursorSet ( ) ;
FUNCTION: void clang_disposeCXCursorSet ( CXCursorSet cset ) ;
FUNCTION: uint clang_CXCursorSet_contains ( CXCursorSet cset, CXCursor cursor ) ;
FUNCTION: uint clang_CXCursorSet_insert ( CXCursorSet cset, CXCursor cursor ) ;
FUNCTION: CXCursor clang_getCursorSemanticParent ( CXCursor cursor ) ;
FUNCTION: CXCursor clang_getCursorLexicalParent ( CXCursor cursor ) ;
FUNCTION: void clang_getOverriddenCursors ( CXCursor cursor, CXCursor** overridden, uint* num_overridden ) ;
FUNCTION: void clang_disposeOverriddenCursors ( CXCursor* overridden ) ;
FUNCTION: CXFile clang_getIncludedFile ( CXCursor cursor ) ;
FUNCTION: CXCursor clang_getCursor ( CXTranslationUnit TU,
CXSourceLocation location ) ;
FUNCTION: CXSourceLocation clang_getCursorLocation ( CXCursor ) ;
FUNCTION: CXSourceRange clang_getCursorExtent ( CXCursor ) ;
ENUM: CXTypeKind
{ CXType_Invalid 0 }
{ CXType_Unexposed 1 }
{ CXType_Void 2 }
{ CXType_Bool 3 }
{ CXType_Char_U 4 }
{ CXType_UChar 5 }
{ CXType_Char16 6 }
{ CXType_Char32 7 }
{ CXType_UShort 8 }
{ CXType_UInt 9 }
{ CXType_ULong 10 }
{ CXType_ULongLong 11 }
{ CXType_UInt128 12 }
{ CXType_Char_S 13 }
{ CXType_SChar 14 }
{ CXType_WChar 15 }
{ CXType_Short 16 }
{ CXType_Int 17 }
{ CXType_Long 18 }
{ CXType_LongLong 19 }
{ CXType_Int128 20 }
{ CXType_Float 21 }
{ CXType_Double 22 }
{ CXType_LongDouble 23 }
{ CXType_NullPtr 24 }
{ CXType_Overload 25 }
{ CXType_Dependent 26 }
{ CXType_ObjCId 27 }
{ CXType_ObjCClass 28 }
{ CXType_ObjCSel 29 }
{ CXType_FirstBuiltin 2 }
{ CXType_LastBuiltin 29 }
{ CXType_Complex 100 }
{ CXType_Pointer 101 }
{ CXType_BlockPointer 102 }
{ CXType_LValueReference 103 }
{ CXType_RValueReference 104 }
{ CXType_Record 105 }
{ CXType_Enum 106 }
{ CXType_Typedef 107 }
{ CXType_ObjCInterface 108 }
{ CXType_ObjCObjectPointer 109 }
{ CXType_FunctionNoProto 110 }
{ CXType_FunctionProto 111 } ;
STRUCT: CXType
{ kind CXTypeKind }
{ data void*[2] } ;
FUNCTION: CXType clang_getCursorType ( CXCursor C ) ;
FUNCTION: uint clang_equalTypes ( CXType A, CXType B ) ;
FUNCTION: CXType clang_getCanonicalType ( CXType T ) ;
FUNCTION: uint clang_isConstQualifiedType ( CXType T ) ;
FUNCTION: uint clang_isVolatileQualifiedType ( CXType T ) ;
FUNCTION: uint clang_isRestrictQualifiedType ( CXType T ) ;
FUNCTION: CXType clang_getPointeeType ( CXType T ) ;
FUNCTION: CXCursor clang_getTypeDeclaration ( CXType T ) ;
FUNCTION: CXString clang_getDeclObjCTypeEncoding ( CXCursor C ) ;
FUNCTION: CXString clang_getTypeKindSpelling ( CXTypeKind K ) ;
FUNCTION: CXType clang_getResultType ( CXType T ) ;
FUNCTION: CXType clang_getCursorResultType ( CXCursor C ) ;
FUNCTION: uint clang_isPODType ( CXType T ) ;
FUNCTION: uint clang_isVirtualBase ( CXCursor ) ;
ENUM: CX_CXXAccessSpecifier
CX_CXXInvalidAccessSpecifier
CX_CXXPublic
CX_CXXProtected
CX_CXXPrivate ;
FUNCTION: CX_CXXAccessSpecifier clang_getCXXAccessSpecifier ( CXCursor ) ;
FUNCTION: uint clang_getNumOverloadedDecls ( CXCursor cursor ) ;
FUNCTION: CXCursor clang_getOverloadedDecl ( CXCursor cursor, uint index ) ;
FUNCTION: CXType clang_getIBOutletCollectionType ( CXCursor ) ;
ENUM: CXChildVisitResult
CXChildVisit_Break
CXChildVisit_Continue
CXChildVisit_Recurse ;
CALLBACK: CXChildVisitResult CXCursorVisitor ( CXCursor cursor,
CXCursor parent,
CXClientData client_data ) ;
FUNCTION: uint clang_visitChildren ( CXCursor parent,
CXCursorVisitor visitor,
CXClientData client_data ) ;
FUNCTION: CXString clang_getCursorUSR ( CXCursor ) ;
FUNCTION: CXString clang_constructUSR_ObjCClass ( c-string class_name ) ;
FUNCTION: CXString clang_constructUSR_ObjCCategory ( c-string class_name,
c-string category_name ) ;
FUNCTION: CXString clang_constructUSR_ObjCProtocol ( c-string protocol_name ) ;
FUNCTION: CXString clang_constructUSR_ObjCIvar ( c-string name,
CXString classUSR ) ;
FUNCTION: CXString clang_constructUSR_ObjCMethod ( c-string name,
uint isInstanceMethod,
CXString classUSR ) ;
FUNCTION: CXString clang_constructUSR_ObjCProperty ( c-string property,
CXString classUSR ) ;
FUNCTION: CXString clang_getCursorSpelling ( CXCursor ) ;
FUNCTION: CXString clang_getCursorDisplayName ( CXCursor ) ;
FUNCTION: CXCursor clang_getCursorReferenced ( CXCursor ) ;
FUNCTION: CXCursor clang_getCursorDefinition ( CXCursor ) ;
FUNCTION: uint clang_isCursorDefinition ( CXCursor ) ;
FUNCTION: CXCursor clang_getCanonicalCursor ( CXCursor ) ;
FUNCTION: uint clang_CXXMethod_isStatic ( CXCursor C ) ;
FUNCTION: uint clang_CXXMethod_isVirtual ( CXCursor C ) ;
FUNCTION: CXCursorKind clang_getTemplateCursorKind ( CXCursor C ) ;
FUNCTION: CXCursor clang_getSpecializedCursorTemplate ( CXCursor C ) ;
ENUM: CXTokenKind
CXToken_Punctuation
CXToken_Keyword
CXToken_Identifier
CXToken_Literal
CXToken_Comment ;
STRUCT: CXToken
{ int_data uint[4] }
{ ptr_data void* } ;
FUNCTION: CXTokenKind clang_getTokenKind ( CXToken ) ;
FUNCTION: CXString clang_getTokenSpelling ( CXTranslationUnit TU,
CXToken Token ) ;
FUNCTION: CXSourceLocation clang_getTokenLocation ( CXTranslationUnit TU,
CXToken Token ) ;
FUNCTION: CXSourceRange clang_getTokenExtent ( CXTranslationUnit TU,
CXToken Token ) ;
FUNCTION: void clang_tokenize ( CXTranslationUnit TU,
CXSourceRange Range,
CXToken** Tokens,
uint* NumTokens ) ;
FUNCTION: void clang_annotateTokens ( CXTranslationUnit TU,
CXToken* Tokens,
uint NumTokens,
CXCursor* Cursors ) ;
FUNCTION: void clang_disposeTokens ( CXTranslationUnit TU,
CXToken* Tokens,
uint NumTokens ) ;
FUNCTION: CXString clang_getCursorKindSpelling ( CXCursorKind Kind ) ;
FUNCTION: void clang_getDefinitionSpellingAndExtent ( CXCursor cursor,
char** startBuf,
char** endBuf,
uint* startLine,
uint* startColumn,
uint* endLine,
uint* endColumn ) ;
FUNCTION: void clang_enableStackTraces ( ) ;
CALLBACK: void executeOnThreadCallback ( void* ) ;
FUNCTION: void clang_executeOnThread ( executeOnThreadCallback* callback,
void* user_data,
uint stack_size ) ;
TYPEDEF: void* CXCompletionString
STRUCT: CXCompletionResult
{ CursorKind CXCursorKind }
{ CompletionString CXCompletionString } ;
ENUM: CXCompletionChunkKind
CXCompletionChunk_Optional
CXCompletionChunk_TypedText
CXCompletionChunk_Text
CXCompletionChunk_Placeholder
CXCompletionChunk_Informative
CXCompletionChunk_CurrentParameter
CXCompletionChunk_LeftParen
CXCompletionChunk_RightParen
CXCompletionChunk_LeftBracket
CXCompletionChunk_RightBracket
CXCompletionChunk_LeftBrace
CXCompletionChunk_RightBrace
CXCompletionChunk_LeftAngle
CXCompletionChunk_RightAngle
CXCompletionChunk_Comma
CXCompletionChunk_ResultType
CXCompletionChunk_Colon
CXCompletionChunk_SemiColon
CXCompletionChunk_Equal
CXCompletionChunk_HorizontalSpace
CXCompletionChunk_VerticalSpace ;
FUNCTION: CXCompletionChunkKind clang_getCompletionChunkKind ( CXCompletionString completion_string,
uint chunk_number ) ;
FUNCTION: CXString clang_getCompletionChunkText ( CXCompletionString completion_string,
uint chunk_number ) ;
FUNCTION: CXCompletionString clang_getCompletionChunkCompletionString ( CXCompletionString completion_string,
uint chunk_number ) ;
FUNCTION: uint clang_getNumCompletionChunks ( CXCompletionString completion_string ) ;
FUNCTION: uint clang_getCompletionPriority ( CXCompletionString completion_string ) ;
FUNCTION: CXAvailabilityKind clang_getCompletionAvailability ( CXCompletionString completion_string ) ;
STRUCT: CXCodeCompleteResults
{ Results CXCompletionResult* }
{ NumResults uint } ;
ENUM: CXCodeComplete_Flags
{ CXCodeComplete_IncludeMacros 1 }
{ CXCodeComplete_IncludeCodePatterns 2 } ;
FUNCTION: uint clang_defaultCodeCompleteOptions ( ) ;
FUNCTION: CXCodeCompleteResults* clang_codeCompleteAt ( CXTranslationUnit TU,
c-string complete_filename,
uint complete_line,
uint complete_column,
CXUnsavedFile* unsaved_files,
uint num_unsaved_files,
uint options ) ;
FUNCTION: void clang_sortCodeCompletionResults ( CXCompletionResult* Results, uint NumResults ) ;
FUNCTION: void clang_disposeCodeCompleteResults ( CXCodeCompleteResults* Results ) ;
FUNCTION: uint clang_codeCompleteGetNumDiagnostics ( CXCodeCompleteResults* Results ) ;
FUNCTION: CXDiagnostic clang_codeCompleteGetDiagnostic ( CXCodeCompleteResults* Results,
uint Index ) ;
FUNCTION: CXString clang_getClangVersion ( ) ;
FUNCTION: void clang_toggleCrashRecovery ( uint isEnabled ) ;
CALLBACK: void CXInclusionVisitor ( CXFile included_file,
CXSourceLocation* inclusion_stack,
uint include_len,
CXClientData client_data ) ;
FUNCTION: void clang_getInclusions ( CXTranslationUnit tu,
CXInclusionVisitor visitor,
CXClientData client_data ) ;
]]
FILE: [[llvm/types/types-tests.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel llvm.types sequences tools.test ;
{ T{ integer f 32 } } [ " i32 " parse-type ] unit-test
{ float } [ " float " parse-type ] unit-test
{ T{ pointer f f x86_fp80 } } [ " x86_fp80 * " parse-type ] unit-test
{ T{ vector f f 4 T{ integer f 32 } } } [ " < 4 x i32 > " parse-type ] unit-test
{ T{ struct f f { float double } f } } [ TYPE: { float , double } ; ] unit-test
{ T{ array f f 0 float } } [ TYPE: [ 0 x float ] ; ] unit-test
{ label void metadata }
[ [ " label " " void " " metadata " ] [ parse-type ] each ] unit-test
{ T{ function f f float { float float } t } }
[ TYPE: float ( float , float , ... ) ; ] unit-test
{ T{ struct f f { float TYPE: i32 (i32)* ; } t } }
[ TYPE: < { float, i32 (i32)* } > ; ] unit-test
{ t } [ TYPE: i32 ; TYPE: i32 ; [ >tref ] same? ] unit-test
{ t } [ TYPE: i32 * ; TYPE: i32 * ; [ >tref ] same? ] unit-test
{ TYPE: i32 ; } [ TYPE: i32 ; >tref tref> ] unit-test
{ TYPE: float ; } [ TYPE: float ; >tref tref> ] unit-test
{ TYPE: double ; } [ TYPE: double ; >tref tref> ] unit-test
{ TYPE: x86_fp80 ; } [ TYPE: x86_fp80 ; >tref tref> ] unit-test
{ TYPE: fp128 ; } [ TYPE: fp128 ; >tref tref> ] unit-test
{ TYPE: ppc_fp128 ; } [ TYPE: ppc_fp128 ; >tref tref> ] unit-test
{ TYPE: opaque ; } [ TYPE: opaque ; >tref tref> ] unit-test
{ TYPE: label ; } [ TYPE: label ; >tref tref> ] unit-test
{ TYPE: void ; } [ TYPE: void ; >tref tref> ] unit-test
{ TYPE: i32* ; } [ TYPE: i32* ; >tref tref> ] unit-test
{ TYPE: < 2 x i32 > ; } [ TYPE: < 2 x i32 > ; >tref tref> ] unit-test
{ TYPE: [ 0 x i32 ] ; } [ TYPE: [ 0 x i32 ] ; >tref tref> ] unit-test
{ TYPE: { i32, i32 } ; } [ TYPE: { i32, i32 } ; >tref tref> ] unit-test
{ TYPE: < { i32, i32 } > ; } [ TYPE: < { i32, i32 } > ; >tref tref> ] unit-test
{ TYPE: i32 ( i32 ) ; } [ TYPE: i32 ( i32 ) ; >tref tref> ] unit-test
{ TYPE: \1* ; } [ TYPE: \1* ; >tref tref> ] unit-test
{ TYPE: { i32, \2* } ; } [ TYPE: { i32, \2* } ; >tref tref> ] unit-test
]]
FILE: [[llvm/types/types.factor]] [=[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.c-types alien.data arrays combinators
kernel llvm.core locals math.parser math multiline namespaces
parser peg.ebnf sequences sequences.deep specialized-arrays
strings vocabs words ;
SPECIALIZED-ARRAY: void*
IN: llvm.types
! Type resolution strategy:
! pass 1:
! create the type with uprefs mapped to opaque types
! cache typerefs in enclosing types for pass 2
! if our type is concrete, then we are done
!
! pass 2:
! wrap our abstract type in a type handle
! create a second type, using the cached enclosing type info
! resolve the first type to the second
!
GENERIC: (>tref) ( type -- LLVMTypeRef )
GENERIC: ((tref>)) ( LLVMTypeRef type -- type )
GENERIC: c-type ( type -- str )
! default implementation for simple types
M: object ((tref>)) nip ;
: unsupported-type ( -- )
"cannot generate c-type: unsupported llvm type" throw ;
M: object c-type unsupported-type ;
TUPLE: integer size ;
C: <integer> integer
M: integer (>tref) size>> LLVMIntType ;
M: integer ((tref>)) swap LLVMGetIntTypeWidth >>size ;
M: integer c-type size>> {
{ 64 [ "longlong" ] }
{ 32 [ "int" ] }
{ 16 [ "short" ] }
{ 8 [ "char" ] }
[ unsupported-type ]
} case ;
SINGLETONS: float double x86_fp80 fp128 ppc_fp128 ;
M: float (>tref) drop LLVMFloatType ;
M: double (>tref) drop LLVMDoubleType ;
M: double c-type drop "double" ;
M: x86_fp80 (>tref) drop LLVMX86FP80Type ;
M: fp128 (>tref) drop LLVMFP128Type ;
M: ppc_fp128 (>tref) drop LLVMPPCFP128Type ;
SINGLETONS: opaque label void metadata ;
M: opaque (>tref) drop LLVMOpaqueType ;
M: label (>tref) drop LLVMLabelType ;
M: void (>tref) drop LLVMVoidType ;
M: void c-type drop "void" ;
M: metadata (>tref) drop
"metadata types unsupported by llvm c bindings" throw ;
! enclosing types cache their llvm refs during
! the first pass, used in the second pass to
! resolve uprefs
TUPLE: enclosing cached ;
GENERIC: clean ( type -- )
GENERIC: clean* ( type -- )
M: object clean drop ;
M: enclosing clean f >>cached clean* ;
! builds the stack of types that uprefs need to refer to
SYMBOL: types
:: push-type ( type quot: ( type -- LLVMTypeRef ) -- LLVMTypeRef )
type types get push
type quot call( type -- LLVMTypeRef )
types get pop over >>cached drop ;
DEFER: <up-ref>
:: push-ref ( ref quot: ( LLVMTypeRef -- type ) -- type )
ref types get index
[ types get length swap - <up-ref> ] [
ref types get push
ref quot call( LLVMTypeRef -- type )
types get pop drop
] if* ;
GENERIC: (>tref)* ( type -- LLVMTypeRef )
M: enclosing (>tref) [ (>tref)* ] push-type ;
DEFER: type-kind
GENERIC: (tref>)* ( LLVMTypeRef type -- type )
M: enclosing ((tref>)) [ (tref>)* ] curry push-ref ;
: (tref>) ( LLVMTypeRef -- type ) dup type-kind ((tref>)) ;
TUPLE: pointer < enclosing type ;
: <pointer> ( t -- o ) pointer new swap >>type ;
M: pointer (>tref)* type>> (>tref) 0 LLVMPointerType ;
M: pointer clean* type>> clean ;
M: pointer (tref>)* swap LLVMGetElementType (tref>) >>type ;
M: pointer c-type type>> 8 <integer> = "c-string" "void*" ? ;
TUPLE: vector < enclosing size type ;
: <vector> ( s t -- o )
vector new
swap >>type swap >>size ;
M: vector (>tref)* [ type>> (>tref) ] [ size>> ] bi LLVMVectorType ;
M: vector clean* type>> clean ;
M: vector (tref>)*
over LLVMGetElementType (tref>) >>type
swap LLVMGetVectorSize >>size ;
TUPLE: struct < enclosing types packed? ;
: <struct> ( ts p? -- o )
struct new
swap >>packed? swap >>types ;
M: struct (>tref)*
[ types>> [ (>tref) ] map void* >c-array ]
[ types>> length ]
[ packed?>> 1 0 ? ] tri LLVMStructType ;
M: struct clean* types>> [ clean ] each ;
M: struct (tref>)*
over LLVMIsPackedStruct 0 = not >>packed?
swap dup LLVMCountStructElementTypes void* <c-array>
[ LLVMGetStructElementTypes ] keep >array
[ (tref>) ] map >>types ;
TUPLE: array < enclosing size type ;
: <array> ( s t -- o )
array new
swap >>type swap >>size ;
M: array (>tref)* [ type>> (>tref) ] [ size>> ] bi LLVMArrayType ;
M: array clean* type>> clean ;
M: array (tref>)*
over LLVMGetElementType (tref>) >>type
swap LLVMGetArrayLength >>size ;
SYMBOL: ...
TUPLE: function < enclosing return params vararg? ;
: <function> ( ret params var? -- o )
function new
swap >>vararg? swap >>params swap >>return ;
M: function (>tref)* {
[ return>> (>tref) ]
[ params>> [ (>tref) ] map void* >c-array ]
[ params>> length ]
[ vararg?>> 1 0 ? ]
} cleave LLVMFunctionType ;
M: function clean* [ return>> clean ] [ params>> [ clean ] each ] bi ;
M: function (tref>)*
over LLVMIsFunctionVarArg 0 = not >>vararg?
over LLVMGetReturnType (tref>) >>return
swap dup LLVMCountParamTypes void* <c-array>
[ LLVMGetParamTypes ] keep >array
[ (tref>) ] map >>params ;
: type-kind ( LLVMTypeRef -- class )
LLVMGetTypeKind {
{ LLVMVoidTypeKind [ void ] }
{ LLVMFloatTypeKind [ float ] }
{ LLVMDoubleTypeKind [ double ] }
{ LLVMX86_FP80TypeKind [ x86_fp80 ] }
{ LLVMFP128TypeKind [ fp128 ] }
{ LLVMPPC_FP128TypeKind [ ppc_fp128 ] }
{ LLVMLabelTypeKind [ label ] }
{ LLVMIntegerTypeKind [ integer new ] }
{ LLVMFunctionTypeKind [ function new ] }
{ LLVMStructTypeKind [ struct new ] }
{ LLVMArrayTypeKind [ array new ] }
{ LLVMPointerTypeKind [ pointer new ] }
{ LLVMOpaqueTypeKind [ opaque ] }
{ LLVMVectorTypeKind [ vector new ] }
} case ;
TUPLE: up-ref height ;
C: <up-ref> up-ref
M: up-ref (>tref)
types get length swap height>> - types get nth
cached>> [ LLVMOpaqueType ] unless* ;
: resolve-types ( typeref typeref -- typeref )
over LLVMCreateTypeHandle [ LLVMRefineType ] dip
[ LLVMResolveTypeHandle ] keep LLVMDisposeTypeHandle ;
: >tref-caching ( type -- LLVMTypeRef )
V{ } clone types [ (>tref) ] with-variable ;
: >tref ( type -- LLVMTypeRef )
[ >tref-caching ] [ >tref-caching ] [ clean ] tri
2dup = [ drop ] [ resolve-types ] if ;
: tref> ( LLVMTypeRef -- type )
V{ } clone types [ (tref>) ] with-variable ;
: t. ( type -- )
>tref
"type-info" LLVMModuleCreateWithName
[ "t" rot LLVMAddTypeName drop ]
[ LLVMDumpModule ]
[ LLVMDisposeModule ] tri ;
EBNF: parse-type
WhiteSpace = " "*
Zero = "0" => [[ drop 0 ]]
LeadingDigit = [1-9]
DecimalDigit = [0-9]
Number = LeadingDigit:d (DecimalDigit)*:ds => [[ ds d prefix string>number ]]
WhiteNumberSpace = WhiteSpace Number:n WhiteSpace => [[ n ]]
WhiteZeroSpace = WhiteSpace (Zero | Number):n WhiteSpace => [[ n ]]
Integer = "i" Number:n => [[ n <integer> ]]
FloatingPoint = ( "float" | "double" | "x86_fp80" | "fp128" | "ppc_fp128" ) => [[ "llvm.types" vocab lookup-word ]]
LabelVoidMetadata = ( "label" | "void" | "metadata" | "opaque" ) => [[ "llvm.types" vocab lookup-word ]]
Primitive = LabelVoidMetadata | FloatingPoint
Pointer = T:t WhiteSpace "*" => [[ t <pointer> ]]
Vector = "<" WhiteNumberSpace:n "x" Type:t ">" => [[ n t <vector> ]]
StructureTypesList = "," Type:t => [[ t ]]
Structure = "{" Type:t (StructureTypesList)*:ts "}" => [[ ts t prefix >array f <struct> ]]
Array = "[" WhiteZeroSpace:n "x" Type:t "]" => [[ n t <array> ]]
NoFunctionParams = "(" WhiteSpace ")" => [[ drop { } ]]
VarArgs = WhiteSpace "..." WhiteSpace => [[ drop ... ]]
ParamListContinued = "," (Type | VarArgs):t => [[ t ]]
ParamList = "(" Type:t (ParamListContinued*):ts ")" => [[ ts t prefix ]]
Function = T:t WhiteSpace ( ParamList | NoFunctionParams ):ts => [[ ... ts member? dup [ ... ts remove! drop ] when t ts >array rot <function> ]]
PackedStructure = "<" WhiteSpace "{" Type:ty (StructureTypesList)*:ts "}" WhiteSpace ">" => [[ ts ty prefix >array t <struct> ]]
UpReference = "\\" Number:n => [[ n <up-ref> ]]
Name = '%' ([a-zA-Z][a-zA-Z0-9]*):id => [[ id flatten >string ]]
T = Pointer | Function | Primitive | Integer | Vector | Structure | PackedStructure | Array | UpReference | Name
Type = WhiteSpace T:t WhiteSpace => [[ t ]]
Program = Type
;EBNF
SYNTAX: TYPE: ";" parse-multiline-string parse-type suffix! ;
]=]
FILE: [[llvm/types/tags.txt]] [[not tested
]]
FILE: [[llvm/core/core.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.libraries alien.syntax
combinators kernel sequences system ;
IN: llvm.core
<<
: add-llvm-library ( name -- )
dup {
{ [ os macosx? ] [ "lib" ".dylib" surround ] }
{ [ os unix? ] [ "lib" ".so" surround ] }
{ [ os windows? ] [ ".dll" append ] }
} cond cdecl add-library ;
{ "LLVMSystem" "LLVMSupport" "LLVMCore" "LLVMBitReader" }
[ add-llvm-library ] each
>>
! llvm-c/Core.h
LIBRARY: LLVMCore
TYPEDEF: uint unsigned
TYPEDEF: unsigned enum
ENUM: LLVMAttribute
{ LLVMZExtAttribute 0b1 }
{ LLVMSExtAttribute 0b10 }
{ LLVMNoReturnAttribute 0b100 }
{ LLVMInRegAttribute 0b1000 }
{ LLVMStructRetAttribute 0b10000 }
{ LLVMNoUnwindAttribute 0b100000 }
{ LLVMNoAliasAttribute 0b1000000 }
{ LLVMByValAttribute 0b10000000 }
{ LLVMNestAttribute 0b100000000 }
{ LLVMReadNoneAttribute 0b1000000000 }
{ LLVMReadOnlyAttribute 0b10000000000 } ;
ENUM: LLVMTypeKind
LLVMVoidTypeKind
LLVMFloatTypeKind
LLVMDoubleTypeKind
LLVMX86_FP80TypeKind
LLVMFP128TypeKind
LLVMPPC_FP128TypeKind
LLVMLabelTypeKind
LLVMMetadataTypeKind
LLVMIntegerTypeKind
LLVMFunctionTypeKind
LLVMStructTypeKind
LLVMArrayTypeKind
LLVMPointerTypeKind
LLVMOpaqueTypeKind
LLVMVectorTypeKind ;
ENUM: LLVMLinkage
LLVMExternalLinkage
LLVMLinkOnceLinkage
LLVMWeakLinkage
LLVMAppendingLinkage
LLVMInternalLinkage
LLVMDLLImportLinkage
LLVMDLLExportLinkage
LLVMExternalWeakLinkage
LLVMGhostLinkage ;
ENUM: LLVMVisibility
LLVMDefaultVisibility
LLVMHiddenVisibility
LLVMProtectedVisibility ;
ENUM: LLVMCallConv
{ LLVMCCallConv 0 }
{ LLVMFastCallConv 8 }
{ LLVMColdCallConv 9 }
{ LLVMX86StdcallCallConv 64 }
{ LLVMX86FastcallCallConv 65 } ;
ENUM: LLVMIntPredicate
{ LLVMIntEQ 32 }
{ LLVMIntNE 33 }
{ LLVMIntUGT 34 }
{ LLVMIntUGE 35 }
{ LLVMIntULT 36 }
{ LLVMIntULE 37 }
{ LLVMIntSGT 38 }
{ LLVMIntSGE 39 }
{ LLVMIntSLT 40 }
{ LLVMIntSLE 41 } ;
ENUM: LLVMRealPredicate
LLVMRealPredicateFalse
LLVMRealOEQ
LLVMRealOGT
LLVMRealOGE
LLVMRealOLT
LLVMRealOLE
LLVMRealONE
LLVMRealORD
LLVMRealUNO
LLVMRealUEQ
LLVMRealUGT
LLVMRealUGE
LLVMRealULT
LLVMRealULE
LLVMRealUNE
LLVMRealPredicateTrue ;
! Opaque Types
TYPEDEF: void* LLVMModuleRef
TYPEDEF: void* LLVMPassManagerRef
TYPEDEF: void* LLVMModuleProviderRef
TYPEDEF: void* LLVMTypeRef
TYPEDEF: void* LLVMTypeHandleRef
TYPEDEF: void* LLVMValueRef
TYPEDEF: void* LLVMBasicBlockRef
TYPEDEF: void* LLVMBuilderRef
TYPEDEF: void* LLVMMemoryBufferRef
! Functions
FUNCTION: void LLVMDisposeMessage ( c-string Message ) ;
FUNCTION: LLVMModuleRef LLVMModuleCreateWithName ( c-string ModuleID ) ;
FUNCTION: int LLVMAddTypeName ( LLVMModuleRef M, c-string Name, LLVMTypeRef Ty ) ;
FUNCTION: void LLVMDisposeModule ( LLVMModuleRef M ) ;
FUNCTION: void LLVMDumpModule ( LLVMModuleRef M ) ;
FUNCTION: LLVMModuleProviderRef
LLVMCreateModuleProviderForExistingModule ( LLVMModuleRef M ) ;
FUNCTION: void LLVMDisposeModuleProvider ( LLVMModuleProviderRef MP ) ;
! Types
! LLVM types conform to the following hierarchy:
!
! types:
! integer type
! real type
! function type
! sequence types:
! array type
! pointer type
! vector type
! void type
! label type
! opaque type
! See llvm::LLVMTypeKind::getTypeID.
FUNCTION: LLVMTypeKind LLVMGetTypeKind ( LLVMTypeRef Ty ) ;
! Operations on integer types
FUNCTION: LLVMTypeRef LLVMInt1Type ( ) ;
FUNCTION: LLVMTypeRef LLVMInt8Type ( ) ;
FUNCTION: LLVMTypeRef LLVMInt16Type ( ) ;
FUNCTION: LLVMTypeRef LLVMInt32Type ( ) ;
FUNCTION: LLVMTypeRef LLVMInt64Type ( ) ;
FUNCTION: LLVMTypeRef LLVMIntType ( unsigned NumBits ) ;
FUNCTION: unsigned LLVMGetIntTypeWidth ( LLVMTypeRef IntegerTy ) ;
! Operations on real types
FUNCTION: LLVMTypeRef LLVMFloatType ( ) ;
FUNCTION: LLVMTypeRef LLVMDoubleType ( ) ;
FUNCTION: LLVMTypeRef LLVMX86FP80Type ( ) ;
FUNCTION: LLVMTypeRef LLVMFP128Type ( ) ;
FUNCTION: LLVMTypeRef LLVMPPCFP128Type ( ) ;
! Operations on function types
FUNCTION: LLVMTypeRef
LLVMFunctionType ( LLVMTypeRef ReturnType, LLVMTypeRef* ParamTypes, unsigned ParamCount, int IsVarArg ) ;
FUNCTION: int LLVMIsFunctionVarArg ( LLVMTypeRef FunctionTy ) ;
FUNCTION: LLVMTypeRef LLVMGetReturnType ( LLVMTypeRef FunctionTy ) ;
FUNCTION: unsigned LLVMCountParamTypes ( LLVMTypeRef FunctionTy ) ;
FUNCTION: void LLVMGetParamTypes ( LLVMTypeRef FunctionTy, LLVMTypeRef* Dest ) ;
! Operations on struct types
FUNCTION: LLVMTypeRef
LLVMStructType ( LLVMTypeRef* ElementTypes, unsigned ElementCount, int Packed ) ;
FUNCTION: unsigned LLVMCountStructElementTypes ( LLVMTypeRef StructTy ) ;
FUNCTION: void LLVMGetStructElementTypes ( LLVMTypeRef StructTy, LLVMTypeRef* Dest ) ;
FUNCTION: int LLVMIsPackedStruct ( LLVMTypeRef StructTy ) ;
! Operations on array, pointer, and vector types (sequence types)
FUNCTION: LLVMTypeRef LLVMArrayType ( LLVMTypeRef ElementType, unsigned ElementCount ) ;
FUNCTION: LLVMTypeRef LLVMPointerType ( LLVMTypeRef ElementType, unsigned AddressSpace ) ;
FUNCTION: LLVMTypeRef LLVMVectorType ( LLVMTypeRef ElementType, unsigned ElementCount ) ;
FUNCTION: LLVMTypeRef LLVMGetElementType ( LLVMTypeRef Ty ) ;
FUNCTION: unsigned LLVMGetArrayLength ( LLVMTypeRef ArrayTy ) ;
FUNCTION: unsigned LLVMGetPointerAddressSpace ( LLVMTypeRef PointerTy ) ;
FUNCTION: unsigned LLVMGetVectorSize ( LLVMTypeRef VectorTy ) ;
! Operations on other types
FUNCTION: LLVMTypeRef LLVMVoidType ( ) ;
FUNCTION: LLVMTypeRef LLVMLabelType ( ) ;
FUNCTION: LLVMTypeRef LLVMOpaqueType ( ) ;
! Operations on type handles
FUNCTION: LLVMTypeHandleRef LLVMCreateTypeHandle ( LLVMTypeRef PotentiallyAbstractTy ) ;
FUNCTION: void LLVMRefineType ( LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy ) ;
FUNCTION: LLVMTypeRef LLVMResolveTypeHandle ( LLVMTypeHandleRef TypeHandle ) ;
FUNCTION: void LLVMDisposeTypeHandle ( LLVMTypeHandleRef TypeHandle ) ;
! Types end
FUNCTION: unsigned LLVMCountParams ( LLVMValueRef Fn ) ;
FUNCTION: void LLVMGetParams ( LLVMValueRef Fn, LLVMValueRef* Params ) ;
FUNCTION: LLVMValueRef
LLVMAddFunction ( LLVMModuleRef M, c-string Name, LLVMTypeRef FunctionTy ) ;
FUNCTION: LLVMValueRef LLVMGetFirstFunction ( LLVMModuleRef M ) ;
FUNCTION: LLVMValueRef LLVMGetNextFunction ( LLVMValueRef Fn ) ;
FUNCTION: unsigned LLVMGetFunctionCallConv ( LLVMValueRef Fn ) ;
FUNCTION: void LLVMSetFunctionCallConv ( LLVMValueRef Fn, unsigned CC ) ;
FUNCTION: LLVMBasicBlockRef
LLVMAppendBasicBlock ( LLVMValueRef Fn, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMGetBasicBlockParent ( LLVMBasicBlockRef BB ) ;
! Values
FUNCTION: LLVMTypeRef LLVMTypeOf ( LLVMValueRef Val ) ;
FUNCTION: c-string LLVMGetValueName ( LLVMValueRef Val ) ;
FUNCTION: void LLVMSetValueName ( LLVMValueRef Val, c-string Name ) ;
FUNCTION: void LLVMDumpValue ( LLVMValueRef Val ) ;
! Instruction Builders
FUNCTION: LLVMBuilderRef LLVMCreateBuilder ( ) ;
FUNCTION: void LLVMPositionBuilder
( LLVMBuilderRef Builder, LLVMBasicBlockRef Block, LLVMValueRef Instr ) ;
FUNCTION: void LLVMPositionBuilderBefore
( LLVMBuilderRef Builder, LLVMValueRef Instr ) ;
FUNCTION: void LLVMPositionBuilderAtEnd
( LLVMBuilderRef Builder, LLVMBasicBlockRef Block ) ;
FUNCTION: LLVMBasicBlockRef LLVMGetInsertBlock
( LLVMBuilderRef Builder ) ;
FUNCTION: void LLVMClearInsertionPosition
( LLVMBuilderRef Builder ) ;
FUNCTION: void LLVMInsertIntoBuilder
( LLVMBuilderRef Builder, LLVMValueRef Instr ) ;
FUNCTION: void LLVMDisposeBuilder
( LLVMBuilderRef Builder ) ;
! IB Terminators
FUNCTION: LLVMValueRef LLVMBuildRetVoid
( LLVMBuilderRef Builder ) ;
FUNCTION: LLVMValueRef LLVMBuildRet
( LLVMBuilderRef Builder, LLVMValueRef V ) ;
FUNCTION: LLVMValueRef LLVMBuildBr
( LLVMBuilderRef Builder, LLVMBasicBlockRef Dest ) ;
FUNCTION: LLVMValueRef LLVMBuildCondBr
( LLVMBuilderRef Builder, LLVMValueRef If, LLVMBasicBlockRef Then, LLVMBasicBlockRef Else ) ;
FUNCTION: LLVMValueRef LLVMBuildSwitch
( LLVMBuilderRef Builder, LLVMValueRef V, LLVMBasicBlockRef Else, unsigned NumCases ) ;
FUNCTION: LLVMValueRef LLVMBuildInvoke
( LLVMBuilderRef Builder, LLVMValueRef Fn, LLVMValueRef* Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildUnwind
( LLVMBuilderRef Builder ) ;
FUNCTION: LLVMValueRef LLVMBuildUnreachable
( LLVMBuilderRef Builder ) ;
! IB Add Case to Switch
FUNCTION: void LLVMAddCase
( LLVMValueRef Switch, LLVMValueRef OnVal, LLVMBasicBlockRef Dest ) ;
! IB Arithmetic
FUNCTION: LLVMValueRef LLVMBuildAdd
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildSub
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildMul
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildUDiv
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildSDiv
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFDiv
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildURem
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildSRem
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFRem
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildShl
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildLShr
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildAShr
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildAnd
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildOr
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildXor
( LLVMBuilderRef Builder, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildNeg
( LLVMBuilderRef Builder, LLVMValueRef V, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildNot
( LLVMBuilderRef Builder, LLVMValueRef V, c-string Name ) ;
! IB Memory
FUNCTION: LLVMValueRef LLVMBuildMalloc
( LLVMBuilderRef Builder, LLVMTypeRef Ty, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildArrayMalloc
( LLVMBuilderRef Builder, LLVMTypeRef Ty, LLVMValueRef Val, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildAlloca
( LLVMBuilderRef Builder, LLVMTypeRef Ty, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildArrayAlloca
( LLVMBuilderRef Builder, LLVMTypeRef Ty, LLVMValueRef Val, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFree
( LLVMBuilderRef Builder, LLVMValueRef PointerVal ) ;
FUNCTION: LLVMValueRef LLVMBuildLoad
( LLVMBuilderRef Builder, LLVMValueRef PointerVal, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildStore
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMValueRef Ptr ) ;
FUNCTION: LLVMValueRef LLVMBuildGEP
( LLVMBuilderRef B, LLVMValueRef Pointer, LLVMValueRef* Indices,
unsigned NumIndices, c-string Name ) ;
! IB Casts
FUNCTION: LLVMValueRef LLVMBuildTrunc
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildZExt
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildSExt
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFPToUI
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFPToSI
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildUIToFP
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildSIToFP
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFPTrunc
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFPExt
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildPtrToInt
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildIntToPtr
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildBitCast
( LLVMBuilderRef Builder, LLVMValueRef Val, LLVMTypeRef DestTy, c-string Name ) ;
! IB Comparisons
FUNCTION: LLVMValueRef LLVMBuildICmp
( LLVMBuilderRef Builder, LLVMIntPredicate Op, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildFCmp
( LLVMBuilderRef Builder, LLVMRealPredicate Op, LLVMValueRef LHS, LLVMValueRef RHS, c-string Name ) ;
! IB Misc Instructions
FUNCTION: LLVMValueRef LLVMBuildPhi
( LLVMBuilderRef Builder, LLVMTypeRef Ty, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildCall
( LLVMBuilderRef Builder, LLVMValueRef Fn, LLVMValueRef* Args, unsigned NumArgs, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildSelect
( LLVMBuilderRef Builder, LLVMValueRef If, LLVMValueRef Then, LLVMValueRef Else, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildVAArg
( LLVMBuilderRef Builder, LLVMValueRef List, LLVMTypeRef Ty, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildExtractElement
( LLVMBuilderRef Builder, LLVMValueRef VecVal, LLVMValueRef Index, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildInsertElement
( LLVMBuilderRef Builder, LLVMValueRef VecVal, LLVMValueRef EltVal, LLVMValueRef Index, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildShuffleVector
( LLVMBuilderRef Builder, LLVMValueRef V1, LLVMValueRef V2, LLVMValueRef Mask, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildExtractValue
( LLVMBuilderRef Builder, LLVMValueRef AggVal, unsigned Index, c-string Name ) ;
FUNCTION: LLVMValueRef LLVMBuildInsertValue
( LLVMBuilderRef Builder, LLVMValueRef AggVal, LLVMValueRef EltVal, unsigned Index, c-string Name ) ;
! Memory Buffers/Bit Reader
FUNCTION: int LLVMCreateMemoryBufferWithContentsOfFile
( c-string Path, LLVMMemoryBufferRef* OutMemBuf, c-string* OutMessage ) ;
FUNCTION: void LLVMDisposeMemoryBuffer ( LLVMMemoryBufferRef MemBuf ) ;
LIBRARY: LLVMBitReader
FUNCTION: int LLVMParseBitcode
( LLVMMemoryBufferRef MemBuf, LLVMModuleRef* OutModule, c-string* OutMessage ) ;
FUNCTION: int LLVMGetBitcodeModuleProvider
( LLVMMemoryBufferRef MemBuf, LLVMModuleProviderRef* OutMP, c-string* OutMessage ) ;
]]
FILE: [[llvm/core/tags.txt]] [[not tested
]]
FILE: [[llvm/invoker/invoker-tests.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.llvm io.pathnames llvm.invoker llvm.reader tools.test ;
{ 3 } [
<< "resource:extra/llvm/reader/add.bc" install-bc >> 1 2 add
] unit-test
]]
FILE: [[llvm/invoker/invoker.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.data arrays assocs compiler.units
effects io.backend io.pathnames kernel llvm.core llvm.jit
llvm.reader llvm.types make namespaces sequences
specialized-arrays vocabs words ;
QUALIFIED-WITH: alien.c-types c
SPECIALIZED-ARRAY: c:void*
IN: llvm.invoker
! get function name, ret type, param types and names
! load module
! iterate through functions in a module
TUPLE: function name alien return params ;
: params ( llvm-function -- param-list )
dup LLVMCountParams c:void* <c-array>
[ LLVMGetParams ] keep >array
[ [ LLVMGetValueName ] [ LLVMTypeOf tref> ] bi 2array ] map ;
: <function> ( LLVMValueRef -- function )
function new
over LLVMGetValueName >>name
over LLVMTypeOf tref> type>> return>> >>return
swap params >>params ;
: (functions) ( llvm-function -- )
[ dup , LLVMGetNextFunction (functions) ] when* ;
: functions ( llvm-module -- functions )
LLVMGetFirstFunction [ (functions) ] { } make [ <function> ] map ;
: function-effect ( function -- effect )
[ params>> keys ] [ return>> void? 0 1 ? ] bi <effect> ;
: install-function ( function -- )
dup name>> "alien.llvm" create-vocab drop
"alien.llvm" create-word swap
[
dup name>> function-pointer ,
dup return>> c:lookup-c-type ,
dup params>> [ second c:lookup-c-type ] map ,
cdecl , \ alien-indirect ,
] [ ] make swap function-effect [ define-declared ] with-compilation-unit ;
: install-module ( name -- )
current-jit mps>> at [
module>> functions [ install-function ] each
] [ "no such module" throw ] if* ;
: install-bc ( path -- )
[ normalize-path ] [ file-name ] bi
[ load-into-jit ] keep install-module ;
<< "alien.llvm" create-vocab drop >>
]]
FILE: [[llvm/invoker/tags.txt]] [[not tested
]]
FILE: [[llvm/jit/jit.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.c-types alien.data alien.syntax assocs
destructors kernel llvm.core llvm.engine llvm.wrappers
namespaces ;
IN: llvm.jit
TUPLE: jit ee mps ;
: empty-engine ( -- engine )
"initial-module" <module> <provider> <engine> ;
: <jit> ( -- jit )
jit new empty-engine >>ee H{ } clone >>mps ;
: current-jit ( -- jit )
\ current-jit global [ drop <jit> ] cache ;
: (remove-functions) ( function -- )
current-jit ee>> value>> over LLVMFreeMachineCodeForFunction
LLVMGetNextFunction dup ALIEN: 0 = [ drop ] [ (remove-functions) ] if ;
: remove-functions ( module -- )
! free machine code for each function in module
LLVMGetFirstFunction dup ALIEN: 0 = [ drop ] [ (remove-functions) ] if ;
: remove-provider ( provider -- )
current-jit ee>> value>> swap value>> f void* <ref> f void* <ref>
[ LLVMRemoveModuleProvider drop ] 2keep void* deref [ llvm-throw ] when*
void* deref module new swap >>value
[ value>> remove-functions ] with-disposal ;
: remove-module ( name -- )
dup current-jit mps>> at [
remove-provider
current-jit mps>> delete-at
] [ drop ] if* ;
: add-module ( module name -- )
[ <provider> ] dip [ remove-module ] keep
current-jit ee>> value>> pick
[ [ value>> LLVMAddModuleProvider ] [ t >>disposed drop ] bi ] with-disposal
current-jit mps>> set-at ;
: function-pointer ( name -- alien )
current-jit ee>> value>> dup
rot f void* <ref> [ LLVMFindFunction drop ] keep
void* deref LLVMGetPointerToGlobal ;
]]
FILE: [[llvm/jit/tags.txt]] [[not tested
]]
FILE: [[llvm/jit/jit-tests.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: destructors llvm.jit llvm.wrappers tools.test ;
{ } [ "test" <module> "test" add-module "test" remove-module ] unit-test
]]
FILE: [[llvm/authors.txt]] [[Matthew Willis
]]
FILE: [[llvm/engine/engine.factor]] [[! Copyright (C) 2009 Matthew Willis.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.libraries alien.syntax kernel
llvm.core sequences ;
IN: llvm.engine
<<
{
"LLVMExecutionEngine" "LLVMTarget" "LLVMAnalysis" "LLVMipa"
"LLVMTransformUtils" "LLVMScalarOpts" "LLVMCodeGen"
"LLVMAsmPrinter" "LLVMSelectionDAG" "LLVMX86CodeGen"
"LLVMJIT" "LLVMInterpreter"
} [ add-llvm-library ] each
>>
! llvm-c/ExecutionEngine.h
LIBRARY: LLVMExecutionEngine
TYPEDEF: void* LLVMGenericValueRef
TYPEDEF: void* LLVMExecutionEngineRef
FUNCTION: LLVMGenericValueRef LLVMCreateGenericValueOfInt
( LLVMTypeRef Ty, ulonglong N, int IsSigned ) ;
FUNCTION: ulonglong LLVMGenericValueToInt
( LLVMGenericValueRef GenVal, int IsSigned ) ;
FUNCTION: int LLVMCreateExecutionEngine
( LLVMExecutionEngineRef *OutEE, LLVMModuleProviderRef MP, c-string* OutError ) ;
FUNCTION: int LLVMCreateJITCompiler
( LLVMExecutionEngineRef* OutJIT, LLVMModuleProviderRef MP, unsigned OptLevel, c-string* OutError ) ;
FUNCTION: void LLVMDisposeExecutionEngine ( LLVMExecutionEngineRef EE ) ;
FUNCTION: void LLVMFreeMachineCodeForFunction ( LLVMExecutionEngineRef EE, LLVMValueRef F ) ;
FUNCTION: void LLVMAddModuleProvider ( LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP ) ;
FUNCTION: int LLVMRemoveModuleProvider
( LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP, LLVMModuleRef* OutMod, c-string* OutError ) ;
FUNCTION: int LLVMFindFunction
( LLVMExecutionEngineRef EE, c-string Name, LLVMValueRef* OutFn ) ;
FUNCTION: void* LLVMGetPointerToGlobal ( LLVMExecutionEngineRef EE, LLVMValueRef Global ) ;
FUNCTION: LLVMGenericValueRef LLVMRunFunction
( LLVMExecutionEngineRef EE, LLVMValueRef F, unsigned NumArgs, LLVMGenericValueRef* Args ) ;
]]
FILE: [[llvm/engine/tags.txt]] [[not tested
]]
FILE: [[llvm/tags.txt]] [[bindings
not tested
]]
FILE: [[pdf/pdf-tests.factor]] [[USING: io.files kernel math namespaces pdf pdf.libhpdf prettyprint sequences ;
IN: pdf.tests
SYMBOL: font
SYMBOL: width
SYMBOL: height
SYMBOL: twidth
: font-list ( -- seq ) {
"Courier"
"Courier-Bold"
"Courier-Oblique"
"Courier-BoldOblique"
"Helvetica"
"Helvetica-Bold"
"Helvetica-Oblique"
"Helvetica-BoldOblique"
"Times-Roman"
"Times-Bold"
"Times-Italic"
"Times-BoldItalic"
"Symbol"
"ZapfDingbats"
} ;
[
! HPDF_COMP_ALL set-compression-mode
! HPDF_PAGE_MODE_USE_OUTLINE set-page-mode
! Add a new page object
add-page
get-page-height height set
get-page-width width set
! Print the lines of the page
1 set-page-line-width
50 50 width get 100 - height get 110 - page-rectangle
page-stroke
! Print the title of the page (with positioning center)
"Helvetica" f get-font font set
font get 24 set-page-font-and-size
"Font Demo" page-text-width twidth set
[
width get twidth get - 2 / height get 50 - "Font Demo" page-text-out
] with-text
! Print subtitle
[
font get 16 set-page-font-and-size
60 height get 80 - "<Standard Type1 font samples>" page-text-out
] with-text
! Print font list
[
60 height get 105 - page-move-text-pos
SYMBOL: fontname
font-list [
fontname set
fontname get f get-font font set
! print a label of text
font get 9 set-page-font-and-size
fontname get page-show-text
0 -18 page-move-text-pos
! print a sample text
font get 20 set-page-font-and-size
"abcdefgABCDEFG12345!#$%&+-@?" page-show-text
0 -20 page-move-text-pos
] each
] with-text
"font_test.pdf" temp-file save-to-file
] with-pdf
]]
FILE: [[pdf/libhpdf/libhpdf.factor]] [[! Copyright (C) 2007 Elie CHAFTARI
! See http://factorcode.org/license.txt for BSD license.
!
! Tested with libharu2 2.0.8 on Mac OS X 10.4.9 PowerPC
!
! export LD_LIBRARY_PATH=/opt/local/lib
USING: alien alien.syntax combinators system ;
IN: pdf.libhpdf
<< "libhpdf" {
{ [ win32? ] [ "libhpdf.dll" stdcall ] }
{ [ macosx? ] [ "libhpdf.dylib" cdecl ] }
{ [ unix? ] [ "$LD_LIBRARY_PATH/libhpdf.so" cdecl ] }
} cond add-library >>
! compression mode
: HPDF_COMP_NONE 0x00 ; inline ! No contents are compressed
: HPDF_COMP_TEXT 0x01 ; inline ! Compress contents stream of page
: HPDF_COMP_IMAGE 0x02 ; inline ! Compress streams of image objects
: HPDF_COMP_METADATA 0x04 ; inline ! Compress other data (fonts, cmaps...)
: HPDF_COMP_ALL 0x0F ; inline ! All stream data are compressed
: HPDF_COMP_MASK 0xFF ; inline
! page mode
CONSTANT: HPDF_PAGE_MODE_USE_NONE 0
CONSTANT: HPDF_PAGE_MODE_USE_OUTLINE 1
CONSTANT: HPDF_PAGE_MODE_USE_THUMBS 2
CONSTANT: HPDF_PAGE_MODE_FULL_SCREEN 3
CONSTANT: HPDF_PAGE_MODE_EOF 4
: error-code ( -- seq ) {
{ 0x1001 "HPDF_ARRAY_COUNT_ERR\nInternal error. The consistency of the data was lost." }
{ 0x1002 "HPDF_ARRAY_ITEM_NOT_FOUND\nInternal error. The consistency of the data was lost." }
{ 0x1003 "HPDF_ARRAY_ITEM_UNEXPECTED_TYPE\nInternal error. The consistency of the data was lost." }
{ 0x1004 "HPDF_BINARY_LENGTH_ERR\nThe length of the data exceeds HPDF_LIMIT_MAX_STRING_LEN." }
{ 0x1005 "HPDF_CANNOT_GET_PALLET\nCannot get a pallet data from PNG image." }
{ 0x1007 "HPDF_DICT_COUNT_ERR\nThe count of elements of a dictionary exceeds HPDF_LIMIT_MAX_DICT_ELEMENT" }
{ 0x1008 "HPDF_DICT_ITEM_NOT_FOUND\nInternal error. The consistency of the data was lost." }
{ 0x1009 "HPDF_DICT_ITEM_UNEXPECTED_TYPE\nInternal error. The consistency of the data was lost." }
{ 0x100A "HPDF_DICT_STREAM_LENGTH_NOT_FOUND\nInternal error. The consistency of the data was lost." }
{ 0x100B "HPDF_DOC_ENCRYPTDICT_NOT_FOUND\nHPDF_SetPermission() OR HPDF_SetEncryptMode() was called before a password is set." }
{ 0x100C "HPDF_DOC_INVALID_OBJECT\nInternal error. The consistency of the data was lost." }
{ 0x100E "HPDF_DUPLICATE_REGISTRATION\nTried to register a font that has been registered." }
{ 0x100F "HPDF_EXCEED_JWW_CODE_NUM_LIMIT\nCannot register a character to the japanese word wrap characters list." }
{ 0x1011 "HPDF_ENCRYPT_INVALID_PASSWORD\nTried to set the owner password to NULL. owner password and user password is the same." }
{ 0x1013 "HPDF_ERR_UNKNOWN_CLASS\nInternal error. The consistency of the data was lost." }
{ 0x1014 "HPDF_EXCEED_GSTATE_LIMIT\nThe depth of the stack exceeded HPDF_LIMIT_MAX_GSTATE." }
{ 0x1015 "HPDF_FAILED_TO_ALLOC_MEM\nMemory allocation failed." }
{ 0x1016 "HPDF_FILE_IO_ERROR\nFile processing failed. (A detailed code is set.)" }
{ 0x1017 "HPDF_FILE_OPEN_ERROR\nCannot open a file. (A detailed code is set.)" }
{ 0x1019 "HPDF_FONT_EXISTS\nTried to load a font that has already been registered." }
{ 0x101A "HPDF_FONT_INVALID_WIDTHS_TABLE\nThe format of a font-file is invalid . Internal error. The consistency of the data was lost." }
{ 0x101B "HPDF_INVALID_AFM_HEADER\nCannot recognize a header of an afm file." }
{ 0x101C "HPDF_INVALID_ANNOTATION\nThe specified annotation handle is invalid." }
{ 0x101E "HPDF_INVALID_BIT_PER_COMPONENT\nBit-per-component of a image which was set as mask-image is invalid." }
{ 0x101F "HPDF_INVALID_CHAR_MATRICS_DATA\nCannot recognize char-matrics-data of an afm file." }
{ 0x1020 "HPDF_INVALID_COLOR_SPACE\n1. The color_space parameter of HPDF_LoadRawImage is invalid.\n2. Color-space of a image which was set as mask-image is invalid.\n3. The function which is invalid in the present color-space was invoked." }
{ 0x1021 "HPDF_INVALID_COMPRESSION_MODE\nInvalid value was set when invoking HPDF_SetCommpressionMode()." }
{ 0x1022 "HPDF_INVALID_DATE_TIME\nAn invalid date-time value was set." }
{ 0x1023 "HPDF_INVALID_DESTINATION\nAn invalid destination handle was set." }
{ 0x1025 "HPDF_INVALID_DOCUMENT\nAn invalid document handle is set." }
{ 0x1026 "HPDF_INVALID_DOCUMENT_STATE\nThe function which is invalid in the present state was invoked." }
{ 0x1027 "HPDF_INVALID_ENCODER\nAn invalid encoder handle was set." }
{ 0x1028 "HPDF_INVALID_ENCODER_TYPE\nA combination between font and encoder is wrong." }
{ 0x102B "HPDF_INVALID_ENCODING_NAME\nAn Invalid encoding name is specified." }
{ 0x102C "HPDF_INVALID_ENCRYPT_KEY_LEN\nThe lengh of the key of encryption is invalid." }
{ 0x102D "HPDF_INVALID_FONTDEF_DATA\n1. An invalid font handle was set.\n2. Unsupported font format." }
{ 0x102E "HPDF_INVALID_FONTDEF_TYPE\nInternal error. The consistency of the data was lost." }
{ 0x102F "HPDF_INVALID_FONT_NAME\nA font which has the specified name is not found." }
{ 0x1030 "HPDF_INVALID_IMAGE\nUnsupported image format." }
{ 0x1031 "HPDF_INVALID_JPEG_DATA\nUnsupported image format." }
{ 0x1032 "HPDF_INVALID_N_DATA\nCannot read a postscript-name from an afm file." }
{ 0x1033 "HPDF_INVALID_OBJECT\n1. An invalid object is set.\n2. Internal error. The consistency of the data was lost." }
{ 0x1034 "HPDF_INVALID_OBJ_ID\nInternal error. The consistency of the data was lost." }
{ 0x1035 "HPDF_INVALID_OPERATION\nInvoked HPDF_Image_SetColorMask() against the image-object which was set a mask-image." }
{ 0x1036 "HPDF_INVALID_OUTLINE\nAn invalid outline-handle was specified." }
{ 0x1037 "HPDF_INVALID_PAGE\nAn invalid page-handle was specified." }
{ 0x1038 "HPDF_INVALID_PAGES\nAn invalid pages-handle was specified. (internal error)" }
{ 0x1039 "HPDF_INVALID_PARAMETER\nAn invalid value is set." }
{ 0x103B "HPDF_INVALID_PNG_IMAGE\nInvalid PNG image format." }
{ 0x103C "HPDF_INVALID_STREAM\nInternal error. The consistency of the data was lost." }
{ 0x103D "HPDF_MISSING_FILE_NAME_ENTRY\nInternal error. The \"_FILE_NAME\" entry for delayed loading is missing." }
{ 0x103F "HPDF_INVALID_TTC_FILE\nInvalid .TTC file format." }
{ 0x1040 "HPDF_INVALID_TTC_INDEX\nThe index parameter was exceed the number of included fonts" }
{ 0x1041 "HPDF_INVALID_WX_DATA\nCannot read a width-data from an afm file." }
{ 0x1042 "HPDF_ITEM_NOT_FOUND\nInternal error. The consistency of the data was lost." }
{ 0x1043 "HPDF_LIBPNG_ERROR\nAn error has returned from PNGLIB while loading an image." }
{ 0x1044 "HPDF_NAME_INVALID_VALUE\nInternal error. The consistency of the data was lost." }
{ 0x1045 "HPDF_NAME_OUT_OF_RANGE\nInternal error. The consistency of the data was lost." }
{ 0x1049 "HPDF_PAGES_MISSING_KIDS_ENTRY\nInternal error. The consistency of the data was lost." }
{ 0x104A "HPDF_PAGE_CANNOT_FIND_OBJECT\nInternal error. The consistency of the data was lost." }
{ 0x104B "HPDF_PAGE_CANNOT_GET_ROOT_PAGES\nInternal error. The consistency of the data was lost." }
{ 0x104C "HPDF_PAGE_CANNOT_RESTORE_GSTATE\nThere are no graphics-states to be restored." }
{ 0x104D "HPDF_PAGE_CANNOT_SET_PARENT\nInternal error. The consistency of the data was lost." }
{ 0x104E "HPDF_PAGE_FONT_NOT_FOUND\nThe current font is not set." }
{ 0x104F "HPDF_PAGE_INVALID_FONT\nAn invalid font-handle was specified." }
{ 0x1050 "HPDF_PAGE_INVALID_FONT_SIZE\nAn invalid font-size was set." }
{ 0x1051 "HPDF_PAGE_INVALID_GMODE\nSee Graphics mode." }
{ 0x1052 "HPDF_PAGE_INVALID_INDEX\nInternal error. The consistency of the data was lost." }
{ 0x1053 "HPDF_PAGE_INVALID_ROTATE_VALUE\nThe specified value is not a multiple of 90." }
{ 0x1054 "HPDF_PAGE_INVALID_SIZE\nAn invalid page-size was set." }
{ 0x1055 "HPDF_PAGE_INVALID_XOBJECT\nAn invalid image-handle was set." }
{ 0x1056 "HPDF_PAGE_OUT_OF_RANGE\nThe specified value is out of range." }
{ 0x1057 "HPDF_REAL_OUT_OF_RANGE\nThe specified value is out of range." }
{ 0x1058 "HPDF_STREAM_EOF\nUnexpected EOF marker was detected." }
{ 0x1059 "HPDF_STREAM_READLN_CONTINUE\nInternal error. The consistency of the data was lost." }
{ 0x105B "HPDF_STRING_OUT_OF_RANGE\nThe length of the specified text is too long." }
{ 0x105C "HPDF_THIS_FUNC_WAS_SKIPPED\nThe execution of a function was skipped because of other errors." }
{ 0x105D "HPDF_TTF_CANNOT_EMBEDDING_FONT\nThis font cannot be embedded. (restricted by license.)" }
{ 0x105E "HPDF_TTF_INVALID_CMAP\nUnsupported ttf format. (cannot find unicode cmap.)" }
{ 0x105F "HPDF_TTF_INVALID_FOMAT\nUnsupported ttf format." }
{ 0x1060 "HPDF_TTF_MISSING_TABLE\nUnsupported ttf format. (cannot find a necessary table.)" }
{ 0x1061 "HPDF_UNSUPPORTED_FONT_TYPE\nInternal error. The consistency of the data was lost." }
{ 0x1062 "HPDF_UNSUPPORTED_FUNC\n1. The library is not configured to use PNGLIB.\n2. Internal error. The consistency of the data was lost." }
{ 0x1063 "HPDF_UNSUPPORTED_JPEG_FORMAT\nUnsupported Jpeg format." }
{ 0x1064 "HPDF_UNSUPPORTED_TYPE1_FONT\nFailed to parse .PFB file." }
{ 0x1065 "HPDF_XREF_COUNT_ERR\nInternal error. The consistency of the data was lost." }
{ 0x1066 "HPDF_ZLIB_ERROR\nAn error has occurred while executing a function of Zlib." }
{ 0x1067 "HPDF_INVALID_PAGE_INDEX\nAn error returned from Zlib." }
{ 0x1068 "HPDF_INVALID_URI\nAn invalid URI was set." }
{ 0x1069 "HPDF_PAGELAYOUT_OUT_OF_RANGE\nAn invalid page-layout was set." }
{ 0x1070 "HPDF_PAGEMODE_OUT_OF_RANGE\nAn invalid page-mode was set." }
{ 0x1071 "HPDF_PAGENUM_STYLE_OUT_OF_RANGE\nAn invalid page-num-style was set." }
{ 0x1072 "HPDF_ANNOT_INVALID_ICON\nAn invalid icon was set." }
{ 0x1073 "HPDF_ANNOT_INVALID_BORDER_STYLE\nAn invalid border-style was set." }
{ 0x1074 "HPDF_PAGE_INVALID_DIRECTION\nAn invalid page-direction was set." }
{ 0x1075 "HPDF_INVALID_FONT\nAn invalid font-handle was specified." }
} ;
LIBRARY: libhpdf
! ===============================================
! hpdf.h
! ===============================================
FUNCTION: void* HPDF_New ( void* user_error_fn, void* user_data ) ;
FUNCTION: void* HPDF_Free ( void* pdf ) ;
FUNCTION: ulong HPDF_SetCompressionMode ( void* pdf, uint mode ) ;
FUNCTION: ulong HPDF_SetPageMode ( void* pdf, uint mode ) ;
FUNCTION: void* HPDF_AddPage ( void* pdf ) ;
FUNCTION: ulong HPDF_SaveToFile ( void* pdf, char* file_name ) ;
FUNCTION: float HPDF_Page_GetHeight ( void* page ) ;
FUNCTION: float HPDF_Page_GetWidth ( void* page ) ;
FUNCTION: ulong HPDF_Page_SetLineWidth ( void* page, float line_width ) ;
FUNCTION: ulong HPDF_Page_Rectangle ( void* page, float x, float y,
float width, float height ) ;
FUNCTION: ulong HPDF_Page_Stroke ( void* page ) ;
FUNCTION: void* HPDF_GetFont ( void* pdf, char* font_name,
char* encoding_name ) ;
FUNCTION: ulong HPDF_Page_SetFontAndSize ( void* page, void* font,
float size ) ;
FUNCTION: float HPDF_Page_TextWidth ( void* page, char* text ) ;
FUNCTION: ulong HPDF_Page_BeginText ( void* page ) ;
FUNCTION: ulong HPDF_Page_TextOut ( void* page, float xpos, float ypos,
char* text ) ;
FUNCTION: ulong HPDF_Page_EndText ( void* page ) ;
FUNCTION: ulong HPDF_Page_MoveTextPos ( void* page, float x, float y ) ;
FUNCTION: ulong HPDF_Page_ShowText ( void* page, char* text ) ;
]]
FILE: [[pdf/pdf.factor]] [[! Copyright (C) 2007 Elie CHAFTARI
! See http://factorcode.org/license.txt for BSD license.
!
! Tested with libharu2 2.0.8 on Mac OS X 10.4.9 PowerPC
USING: assocs continuations hashtables kernel math namespaces pdf.libhpdf ;
IN: pdf
SYMBOL: pdf
SYMBOL: page
! =========================================================
! Error handling routines
! =========================================================
: check-status ( status -- )
dup zero? [
drop
] [
error-code >hashtable at throw
] if ;
! =========================================================
! Document handling routines
! =========================================================
: new-pdf ( error-handler user-data -- )
HPDF_New pdf set ;
: free-pdf ( -- )
pdf get HPDF_Free drop ;
: with-pdf ( quot -- )
[ f f new-pdf [ free-pdf ] [ ] cleanup ] with-scope ; inline
: set-compression-mode ( mode -- )
pdf get swap HPDF_SetCompressionMode check-status ;
: set-page-mode ( mode -- )
pdf get swap HPDF_SetPageMode check-status ;
: add-page ( -- )
pdf get HPDF_AddPage page set ;
: save-to-file ( filename -- )
pdf get swap HPDF_SaveToFile check-status ;
: get-font ( fontname encoding -- font )
pdf get -rot HPDF_GetFont ;
! =========================================================
! Page Handling routines
! =========================================================
: get-page-height ( -- height )
page get HPDF_Page_GetHeight ;
: get-page-width ( -- width )
page get HPDF_Page_GetWidth ;
: page-text-width ( text -- width )
page get swap HPDF_Page_TextWidth ;
! =========================================================
! Graphics routines
! =========================================================
: set-page-line-width ( linewidth -- )
page get swap HPDF_Page_SetLineWidth check-status ;
: page-rectangle ( x y width height -- )
>r >r >r >r page get r> r> r> r> HPDF_Page_Rectangle check-status ;
: page-stroke ( -- )
page get HPDF_Page_Stroke check-status ;
: set-page-font-and-size ( font size -- )
page get -rot HPDF_Page_SetFontAndSize check-status ;
: page-begin-text ( -- )
page get HPDF_Page_BeginText check-status ;
: page-text-out ( xpos ypos text -- )
page get -roll HPDF_Page_TextOut check-status ;
: page-end-text ( -- )
page get HPDF_Page_EndText check-status ;
: with-text ( -- )
[ page-begin-text [ page-end-text ] [ ] cleanup ] with-scope ; inline
: page-move-text-pos ( x y -- )
page get -rot HPDF_Page_MoveTextPos check-status ;
: page-show-text ( text -- )
page get swap HPDF_Page_ShowText check-status ;
]]
ln -sf $(SONAME)$(SOVER1) $(SONAME)$(SONAME)$(SOVER1)JS) $(LDFLAGS) -Wl X, modify the Makefile after calling ./configure --shared
Now you can build and install:
make clean
make
make install
Test PDF files from pdf-tests.factor are generated in the test folder.]]
FILE: [[pdf/authors.txt]] [[Elie Chaftari
]]
FILE: [[advice/advice.factor]] [[! Copyright (C) 2008 James Cash
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences fry words assocs linked-assocs tools.annotations
coroutines lexer parser quotations arrays namespaces continuations
summary ;
IN: advice
SYMBOLS: before after around advised in-advice? ;
: advised? ( word -- ? )
advised word-prop ;
DEFER: make-advised
<PRIVATE
: init-around-co ( quot -- coroutine )
\ coreset suffix cocreate ;
PRIVATE>
: advise ( quot name word loc -- )
dup around eq? [ [ init-around-co ] 3dip ] when
over advised? [ over make-advised ] unless
word-prop set-at ;
: advise-before ( quot name word -- ) before advise ;
: advise-after ( quot name word -- ) after advise ;
: advise-around ( quot name word -- ) around advise ;
: get-advice ( word type -- seq )
word-prop values ;
: call-before ( word -- )
before get-advice [ call ] each ;
: call-after ( word -- )
after get-advice [ call ] each ;
: call-around ( main word -- )
t in-advice? [
around get-advice tuck
[ [ coresume ] each ] [ call ] [ <reversed> [ coresume ] each ] tri*
] with-variable ;
: remove-advice ( name word loc -- )
word-prop delete-at ;
ERROR: ad-do-it-error ;
M: ad-do-it-error summary
drop "ad-do-it should only be called inside 'around' advice" ;
: ad-do-it ( input -- result )
in-advice? get [ ad-do-it-error ] unless coyield ;
: make-advised ( word -- )
[ dup '[ [ _ ] dip over dup '[ _ call-before _ _ call-around _ call-after ] ] annotate ]
[ { before after around } [ <linked-hash> swap set-word-prop ] with each ]
[ t advised set-word-prop ] tri ;
: unadvise ( word -- )
[ reset ] [ { before after around advised } [ f swap set-word-prop ] with each ] bi ;
SYNTAX: ADVISE: ! word adname location => word adname quot loc
scan-word scan scan-word parse-definition swap [ spin ] dip advise ;
SYNTAX: UNADVISE:
scan-word suffix! \ unadvise suffix! ;
]]
FILE: [[advice/advice-docs.factor]] [[IN: advice
USING: help.markup help.syntax tools.annotations words coroutines ;
HELP: make-advised
{ $values { "word" "a word to annotate in preparation of advising" } }
{ $description "Prepares a word for being advised. This is done by: "
{ $list
{ "Annotating it to call the appropriate words before, around, and after the original body " }
{ "Adding " { $snippet "before" } ", " { $snippet "around" } ", and " { $snippet "after" } " properties, which will contain the advice" }
{ "Adding an " { $snippet "advised" } "property, which can later be used to determine if a given word is defined (see " { $link advised? } ")" }
}
}
{ $see-also advised? annotate } ;
HELP: advised?
{ $values { "word" "a word" } { "?" "t or f, indicating if " { $snippet "word" } " is advised" } }
{ $description "Determines whether or not the given word has any advice on it." } ;
HELP: ad-do-it
{ $values { "input" "an object" } { "result" "an object" } }
{ $description "Calls either the next applicable around advice or the main body, returning back to the point it was called from when finished. This word should only be called from inside advice." }
{ $see-also coyield } ;
ARTICLE: "advice" "Advice"
"Advice is a simple way of adding additition functionality to words by adding 'hooks' to a word, which can act before, after, or around the calling of the word." ;
ABOUT: "advice"
]]
FILE: [[advice/advice-tests.factor]] [[! Copyright (C) 2008 James Cash
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences io io.streams.string math tools.test advice math.parser
parser namespaces multiline eval words assocs ;
IN: advice.tests
[
[ ad-do-it ] must-fail
: foo ( -- str ) "foo" ;
\ foo make-advised
{ "bar" "foo" } [
[ "bar" ] "barify" \ foo advise-before
foo
] unit-test
{ "bar" "foo" "baz" } [
[ "baz" ] "bazify" \ foo advise-after
foo
] unit-test
{ "foo" "baz" } [
"barify" \ foo before remove-advice
foo
] unit-test
: bar ( a -- b ) 1 + ;
\ bar make-advised
{ 11 } [
[ 2 * ] "double" \ bar advise-before
5 bar
] unit-test
{ 11/3 } [
[ 3 / ] "third" \ bar advise-after
5 bar
] unit-test
{ -2 } [
[ -1 * ad-do-it 3 + ] "frobnobicate" \ bar advise-around
5 bar
] unit-test
: add ( a b -- c ) + ;
\ add make-advised
{ 10 } [
[ [ 2 * ] bi@ ] "double-args" \ add advise-before
2 3 add
] unit-test
{ 21 } [
[ 3 * ad-do-it 1- ] "around1" \ add advise-around
2 3 add
] unit-test
! { 9 } [
! [ [ 1- ] bi@ ad-do-it 2 / ] "around2" \ add advise-around
! 2 3 add
! ] unit-test
! { { "around1" "around2" } } [
! \ add around word-prop keys
! ] unit-test
{ 5 f } [
\ add unadvise
2 3 add \ add advised?
] unit-test
! : quux ( a b -- c ) * ;
! { f t 3+3/4 } [
! <" USING: advice kernel math ;
! IN: advice.tests
! \ quux advised?
! ADVISE: quux halve before [ 2 / ] bi@ ;
! \ quux advised?
! 3 5 quux"> eval
! ] unit-test
! { 3+3/4 "1+1/2 2+1/2 3+3/4" } [
! <" USING: advice kernel math math.parser io io.streams.string ;
! IN: advice.tests
! ADVISE: quux log around
! 2dup [ number>string write " " write ] bi@
! ad-do-it
! dup number>string write ;
! [ 3 5 quux ] with-string-writer"> eval
! ] unit-test
] with-scope
]]
FILE: [[advice/summary.txt]] [[Implmentation of advice/aspects
]]
FILE: [[advice/authors.txt]] [[James Cash
]]
FILE: [[advice/tags.txt]] [[extensions
]]
FILE: [[peg-lexer/peg-lexer.factor]] [=[USING: hashtables assocs sequences locals math accessors multiline delegate strings
delegate.protocols kernel peg peg.ebnf peg.private lexer namespaces combinators parser
words ;
IN: peg-lexer
TUPLE: lex-hash hash ;
CONSULT: assoc-protocol lex-hash hash>> ;
: <lex-hash> ( a -- lex-hash ) lex-hash boa ;
: pos-or-0 ( neg? -- pos/0 ) dup 0 < [ drop 0 ] when ;
:: prepare-pos ( v i -- c l )
[let | n [ i v head-slice ] |
v CHAR: \n n last-index -1 or 1 + -
n [ CHAR: \n = ] count 1 +
] ;
: store-pos ( v a -- )
input of prepare-pos
lexer get [ line<< ] keep column<< ;
M: lex-hash set-at
swap {
{ pos [ store-pos ] }
[ swap hash>> set-at ]
} case ;
:: at-pos ( t l c -- p ) t l head-slice [ length ] map-sum l 1 - + c + ;
M: lex-hash at*
swap {
{ input [ drop lexer get text>> "\n" join t ] }
{ pos [ drop lexer get [ text>> ] [ line>> 1 - ] [ column>> 1 + ] tri at-pos t ] }
[ swap hash>> at* ]
} case ;
: with-global-lexer ( quot -- result )
[
f lrstack set
V{ } clone error-stack set H{ } clone \ heads set
H{ } clone \ packrat set
] f make-assoc <lex-hash>
swap bind ; inline
: parse* ( parser -- ast )
compile
[ execute [ error-stack get first throw ] unless* ] with-global-lexer
ast>> ; inline
: create-bnf ( name parser -- )
reset-tokenizer [ lexer get skip-blank parse* dup ignore? [ drop ] [ parsed ] if ] curry
define-syntax word make-inline ;
SYNTAX: ON-BNF:
scan-new-word reset-tokenizer ";ON-BNF" parse-multiline-string parse-ebnf
main of create-bnf ;
! Tokenizer like standard factor lexer
EBNF: factor
space = " " | "\n" | "\t"
spaces = space* => [[ drop ignore ]]
chunk = (!(space) .)+ => [[ >string ]]
expr = spaces chunk
;EBNF
]=]
FILE: [[peg-lexer/test-parsers/test-parsers.factor]] [=[USING: peg-lexer math.parser strings ;
IN: peg-lexer.test-parsers
ON-BNF: test1
num = [1-4]* => [[ >string ]]
expr = num ( "-end" | "-done" )
;ON-BNF
ON-BNF: test2
num = [1-4]* => [[ >string string>number ]]
expr= num [5-9]
;ON-BNF
ON-BNF: test3
tokenizer = <foreign factor>
expr= "heavy" "duty" "testing"
;ON-BNF
]=]
FILE: [[peg-lexer/peg-lexer-tests.factor]] [[USING: tools.test peg-lexer.test-parsers ;
IN: peg-lexer.tests
{ V{ "1234" "-end" } } [
test1 1234-end
] unit-test
{ V{ 1234 53 } } [
test2 12345
] unit-test
{ V{ "heavy" "duty" "testing" } } [
test3 heavy duty testing
] unit-test
]]
FILE: [[peg-lexer/summary.txt]] [[Use peg to write parsing words
]]
FILE: [[peg-lexer/peg-lexer-docs.factor]] [[USING: peg.ebnf help.syntax help.markup strings ;
IN: peg-lexer
HELP: ON-BNF:
{ $syntax "ON-BNF: word ... ;ON-BNF" }
{ $description "Creates a parsing word using a parser for lexer control, adding the resulting ast to the stack. Parser syntax is as in " { $link POSTPONE: EBNF: } } ;
HELP: create-bnf
{ $values { "name" string } { "parser" parser } }
{ $description "Runtime equivalent of " { $link POSTPONE: ON-BNF: } " also useful with manually constructed parsers." } ;
HELP: factor
{ $values { "input" string } { "ast" "a sequence of tokens" } }
{ $description "Tokenizer that acts like standard factor lexer, separating tokens by whitespace." } ;
]]
FILE: [[peg-lexer/authors.txt]] [[Sam Anklesaria
]]
FILE: [[peg-lexer/tags.txt]] [[extensions
reflection
]]
FILE: [[flatland/flatland.factor]] [[
USING: accessors arrays combinators combinators.short-circuit
fry kernel locals math math.intervals math.vectors multi-methods
sequences ;
FROM: multi-methods => GENERIC: ;
IN: flatland
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Two dimensional world protocol
GENERIC: x ( obj -- x )
GENERIC: y ( obj -- y )
GENERIC: (x!) ( x obj -- )
GENERIC: (y!) ( y obj -- )
: x! ( obj x -- obj ) over (x!) ;
: y! ( obj y -- obj ) over (y!) ;
GENERIC: width ( obj -- width )
GENERIC: height ( obj -- height )
GENERIC: (width!) ( width obj -- )
GENERIC: (height!) ( height obj -- )
: width! ( obj width -- obj ) over (width!) ;
: height! ( obj height -- obj ) over (width!) ;
! Predicates on relative placement
GENERIC: to-the-left-of? ( obj obj -- ? )
GENERIC: to-the-right-of? ( obj obj -- ? )
GENERIC: below? ( obj obj -- ? )
GENERIC: above? ( obj obj -- ? )
GENERIC: in-between-horizontally? ( obj obj -- ? )
GENERIC: horizontal-interval ( obj -- interval )
GENERIC: move-to ( obj obj -- )
GENERIC: move-by ( obj delta -- )
GENERIC: move-left-by ( obj obj -- )
GENERIC: move-right-by ( obj obj -- )
GENERIC: left ( obj -- left )
GENERIC: right ( obj -- right )
GENERIC: bottom ( obj -- bottom )
GENERIC: top ( obj -- top )
GENERIC: distance ( a b -- c )
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Some of the above methods work on two element sequences.
! A two element sequence may represent a point in space or describe
! width and height.
METHOD: x { sequence } first ;
METHOD: y { sequence } second ;
METHOD: (x!) { number sequence } set-first ;
METHOD: (y!) { number sequence } set-second ;
METHOD: width { sequence } first ;
METHOD: height { sequence } second ;
: changed-x ( seq quot -- ) over [ [ x ] dip call ] dip (x!) ; inline
: changed-y ( seq quot -- ) over [ [ y ] dip call ] dip (y!) ; inline
METHOD: move-to { sequence sequence } [ x x! ] [ y y! ] bi drop ;
METHOD: move-by { sequence sequence } dupd v+ [ x x! ] [ y y! ] bi drop ;
METHOD: move-left-by { sequence number } '[ _ - ] changed-x ;
METHOD: move-right-by { sequence number } '[ _ + ] changed-x ;
! METHOD: move-left-by { sequence number } neg 0 2array move-by ;
! METHOD: move-right-by { sequence number } 0 2array move-by ;
! METHOD:: move-left-by { SEQ:sequence X:number -- )
! SEQ { X 0 } { -1 0 } v* move-by ;
METHOD: distance { sequence sequence } v- norm ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! A class for objects with a position
TUPLE: pos pos ;
METHOD: x { pos } pos>> first ;
METHOD: y { pos } pos>> second ;
METHOD: (x!) { number pos } pos>> set-first ;
METHOD: (y!) { number pos } pos>> set-second ;
METHOD: to-the-left-of? { pos number } [ x ] dip < ;
METHOD: to-the-right-of? { pos number } [ x ] dip > ;
METHOD: move-left-by { pos number } [ pos>> ] dip move-left-by ;
METHOD: move-right-by { pos number } [ pos>> ] dip move-right-by ;
METHOD: above? { pos number } [ y ] dip > ;
METHOD: below? { pos number } [ y ] dip < ;
METHOD: move-by { pos sequence } '[ _ v+ ] change-pos drop ;
METHOD: distance { pos pos } [ pos>> ] bi@ distance ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! A class for objects with velocity. It inherits from pos. Hey, if
! it's moving it has a position right? Unless it's some alternate universe...
TUPLE: vel < pos vel ;
: moving-up? ( obj -- ? ) vel>> y 0 > ;
: moving-down? ( obj -- ? ) vel>> y 0 < ;
: step-size ( vel time -- dist ) [ vel>> ] dip v*n ;
: move-for ( vel time -- ) dupd step-size move-by ;
: reverse-horizontal-velocity ( vel -- ) vel>> [ x neg ] [ ] bi (x!) ;
: reverse-vertical-velocity ( vel -- ) vel>> [ y neg ] [ ] bi (y!) ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! The 'pos' slot indicates the lower left hand corner of the
! rectangle. The 'dim' is holds the width and height.
TUPLE: rectangle < pos dim ;
METHOD: width { rectangle } dim>> first ;
METHOD: height { rectangle } dim>> second ;
METHOD: left { rectangle } x ;
METHOD: right { rectangle } [ x ] [ width ] bi + ;
METHOD: bottom { rectangle } y ;
METHOD: top { rectangle } [ y ] [ height ] bi + ;
: bottom-left ( rectangle -- pos ) pos>> ;
: center-x ( rectangle -- x ) [ left ] [ width 2 / ] bi + ;
: center-y ( rectangle -- y ) [ bottom ] [ height 2 / ] bi + ;
: center ( rectangle -- seq ) [ center-x ] [ center-y ] bi 2array ;
METHOD: to-the-left-of? { pos rectangle } [ x ] [ left ] bi* < ;
METHOD: to-the-right-of? { pos rectangle } [ x ] [ right ] bi* > ;
METHOD: below? { pos rectangle } [ y ] [ bottom ] bi* < ;
METHOD: above? { pos rectangle } [ y ] [ top ] bi* > ;
METHOD: horizontal-interval { rectangle }
[ left ] [ right ] bi [a,b] ;
METHOD: in-between-horizontally? { pos rectangle }
[ x ] [ horizontal-interval ] bi* interval-contains? ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: extent left right bottom top ;
METHOD: left { extent } left>> ;
METHOD: right { extent } right>> ;
METHOD: bottom { extent } bottom>> ;
METHOD: top { extent } top>> ;
METHOD: width { extent } [ right>> ] [ left>> ] bi - ;
METHOD: height { extent } [ top>> ] [ bottom>> ] bi - ;
! METHOD: to-extent ( rectangle -- extent )
! { [ left>> ] [ right>> ] [ bottom>> ] [ top>> ] } cleave extent boa ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
METHOD: to-the-left-of? { sequence rectangle } [ x ] [ left ] bi* < ;
METHOD: to-the-right-of? { sequence rectangle } [ x ] [ right ] bi* > ;
METHOD: below? { sequence rectangle } [ y ] [ bottom ] bi* < ;
METHOD: above? { sequence rectangle } [ y ] [ top ] bi* > ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Some support for the' 'rect' class from math.geometry.rect'
! METHOD: width ( rect -- width ) dim>> first ;
! METHOD: height ( rect -- height ) dim>> second ;
! METHOD: left ( rect -- left ) loc>> x
! METHOD: right ( rect -- right ) [ loc>> x ] [ width ] bi + ;
! METHOD: to-the-left-of? ( sequence rect -- ? ) [ x ] [ loc>> x ] bi* < ;
! METHOD: to-the-right-of? ( sequence rect -- ? ) [ x ] [ loc>> x ] bi* > ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: wrap ( POINT RECT -- POINT )
{
{ [ POINT RECT to-the-left-of? ] [ RECT right ] }
{ [ POINT RECT to-the-right-of? ] [ RECT left ] }
{ [ t ] [ POINT x ] }
}
cond
{
{ [ POINT RECT below? ] [ RECT top ] }
{ [ POINT RECT above? ] [ RECT bottom ] }
{ [ t ] [ POINT y ] }
}
cond
2array ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
GENERIC: within? ( a b -- ? )
METHOD: within? { pos rectangle }
{
[ left to-the-right-of? ]
[ right to-the-left-of? ]
[ bottom above? ]
[ top below? ]
}
2&& ;
]]
FILE: [[models/combinators/combinators.factor]] [[USING: accessors arrays kernel models models.product monads
sequences sequences.extras shuffle ;
FROM: syntax => >> ;
IN: models.combinators
TUPLE: multi-model < model important? ;
GENERIC: (model-changed) ( model observer -- )
: <multi-model> ( models kind -- model ) f swap new-model [ [ add-dependency ] curry each ] keep ;
M: multi-model model-changed over value>> [ (model-changed) ] [ 2drop ] if ;
M: multi-model model-activated dup dependencies>> [ value>> ] find nip
[ swap model-changed ] [ drop ] if* ;
: #1 ( model -- model' ) t >>important? ;
IN: models
: notify-connections ( model -- )
dup connections>> dup [ dup multi-model? [ important?>> ] [ drop f ] if ] find-all
[ second tuck [ remove ] dip prefix ] each
[ model-changed ] with each ;
IN: models.combinators
TUPLE: basic-model < multi-model ;
M: basic-model (model-changed) [ value>> ] dip set-model ;
: merge ( models -- model ) basic-model <multi-model> ;
: 2merge ( model1 model2 -- model ) 2array merge ;
: <basic> ( value -- model ) basic-model new-model ;
TUPLE: filter-model < multi-model quot ;
M: filter-model (model-changed) [ value>> ] dip 2dup quot>> call( a -- ? )
[ set-model ] [ 2drop ] if ;
: filter-model ( model quot -- filter-model ) [ 1array \ filter-model <multi-model> ] dip >>quot ;
TUPLE: fold-model < multi-model quot base values ;
M: fold-model (model-changed) 2dup base>> =
[ [ [ value>> ] [ [ values>> ] [ quot>> ] bi ] bi* swapd reduce* ] keep set-model ]
[ [ [ value>> ] [ values>> ] bi* push ]
[ [ [ value>> ] [ [ value>> ] [ quot>> ] bi ] bi* call( val oldval -- newval ) ] keep set-model ] 2bi
] if ;
M: fold-model model-activated drop ;
: new-fold-model ( deps -- model ) fold-model <multi-model> V{ } clone >>values ;
: fold ( model oldval quot -- model ) rot 1array new-fold-model swap >>quot
swap >>value ;
: fold* ( model oldmodel quot -- model ) over [ [ 2array new-fold-model ] dip >>quot ]
dip [ >>base ] [ value>> >>value ] bi ;
TUPLE: updater-model < multi-model values updates ;
M: updater-model (model-changed) [ tuck updates>> =
[ [ values>> value>> ] keep set-model ]
[ drop ] if ] keep f swap value<< ;
: updates ( values updates -- model ) [ 2array updater-model <multi-model> ] 2keep
[ >>values ] [ >>updates ] bi* ;
SYMBOL: switch
TUPLE: switch-model < multi-model original switcher on ;
M: switch-model (model-changed) 2dup switcher>> =
[ [ value>> ] dip over switch = [ nip [ original>> ] keep f >>on model-changed ] [ t >>on set-model ] if ]
[ dup on>> [ 2drop ] [ [ value>> ] dip over [ set-model ] [ 2drop ] if ] if ] if ;
: switch-models ( model1 model2 -- model' ) swap [ 2array switch-model <multi-model> ] 2keep
[ [ value>> >>value ] [ >>original ] bi ] [ >>switcher ] bi* ;
M: switch-model model-activated [ original>> ] keep model-changed ;
: >behavior ( event -- behavior ) t >>value ;
TUPLE: mapped-model < multi-model model quot ;
: new-mapped-model ( model quot class -- mapped-model ) [ over 1array ] dip
<multi-model> swap >>quot swap >>model ;
: <mapped> ( model quot -- model ) mapped-model new-mapped-model ;
M: mapped-model (model-changed)
[ [ value>> ] [ quot>> ] bi* call( old -- new ) ] [ nip ] 2bi
set-model ;
TUPLE: side-effect-model < mapped-model ;
M: side-effect-model (model-changed) [ value>> ] dip [ quot>> call( old -- ) ] 2keep set-model ;
TUPLE: quot-model < mapped-model ;
M: quot-model (model-changed) nip [ quot>> call( -- b ) ] keep set-model ;
TUPLE: action-value < basic-model parent ;
: <action-value> ( parent value -- model ) action-value new-model swap >>parent ;
M: action-value model-activated dup parent>> dup activate-model model-changed ; ! a fake dependency of sorts
TUPLE: action < multi-model quot ;
M: action (model-changed) [ [ value>> ] [ quot>> ] bi* call( a -- b ) ] keep value>>
[ swap add-connection ] 2keep model-changed ;
: <action> ( model quot -- action-model ) [ 1array action <multi-model> ] dip >>quot dup f <action-value> >>value value>> ;
TUPLE: collection < multi-model ;
: <collection> ( models -- product ) collection <multi-model> ;
M: collection (model-changed)
nip
dup dependencies>> [ value>> ] all?
[ dup [ value>> ] product-value swap set-model ]
[ drop ] if ;
M: collection model-activated dup (model-changed) ;
! for side effects
TUPLE: (when-model) < multi-model quot cond ;
: when-model ( model quot cond -- model ) rot 1array (when-model) <multi-model> swap >>cond swap >>quot ;
M: (when-model) (model-changed) [ quot>> ] 2keep
[ value>> ] [ cond>> ] bi* call( a -- ? ) [ call( model -- ) ] [ 2drop ] if ;
! only used in construction
: with-self ( quot: ( model -- model ) -- model ) [ f <basic> dup ] dip call swap [ add-dependency ] keep ; inline
USE: models.combinators.templates
<< { "$>" "<$" "fmap" } [ fmaps ] each >>
]]
FILE: [[models/combinators/summary.txt]] [[Model combination and manipulation]]
FILE: [[models/combinators/templates/templates.factor]] [[USING: kernel sequences functors fry macros generalizations ;
IN: models.combinators.templates
FROM: models.combinators => <collection> #1 ;
FUNCTOR: fmaps ( W -- )
W IS ${W}
w-n DEFINES ${W}-n
w-2 DEFINES 2${W}
w-3 DEFINES 3${W}
w-4 DEFINES 4${W}
w-n* DEFINES ${W}-n*
w-2* DEFINES 2${W}*
w-3* DEFINES 3${W}*
w-4* DEFINES 4${W}*
WHERE
MACRO: w-n ( int -- quot ) dup '[ [ _ narray <collection> ] dip [ _ firstn ] prepend W ] ;
: w-2 ( a b quot -- mapped ) 2 w-n ; inline
: w-3 ( a b c quot -- mapped ) 3 w-n ; inline
: w-4 ( a b c d quot -- mapped ) 4 w-n ; inline
MACRO: w-n* ( int -- quot ) dup '[ [ _ narray <collection> #1 ] dip [ _ firstn ] prepend W ] ;
: w-2* ( a b quot -- mapped ) 2 w-n* ; inline
: w-3* ( a b c quot -- mapped ) 3 w-n* ; inline
: w-4* ( a b c d quot -- mapped ) 4 w-n* ; inline
;FUNCTOR
]]
FILE: [[models/combinators/authors.txt]] [[Sam Anklesaria
]]
FILE: [[models/combinators/combinators-docs.factor]] [[USING: help.markup help.syntax models models.arrow sequences monads ;
IN: models.combinators
HELP: merge
{ $values { "models" "a list of models" } { "model" basic-model } }
{ $description "Creates a model that merges the updates of others" } ;
HELP: filter-model
{ $values { "model" model } { "quot" "quotation with stack effect ( a b -- c )" } { "filter-model" filter-model } }
{ $description "Creates a model that uses the updates of another model only when they satisfy a given predicate" } ;
HELP: fold
{ $values { "model" model } { "oldval" "starting value" } { "quot" "applied to update and previous values" } { "model" model } }
{ $description "Similar to " { $link reduce } " but works on models, applying a quotation to the previous and new values at each update" } ;
HELP: switch-models
{ $values { "model1" model } { "model2" model } { "model'" model } }
{ $description "Creates a model that starts with the behavior of model2 and switches to the behavior of model1 on its update" } ;
HELP: <mapped>
{ $values { "model" model } { "quot" "applied to model's value on updates" } { "model" model } }
{ $description "An expanded version of " { $link <arrow> } ". Use " { $link fmap } " instead." } ;
HELP: when-model
{ $values { "model" model } { "quot" "called on the model if the quot yields true" } { "cond" "a quotation called on the model's value, yielding a boolean value" } }
{ $description "Calls quot when model updates if its value meets the condition set in cond" } ;
HELP: with-self
{ $values { "quot" "quotation that recieves its own return value" } { "model" model } }
{ $description "Fixed points for models: the quot reacts to the same model to gives" } ;
HELP: #1
{ $values { "model" model } { "model'" model } }
{ $description "Moves a model to the top of its dependencies' connections, thus being notified before the others" } ;
ARTICLE: "models.combinators" "Extending models"
"The " { $vocab-link "models.combinators" } " library expands models to have discrete start and end times. "
"Also, it provides methods of manipulating and combining models, expecially useful when programming user interfaces: "
"The output models of some gadgets (see " { $vocab-link "ui.gadgets.controls" } " ) can be manipulated and used as the input models of others." ;
ABOUT: "models.combinators"
]]
FILE: [[alien/cxx/cxx.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.c-types alien.cxx.parser alien.marshall
alien.inline.types classes.mixin classes.tuple kernel namespaces
assocs sequences parser classes.parser alien.marshall.syntax
interpolate locals effects io strings make vocabs.parser words
generic fry quotations ;
IN: alien.cxx
<PRIVATE
: class-mixin ( str -- word )
create-class-in [ define-mixin-class ] keep ;
: class-tuple-word ( word -- word' )
"#" append create-word-in ;
: define-class-tuple ( word mixin -- )
[ drop class-wrapper { } define-tuple-class ]
[ add-mixin-instance ] 2bi ;
PRIVATE>
: define-c++-class ( name superclass-mixin -- )
[ [ class-tuple-word ] [ class-mixin ] bi dup ] dip
add-mixin-instance define-class-tuple ;
:: define-c++-method ( class-name generic name types effect virtual -- )
[ name % "_" % class-name H{ { CHAR: : CHAR: _ } } substitute % ] "" make :> name'
effect [ in>> "self" suffix ] [ out>> ] bi <effect> :> effect'
types class-name "*" append suffix :> types'
effect in>> "," join :> args
class-name virtual [ "#" append ] unless current-vocab lookup :> class
SBUF" " clone dup [ I[ return self->${name}(${args});]I ] with-output-stream >string :> body
name' types' effect' body define-c-marshalled
class generic create-method name' current-vocab lookup 1quotation define ;
]]
FILE: [[alien/cxx/parser/parser.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: parser lexer alien.inline ;
IN: alien.cxx.parser
: parse-c++-class-definition ( -- class superclass-mixin )
scan scan-word ;
: parse-c++-method-definition ( -- class-name generic name types effect )
scan scan-word function-types-effect ;
]]
FILE: [[alien/cxx/parser/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/cxx/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/cxx/syntax/syntax.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.cxx alien.cxx.parser ;
IN: alien.cxx.syntax
SYNTAX: C++-CLASS:
parse-c++-class-definition define-c++-class ;
SYNTAX: C++-METHOD:
parse-c++-method-definition f define-c++-method ;
SYNTAX: C++-VIRTUAL:
parse-c++-method-definition t define-c++-method ;
]]
FILE: [[alien/cxx/syntax/syntax-tests.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: tools.test alien.cxx.syntax alien.inline.syntax
alien.marshall.syntax alien.marshall accessors kernel ;
IN: alien.cxx.syntax.tests
DELETE-C-LIBRARY: test
C-LIBRARY: test
COMPILE-AS-C++
C-INCLUDE: <string>
C-TYPEDEF: std::string string
C++-CLASS: std::string c++-root
GENERIC: to-string ( obj -- str )
C++-METHOD: std::string to-string const-char* c_str ( )
CM-FUNCTION: std::string* new_string ( const-char* s )
return new std::string(s);
;
;C-LIBRARY
ALIAS: <std::string> new_string
{ 1 1 } [ new_string ] must-infer-as
{ 1 1 } [ c_str_std__string ] must-infer-as
[ t ] [ "abc" <std::string> std::string? ] unit-test
[ "abc" ] [ "abc" <std::string> to-string ] unit-test
DELETE-C-LIBRARY: inheritance
C-LIBRARY: inheritance
COMPILE-AS-C++
C-INCLUDE: <cstring>
<RAW-C
class alpha {
public:
alpha(const char* s) {
str = s;
};
const char* render() {
return str;
};
virtual const char* chop() {
return str;
};
virtual int length() {
return strlen(str);
};
const char* str;
};
class beta : alpha {
public:
beta(const char* s) : alpha(s + 1) { };
const char* render() {
return str + 1;
};
virtual const char* chop() {
return str + 2;
};
};
RAW-C>
C++-CLASS: alpha c++-root
C++-CLASS: beta alpha
CM-FUNCTION: alpha* new_alpha ( const-char* s )
return new alpha(s);
;
CM-FUNCTION: beta* new_beta ( const-char* s )
return new beta(s);
;
ALIAS: <alpha> new_alpha
ALIAS: <beta> new_beta
GENERIC: render ( obj -- obj )
GENERIC: chop ( obj -- obj )
GENERIC: length ( obj -- n )
C++-METHOD: alpha render const-char* render ( )
C++-METHOD: beta render const-char* render ( )
C++-VIRTUAL: alpha chop const-char* chop ( )
C++-VIRTUAL: beta chop const-char* chop ( )
C++-VIRTUAL: alpha length int length ( )
;C-LIBRARY
{ 1 1 } [ render_alpha ] must-infer-as
{ 1 1 } [ chop_beta ] must-infer-as
{ 1 1 } [ length_alpha ] must-infer-as
[ t ] [ "x" <alpha> alpha#? ] unit-test
[ t ] [ "x" <alpha> alpha? ] unit-test
[ t ] [ "x" <beta> alpha? ] unit-test
[ f ] [ "x" <beta> alpha#? ] unit-test
[ 5 ] [ "hello" <alpha> length ] unit-test
[ 4 ] [ "hello" <beta> length ] unit-test
[ "hello" ] [ "hello" <alpha> render ] unit-test
[ "llo" ] [ "hello" <beta> render ] unit-test
[ "ello" ] [ "hello" <beta> underlying>> \ alpha# new swap >>underlying render ] unit-test
[ "hello" ] [ "hello" <alpha> chop ] unit-test
[ "lo" ] [ "hello" <beta> chop ] unit-test
[ "lo" ] [ "hello" <beta> underlying>> \ alpha# new swap >>underlying chop ] unit-test
]]
FILE: [[alien/cxx/syntax/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/inline/types/types.factor]] [=[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.c-types assocs combinators.short-circuit
continuations effects fry kernel math memoize sequences
splitting strings peg.ebnf make words ;
IN: alien.inline.types
: cify-type ( str -- str' )
dup word? [ name>> ] when
H{ { CHAR: - CHAR: space } } substitute ;
: factorize-type ( str -- str' )
cify-type
"const " ?head drop
"unsigned " ?head [ "u" prepend ] when
"long " ?head [ "long" prepend ] when
" const" ?tail drop ;
: const-pointer? ( str -- ? )
cify-type { [ " const" tail? ] [ "&" tail? ] } 1|| ;
: pointer-to-const? ( str -- ? )
cify-type "const " head? ;
: template-class? ( str -- ? )
[ CHAR: < = ] any? ;
MEMO: resolved-primitives ( -- seq )
primitive-types [ resolve-typedef ] map ;
: primitive-type? ( type -- ? )
[
factorize-type resolve-typedef [ resolved-primitives ] dip
'[ _ = ] any?
] [ 2drop f ] recover ;
: pointer? ( type -- ? )
factorize-type [ "*" tail? ] [ "&" tail? ] bi or ;
: type-sans-pointer ( type -- type' )
factorize-type [ '[ _ = ] "*&" swap any? ] trim-tail ;
: pointer-to-primitive? ( type -- ? )
factorize-type
{ [ pointer? ] [ type-sans-pointer primitive-type? ] } 1&& ;
: pointer-to-non-const-primitive? ( str -- ? )
{
[ pointer-to-const? not ]
[ factorize-type pointer-to-primitive? ]
} 1&& ;
: types-effect>params-return ( types effect -- params return )
[ in>> zip ]
[ nip out>> dup length 0 > [ first ] [ drop "void" ] if ]
2bi ;
: annotate-effect ( types effect -- types effect' )
[ in>> ] [ out>> ] bi [
zip
[ over pointer-to-primitive? [ ">" prepend ] when ]
assoc-map unzip
] dip <effect> ;
TUPLE: c++-type name params ptr ;
C: <c++-type> c++-type
EBNF: (parse-c++-type)
dig = [0-9]
alpha = [a-zA-Z]
alphanum = [1-9a-zA-Z]
name = [_a-zA-Z] [_a-zA-Z1-9:]* => [[ first2 swap prefix >string ]]
ptr = [*&] => [[ empty? not ]]
param = "," " "* type " "* => [[ third ]]
params = "<" " "* type " "* param* ">" => [[ [ 4 swap nth ] [ third ] bi prefix ]]
type = name " "* params? " "* ptr? => [[ { 0 2 4 } [ swap nth ] with map first3 <c++-type> ]]
;EBNF
: parse-c++-type ( str -- c++-type )
factorize-type (parse-c++-type) ;
DEFER: c++-type>string
: params>string ( params -- str )
[ "<" % [ c++-type>string ] map "," join % ">" % ] "" make ;
: c++-type>string ( c++-type -- str )
[
[ name>> % ]
[ params>> [ params>string % ] when* ]
[ ptr>> [ "*" % ] when ]
tri
] "" make ;
GENERIC: c++-type ( obj -- c++-type/f )
M: object c++-type drop f ;
M: c++-type c-type ;
]=]
FILE: [[alien/inline/types/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/inline/inline.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.inline.compiler alien.inline.types
alien.libraries alien.parser arrays assocs effects fry
generalizations grouping io.directories io.files
io.files.info io.files.temp kernel lexer math math.order
math.ranges multiline namespaces sequences source-files
splitting strings system vocabs.loader vocabs.parser words
alien.c-types alien.structs make parser continuations ;
IN: alien.inline
SYMBOL: c-library
SYMBOL: library-is-c++
SYMBOL: linker-args
SYMBOL: c-strings
<PRIVATE
: cleanup-variables ( -- )
{ c-library library-is-c++ linker-args c-strings }
[ off ] each ;
: arg-list ( types -- params )
CHAR: a swap length CHAR: a + [a,b]
[ 1string ] map ;
: compile-library? ( -- ? )
c-library get library-path dup exists? [
file get [
path>>
[ file-info modified>> ] bi@ <=> +lt+ =
] [ drop t ] if*
] [ drop t ] if ;
: compile-library ( -- )
library-is-c++ get [ C++ ] [ C ] if
linker-args get
c-strings get "\n" join
c-library get compile-to-library ;
: c-library-name ( name -- name' )
[ current-vocab name>> % "_" % % ] "" make ;
PRIVATE>
: parse-arglist ( parameters return -- types effect )
[ 2 group unzip [ "," ?tail drop ] map ]
[ [ { } ] [ 1array ] if-void ]
bi* <effect> ;
: append-function-body ( prototype-str body -- str )
[ swap % " {\n" % % "\n}\n" % ] "" make ;
: function-types-effect ( -- function types effect )
scan scan swap ")" parse-tokens
[ "(" subseq? ] reject swap parse-arglist ;
: prototype-string ( function types effect -- str )
[ [ cify-type ] map ] dip
types-effect>params-return cify-type -rot
[ " " join ] map ", " join
"(" prepend ")" append 3array " " join
library-is-c++ get [ "extern \"C\" " prepend ] when ;
: prototype-string' ( function types return -- str )
[ dup arg-list ] <effect> prototype-string ;
: factor-function ( function types effect -- word quot effect )
annotate-effect [ c-library get ] 3dip
[ [ factorize-type ] map ] dip
types-effect>params-return factorize-type -roll
concat make-function ;
: define-c-library ( name -- )
c-library-name [ c-library set ] [ "c-library" set ] bi
V{ } clone c-strings set
V{ } clone linker-args set ;
: compile-c-library ( -- )
compile-library? [ compile-library ] when
c-library get dup library-path cdecl add-library ;
: define-c-function ( function types effect body -- )
[
[ factor-function define-declared ]
[ prototype-string ] 3bi
] dip append-function-body c-strings get push ;
: define-c-function' ( function effect body -- )
[
[ in>> ] keep
[ factor-function define-declared ]
[ out>> prototype-string' ] 3bi
] dip append-function-body c-strings get push ;
: c-link-to ( str -- )
"-l" prepend linker-args get push ;
: c-use-framework ( str -- )
"-framework" swap linker-args get '[ _ push ] bi@ ;
: c-link-to/use-framework ( str -- )
os macosx? [ c-use-framework ] [ c-link-to ] if ;
: c-include ( str -- )
"#include " prepend c-strings get push ;
: define-c-typedef ( old new -- )
[ typedef ] [
[ swap "typedef " % % " " % % ";" % ]
"" make c-strings get push
] 2bi ;
: define-c-struct ( name fields -- )
[ current-vocab swap define-struct ] [
over
[
"typedef struct " % "_" % % " {\n" %
[ first2 swap % " " % % ";\n" % ] each
"} " % % ";\n" %
] "" make c-strings get push
] 2bi ;
: delete-inline-library ( name -- )
c-library-name [ remove-library ]
[ library-path dup exists? [ delete-file ] [ drop ] if ] bi ;
: with-c-library ( name quot -- )
[ [ define-c-library ] dip call compile-c-library ]
[ cleanup-variables ] [ ] cleanup ; inline
: raw-c ( str -- )
[ "\n" % % "\n" % ] "" make c-strings get push ;
]]
FILE: [[alien/inline/inline-docs.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel strings effects quotations ;
IN: alien.inline
<PRIVATE
: $binding-note ( x -- )
drop
{ "This word requires that certain variables are correctly bound. "
"Call " { $link POSTPONE: define-c-library } " to set them up." } print-element ;
PRIVATE>
HELP: compile-c-library
{ $description "Writes, compiles, and links code generated since last invocation of " { $link POSTPONE: define-c-library } ". "
"Also calls " { $snippet "add-library" } ". "
"This word does nothing if the shared library is younger than the factor source file." }
{ $notes $binding-note } ;
HELP: c-use-framework
{ $values
{ "str" string }
}
{ $description "OS X only. Adds " { $snippet "-framework name" } " to linker command." }
{ $notes $binding-note }
{ $see-also c-link-to c-link-to/use-framework } ;
HELP: define-c-function
{ $values
{ "function" "function name" } { "types" "a sequence of C types" } { "effect" effect } { "body" string }
}
{ $description "Defines a C function and a factor word which calls it." }
{ $notes
{ $list
{ "The number of " { $snippet "types" } " must match the " { $snippet "in" } " count of the " { $snippet "effect" } "." }
{ "There must be only one " { $snippet "out" } " element. It must be a legal C return type with dashes (-) instead of spaces." }
$binding-note
}
}
{ $see-also POSTPONE: define-c-function' } ;
HELP: define-c-function'
{ $values
{ "function" "function name" } { "effect" effect } { "body" string }
}
{ $description "Defines a C function and a factor word which calls it. See " { $link define-c-function } " for more information." }
{ $notes
{ $list
{ "Each effect element must be a legal C type with dashes (-) instead of spaces. "
"C argument names will be generated alphabetically, starting with " { $snippet "a" } "." }
$binding-note
}
}
{ $see-also define-c-function } ;
HELP: c-include
{ $values
{ "str" string }
}
{ $description "Appends an include line to the C library in scope." }
{ $notes $binding-note } ;
HELP: define-c-library
{ $values
{ "name" string }
}
{ $description "Starts a new C library scope. Other " { $snippet "alien.inline" } " words can be used after this one." } ;
HELP: c-link-to
{ $values
{ "str" string }
}
{ $description "Adds " { $snippet "-lname" } " to linker command." }
{ $notes $binding-note }
{ $see-also c-use-framework c-link-to/use-framework } ;
HELP: c-link-to/use-framework
{ $values
{ "str" string }
}
{ $description "Equivalent to " { $link c-use-framework } " on OS X and " { $link c-link-to } " everywhere else." }
{ $notes $binding-note }
{ $see-also c-link-to c-use-framework } ;
HELP: define-c-struct
{ $values
{ "name" string } { "fields" "type/name pairs" }
}
{ $description "Defines a C struct and factor words which operate on it." }
{ $notes $binding-note } ;
HELP: define-c-typedef
{ $values
{ "old" "C type" } { "new" "C type" }
}
{ $description "Define C and factor typedefs." }
{ $notes $binding-note } ;
HELP: delete-inline-library
{ $values
{ "name" string }
}
{ $description "Delete the shared library file corresponding to " { $snippet "name" } "." }
{ $notes "Must be executed in the vocabulary where " { $snippet "name" } " is defined. " } ;
HELP: with-c-library
{ $values
{ "name" string } { "quot" quotation }
}
{ $description "Calls " { $link define-c-library } ", then the quotation, then " { $link compile-c-library } ", then sets all variables bound by " { $snippet "define-c-library" } " to " { $snippet "f" } "." } ;
HELP: raw-c
{ $values { "str" string } }
{ $description "Insert a string into the generated source file. Useful for macros and other details not implemented in " { $snippet "alien.inline" } "." } ;
]]
FILE: [[alien/inline/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/inline/syntax/syntax.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.inline lexer multiline namespaces parser ;
IN: alien.inline.syntax
SYNTAX: C-LIBRARY: scan define-c-library ;
SYNTAX: COMPILE-AS-C++ t library-is-c++ set ;
SYNTAX: C-LINK: scan c-link-to ;
SYNTAX: C-FRAMEWORK: scan c-use-framework ;
SYNTAX: C-LINK/FRAMEWORK: scan c-link-to/use-framework ;
SYNTAX: C-INCLUDE: scan c-include ;
SYNTAX: C-FUNCTION:
function-types-effect parse-here define-c-function ;
SYNTAX: C-TYPEDEF: scan scan define-c-typedef ;
SYNTAX: C-STRUCTURE:
scan parse-definition define-c-struct ;
SYNTAX: ;C-LIBRARY compile-c-library ;
SYNTAX: DELETE-C-LIBRARY: scan delete-inline-library ;
SYNTAX: <RAW-C "RAW-C>" parse-multiline-string raw-c ;
]]
FILE: [[alien/inline/syntax/syntax-tests.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.inline alien.inline.syntax io.directories io.files
kernel namespaces tools.test alien.c-types alien.data alien.structs ;
IN: alien.inline.syntax.tests
DELETE-C-LIBRARY: test
C-LIBRARY: test
C-FUNCTION: const-int add ( int a, int b )
return a + b;
;
C-TYPEDEF: double bigfloat
C-FUNCTION: bigfloat smaller ( bigfloat a )
return a / 10;
;
C-STRUCTURE: rectangle
{ "int" "width" }
{ "int" "height" } ;
C-FUNCTION: int area ( rectangle c )
return c.width * c.height;
;
;C-LIBRARY
{ 2 1 } [ add ] must-infer-as
[ 5 ] [ 2 3 add ] unit-test
[ t ] [ "double" "bigfloat" [ resolve-typedef ] same? ] unit-test
{ 1 1 } [ smaller ] must-infer-as
[ 1.0 ] [ 10 smaller ] unit-test
[ t ] [ "rectangle" resolve-typedef struct-type? ] unit-test
{ 1 1 } [ area ] must-infer-as
[ 20 ] [
"rectangle" <c-object>
4 over set-rectangle-width
5 over set-rectangle-height
area
] unit-test
DELETE-C-LIBRARY: cpplib
C-LIBRARY: cpplib
COMPILE-AS-C++
C-INCLUDE: <string>
C-FUNCTION: const-char* hello ( )
std::string s("hello world");
return s.c_str();
;
;C-LIBRARY
{ 0 1 } [ hello ] must-infer-as
[ "hello world" ] [ hello ] unit-test
DELETE-C-LIBRARY: compile-error
C-LIBRARY: compile-error
C-FUNCTION: char* breakme ( )
return not a string;
;
<< [ compile-c-library ] must-fail >>
]]
FILE: [[alien/inline/syntax/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/inline/syntax/syntax-docs.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax alien.inline ;
IN: alien.inline.syntax
HELP: ;C-LIBRARY
{ $syntax ";C-LIBRARY" }
{ $description "Writes, compiles, and links code generated since previous invocation of " { $link POSTPONE: C-LIBRARY: } "." }
{ $see-also POSTPONE: compile-c-library } ;
HELP: C-FRAMEWORK:
{ $syntax "C-FRAMEWORK: name" }
{ $description "OS X only. Link to named framework. Takes effect when " { $link POSTPONE: ;C-LIBRARY } " is called." }
{ $see-also POSTPONE: c-use-framework } ;
HELP: C-FUNCTION:
{ $syntax "C-FUNCTION: return name ( args ... )\nbody\n;" }
{ $description "Appends a function to the C library in scope and defines an FFI word that calls it." }
{ $examples
{ $example
"USING: alien.inline.syntax prettyprint ;"
"IN: cmath.ffi"
""
"C-LIBRARY: cmathlib"
""
"C-FUNCTION: int add ( int a, int b )"
" return a + b;"
";"
""
";C-LIBRARY"
""
"1 2 add ."
"3" }
}
{ $see-also POSTPONE: define-c-function } ;
HELP: C-INCLUDE:
{ $syntax "C-INCLUDE: name" }
{ $description "Appends an include line to the C library in scope." }
{ $see-also POSTPONE: c-include } ;
HELP: C-LIBRARY:
{ $syntax "C-LIBRARY: name" }
{ $description "Starts a new C library scope. Other " { $snippet "alien.inline" } " syntax can be used after this word." }
{ $examples
{ $example
"USING: alien.inline.syntax ;"
"IN: rectangle.ffi"
""
"C-LIBRARY: rectlib"
""
"C-STRUCTURE: rectangle { \"int\" \"width\" } { \"int\" \"height\" } ;"
""
"C-FUNCTION: int area ( rectangle c )"
" return c.width * c.height;"
";"
""
";C-LIBRARY"
"" }
}
{ $see-also POSTPONE: define-c-library } ;
HELP: C-LINK/FRAMEWORK:
{ $syntax "C-LINK/FRAMEWORK: name" }
{ $description "Equivalent to " { $link POSTPONE: C-FRAMEWORK: } " on OS X and " { $link POSTPONE: C-LINK: } " everywhere else." }
{ $see-also POSTPONE: c-link-to/use-framework } ;
HELP: C-LINK:
{ $syntax "C-LINK: name" }
{ $description "Link to named library. Takes effect when " { $link POSTPONE: ;C-LIBRARY } " is called." }
{ $see-also POSTPONE: c-link-to } ;
HELP: C-STRUCTURE:
{ $syntax "C-STRUCTURE: name pairs ... ;" }
{ $description "Like " { $snippet "C-STRUCT:" } " but also generates equivalent C code."}
{ $see-also POSTPONE: define-c-struct } ;
HELP: C-TYPEDEF:
{ $syntax "C-TYPEDEF: old new" }
{ $description "Like " { $snippet "TYPEDEF:" } " but generates a C typedef statement too." }
{ $see-also POSTPONE: define-c-typedef } ;
HELP: COMPILE-AS-C++
{ $syntax "COMPILE-AS-C++" }
{ $description "Insert this word anywhere between " { $link POSTPONE: C-LIBRARY: } " and " { $link POSTPONE: ;C-LIBRARY } " and the generated code will be treated as C++ with " { $snippet "extern \"C\"" } " prepended to each function prototype." } ;
HELP: DELETE-C-LIBRARY:
{ $syntax "DELETE-C-LIBRARY: name" }
{ $description "Deletes the shared library file corresponding to " { $snippet "name" } " . " }
{ $notes
{ $list
{ "Must be executed in the vocabulary where " { $snippet "name" } " is defined. " }
"This word is mainly useful for unit tests."
}
}
{ $see-also POSTPONE: delete-inline-library } ;
HELP: <RAW-C
{ $syntax "<RAW-C code RAW-C>" }
{ $description "Insert a (multiline) string into the generated source file. Useful for macros and other details not implemented in " { $snippet "alien.inline" } "." } ;
]]
FILE: [[alien/inline/compiler/compiler.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays combinators fry generalizations
io.encodings.ascii io.files io.files.temp io.launcher kernel
locals make sequences system vocabs.parser words io.directories
io.pathnames ;
IN: alien.inline.compiler
SYMBOL: C
SYMBOL: C++
: inline-libs-directory ( -- path )
"alien-inline-libs" resource-path dup make-directories ;
: inline-library-file ( name -- path )
inline-libs-directory prepend-path ;
: library-suffix ( -- str )
os {
{ [ dup macosx? ] [ drop ".dylib" ] }
{ [ dup unix? ] [ drop ".so" ] }
{ [ dup windows? ] [ drop ".dll" ] }
} cond ;
: library-path ( str -- path )
'[ "lib" % _ % library-suffix % ] "" make inline-library-file ;
HOOK: compiler os ( lang -- str )
M: word compiler
{
{ C [ "gcc" ] }
{ C++ [ "g++" ] }
} case ;
M: openbsd compiler
{
{ C [ "gcc" ] }
{ C++ [ "eg++" ] }
} case ;
M: windows compiler
{
{ C [ "gcc" ] }
{ C++ [ "g++" ] }
} case ;
HOOK: compiler-descr os ( lang -- descr )
M: word compiler-descr compiler 1array ;
M: macosx compiler-descr
call-next-method cpu x86.64?
[ { "-arch" "x86_64" } append ] when ;
HOOK: link-descr os ( lang -- descr )
M: word link-descr drop { "-shared" "-o" } ;
M: macosx link-descr
drop { "-g" "-prebind" "-dynamiclib" "-o" }
cpu x86.64? [ { "-arch" "x86_64" } prepend ] when ;
M: windows link-descr
{
{ C [ { "-mno-cygwin" "-shared" "-o" } ] }
{ C++ [ { "-lstdc++" "-mno-cygwin" "-shared" "-o" } ] }
} case ;
<PRIVATE
: src-suffix ( lang -- str )
{
{ C [ ".c" ] }
{ C++ [ ".cpp" ] }
} case ;
: link-command ( args in out lang -- descr )
[ 2array ] dip [ compiler 1array ] [ link-descr ] bi
append prepend prepend ;
:: compile-to-object ( lang contents name -- )
name ".o" append temp-file
contents name lang src-suffix append temp-file
[ ascii set-file-contents ] keep 2array
lang compiler-descr { "-fPIC" "-c" "-o" } append prepend
try-process ;
:: link-object ( lang args name -- )
args name [ library-path ]
[ ".o" append temp-file ] bi
lang link-command try-process ;
PRIVATE>
:: compile-to-library ( lang args contents name -- )
lang contents name compile-to-object
lang args name link-object ;
]]
FILE: [[alien/inline/compiler/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/inline/compiler/compiler-docs.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel strings words.symbol sequences ;
IN: alien.inline.compiler
HELP: C
{ $var-description "A symbol representing C source." } ;
HELP: C++
{ $var-description "A symbol representing C++ source." } ;
HELP: compile-to-library
{ $values
{ "lang" symbol } { "args" sequence } { "contents" string } { "name" string }
}
{ $description "Compiles and links " { $snippet "contents" } " into a shared library called " { $snippet "libname.suffix" }
"in " { $snippet "resource:alien-inline-libs" } ". " { $snippet "suffix" } " is OS specific. "
{ $snippet "args" } " is a sequence of arguments for the linking stage." }
{ $notes
{ $list
"C and C++ are the only supported languages."
{ "Source and object files are placed in " { $snippet "resource:temp" } "." } }
} ;
HELP: compiler
{ $values
{ "lang" symbol }
{ "str" string }
}
{ $description "Returns a compiler name based on OS and source language." }
{ $see-also compiler-descr } ;
HELP: compiler-descr
{ $values
{ "lang" symbol }
{ "descr" "a process description" }
}
{ $description "Returns a compiler process description based on OS and source language." }
{ $see-also compiler } ;
HELP: inline-library-file
{ $values
{ "name" string }
{ "path" "a pathname string" }
}
{ $description "Appends " { $snippet "name" } " to the " { $link inline-libs-directory } "." } ;
HELP: inline-libs-directory
{ $values
{ "path" "a pathname string" }
}
{ $description "The directory where libraries created using " { $snippet "alien.inline" } " are stored." } ;
HELP: library-path
{ $values
{ "str" string }
{ "path" "a pathname string" }
}
{ $description "Converts " { $snippet "name" } " into a full path to the corresponding inline library." } ;
HELP: library-suffix
{ $values
{ "str" string }
}
{ $description "The appropriate shared library suffix for the current OS." } ;
HELP: link-descr
{ $values
{ "lang" "a language" }
{ "descr" sequence }
}
{ $description "Returns part of a process description. OS dependent." } ;
ARTICLE: "alien.inline.compiler" "Inline C compiler"
{ $vocab-link "alien.inline.compiler" }
;
ABOUT: "alien.inline.compiler"
]]
FILE: [[alien/marshall/marshall.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.c-types alien.inline.types
alien.marshall.private alien.strings byte-arrays classes
combinators combinators.short-circuit destructors fry
io.encodings.utf8 kernel libc sequences alien.data
specialized-arrays strings unix.utilities vocabs.parser
words libc.private locals generalizations math ;
FROM: alien.c-types => float short ;
SPECIALIZED-ARRAY: bool
SPECIALIZED-ARRAY: char
SPECIALIZED-ARRAY: double
SPECIALIZED-ARRAY: float
SPECIALIZED-ARRAY: int
SPECIALIZED-ARRAY: long
SPECIALIZED-ARRAY: longlong
SPECIALIZED-ARRAY: short
SPECIALIZED-ARRAY: uchar
SPECIALIZED-ARRAY: uint
SPECIALIZED-ARRAY: ulong
SPECIALIZED-ARRAY: ulonglong
SPECIALIZED-ARRAY: ushort
SPECIALIZED-ARRAY: void*
IN: alien.marshall
<< primitive-types [ [ void* = ] [ bool = ] bi or not ]
filter [ define-primitive-marshallers ] each >>
TUPLE: alien-wrapper { underlying alien } ;
TUPLE: struct-wrapper < alien-wrapper disposed ;
TUPLE: class-wrapper < alien-wrapper disposed ;
MIXIN: c++-root
GENERIC: unmarshall-cast ( alien-wrapper -- alien-wrapper' )
M: alien-wrapper unmarshall-cast ;
M: struct-wrapper unmarshall-cast ;
M: struct-wrapper dispose* underlying>> free ;
M: class-wrapper c++-type class name>> parse-c++-type ;
: marshall-pointer ( obj -- alien )
{
{ [ dup alien? ] [ ] }
{ [ dup not ] [ ] }
{ [ dup byte-array? ] [ malloc-byte-array ] }
{ [ dup alien-wrapper? ] [ underlying>> ] }
} cond ;
: marshall-primitive ( n -- n )
[ bool>arg ] ptr-pass-through ;
ALIAS: marshall-void* marshall-pointer
: marshall-void** ( seq -- alien )
[ marshall-void* ] void*-array{ } map-as malloc-underlying ;
: (marshall-char*-or-string) ( n/string -- alien )
dup string?
[ utf8 string>alien malloc-byte-array ]
[ (marshall-char*) ] if ;
: marshall-char*-or-string ( n/string -- alien )
[ (marshall-char*-or-string) ] ptr-pass-through ;
: (marshall-char**-or-strings) ( seq -- alien )
[ marshall-char*-or-string ] void*-array{ } map-as
malloc-underlying ;
: marshall-char**-or-strings ( seq -- alien )
[ (marshall-char**-or-strings) ] ptr-pass-through ;
: marshall-bool ( ? -- n )
>boolean [ 1 ] [ 0 ] if ;
: (marshall-bool*) ( ?/seq -- alien )
[ marshall-bool <bool> malloc-byte-array ]
[ >bool-array malloc-underlying ]
marshall-x* ;
: marshall-bool* ( ?/seq -- alien )
[ (marshall-bool*) ] ptr-pass-through ;
: (marshall-bool**) ( seq -- alien )
[ marshall-bool* ] map >void*-array malloc-underlying ;
: marshall-bool** ( seq -- alien )
[ (marshall-bool**) ] ptr-pass-through ;
: unmarshall-bool ( n -- ? )
0 = not ;
: unmarshall-bool* ( alien -- ? )
*bool unmarshall-bool ;
: unmarshall-bool*-free ( alien -- ? )
[ *bool unmarshall-bool ] keep add-malloc free ;
: primitive-marshaller ( type -- quot/f )
{
{ "bool" [ [ ] ] }
{ "boolean" [ [ marshall-bool ] ] }
{ "char" [ [ marshall-primitive ] ] }
{ "uchar" [ [ marshall-primitive ] ] }
{ "short" [ [ marshall-primitive ] ] }
{ "ushort" [ [ marshall-primitive ] ] }
{ "int" [ [ marshall-primitive ] ] }
{ "uint" [ [ marshall-primitive ] ] }
{ "long" [ [ marshall-primitive ] ] }
{ "ulong" [ [ marshall-primitive ] ] }
{ "long" [ [ marshall-primitive ] ] }
{ "ulong" [ [ marshall-primitive ] ] }
{ "float" [ [ marshall-primitive ] ] }
{ "double" [ [ marshall-primitive ] ] }
{ "bool*" [ [ marshall-bool* ] ] }
{ "boolean*" [ [ marshall-bool* ] ] }
{ "char*" [ [ marshall-char*-or-string ] ] }
{ "uchar*" [ [ marshall-uchar* ] ] }
{ "short*" [ [ marshall-short* ] ] }
{ "ushort*" [ [ marshall-ushort* ] ] }
{ "int*" [ [ marshall-int* ] ] }
{ "uint*" [ [ marshall-uint* ] ] }
{ "long*" [ [ marshall-long* ] ] }
{ "ulong*" [ [ marshall-ulong* ] ] }
{ "longlong*" [ [ marshall-longlong* ] ] }
{ "ulonglong*" [ [ marshall-ulonglong* ] ] }
{ "float*" [ [ marshall-float* ] ] }
{ "double*" [ [ marshall-double* ] ] }
{ "bool&" [ [ marshall-bool* ] ] }
{ "boolean&" [ [ marshall-bool* ] ] }
{ "char&" [ [ marshall-char* ] ] }
{ "uchar&" [ [ marshall-uchar* ] ] }
{ "short&" [ [ marshall-short* ] ] }
{ "ushort&" [ [ marshall-ushort* ] ] }
{ "int&" [ [ marshall-int* ] ] }
{ "uint&" [ [ marshall-uint* ] ] }
{ "long&" [ [ marshall-long* ] ] }
{ "ulong&" [ [ marshall-ulong* ] ] }
{ "longlong&" [ [ marshall-longlong* ] ] }
{ "ulonglong&" [ [ marshall-ulonglong* ] ] }
{ "float&" [ [ marshall-float* ] ] }
{ "double&" [ [ marshall-double* ] ] }
{ "void*" [ [ marshall-void* ] ] }
{ "bool**" [ [ marshall-bool** ] ] }
{ "boolean**" [ [ marshall-bool** ] ] }
{ "char**" [ [ marshall-char**-or-strings ] ] }
{ "uchar**" [ [ marshall-uchar** ] ] }
{ "short**" [ [ marshall-short** ] ] }
{ "ushort**" [ [ marshall-ushort** ] ] }
{ "int**" [ [ marshall-int** ] ] }
{ "uint**" [ [ marshall-uint** ] ] }
{ "long**" [ [ marshall-long** ] ] }
{ "ulong**" [ [ marshall-ulong** ] ] }
{ "longlong**" [ [ marshall-longlong** ] ] }
{ "ulonglong**" [ [ marshall-ulonglong** ] ] }
{ "float**" [ [ marshall-float** ] ] }
{ "double**" [ [ marshall-double** ] ] }
{ "void**" [ [ marshall-void** ] ] }
[ drop f ]
} case ;
: marshall-non-pointer ( alien-wrapper/byte-array -- byte-array )
{
{ [ dup byte-array? ] [ ] }
{ [ dup alien-wrapper? ]
[ [ underlying>> ] [ class name>> heap-size ] bi
memory>byte-array ] }
} cond ;
: marshaller ( type -- quot )
factorize-type dup primitive-marshaller [ nip ] [
pointer?
[ [ marshall-pointer ] ]
[ [ marshall-non-pointer ] ] if
] if* ;
: unmarshall-char*-to-string ( alien -- string )
utf8 alien>string ;
: unmarshall-char*-to-string-free ( alien -- string )
[ unmarshall-char*-to-string ] keep add-malloc free ;
: primitive-unmarshaller ( type -- quot/f )
{
{ "bool" [ [ ] ] }
{ "boolean" [ [ unmarshall-bool ] ] }
{ "char" [ [ ] ] }
{ "uchar" [ [ ] ] }
{ "short" [ [ ] ] }
{ "ushort" [ [ ] ] }
{ "int" [ [ ] ] }
{ "uint" [ [ ] ] }
{ "long" [ [ ] ] }
{ "ulong" [ [ ] ] }
{ "longlong" [ [ ] ] }
{ "ulonglong" [ [ ] ] }
{ "float" [ [ ] ] }
{ "double" [ [ ] ] }
{ "bool*" [ [ unmarshall-bool*-free ] ] }
{ "boolean*" [ [ unmarshall-bool*-free ] ] }
{ "char*" [ [ ] ] }
{ "uchar*" [ [ unmarshall-uchar*-free ] ] }
{ "short*" [ [ unmarshall-short*-free ] ] }
{ "ushort*" [ [ unmarshall-ushort*-free ] ] }
{ "int*" [ [ unmarshall-int*-free ] ] }
{ "uint*" [ [ unmarshall-uint*-free ] ] }
{ "long*" [ [ unmarshall-long*-free ] ] }
{ "ulong*" [ [ unmarshall-ulong*-free ] ] }
{ "longlong*" [ [ unmarshall-long*-free ] ] }
{ "ulonglong*" [ [ unmarshall-ulong*-free ] ] }
{ "float*" [ [ unmarshall-float*-free ] ] }
{ "double*" [ [ unmarshall-double*-free ] ] }
{ "bool&" [ [ unmarshall-bool*-free ] ] }
{ "boolean&" [ [ unmarshall-bool*-free ] ] }
{ "char&" [ [ ] ] }
{ "uchar&" [ [ unmarshall-uchar*-free ] ] }
{ "short&" [ [ unmarshall-short*-free ] ] }
{ "ushort&" [ [ unmarshall-ushort*-free ] ] }
{ "int&" [ [ unmarshall-int*-free ] ] }
{ "uint&" [ [ unmarshall-uint*-free ] ] }
{ "long&" [ [ unmarshall-long*-free ] ] }
{ "ulong&" [ [ unmarshall-ulong*-free ] ] }
{ "longlong&" [ [ unmarshall-longlong*-free ] ] }
{ "ulonglong&" [ [ unmarshall-ulonglong*-free ] ] }
{ "float&" [ [ unmarshall-float*-free ] ] }
{ "double&" [ [ unmarshall-double*-free ] ] }
[ drop f ]
} case ;
: struct-primitive-unmarshaller ( type -- quot/f )
{
{ "bool" [ [ unmarshall-bool ] ] }
{ "boolean" [ [ unmarshall-bool ] ] }
{ "char" [ [ ] ] }
{ "uchar" [ [ ] ] }
{ "short" [ [ ] ] }
{ "ushort" [ [ ] ] }
{ "int" [ [ ] ] }
{ "uint" [ [ ] ] }
{ "long" [ [ ] ] }
{ "ulong" [ [ ] ] }
{ "longlong" [ [ ] ] }
{ "ulonglong" [ [ ] ] }
{ "float" [ [ ] ] }
{ "double" [ [ ] ] }
{ "bool*" [ [ unmarshall-bool* ] ] }
{ "boolean*" [ [ unmarshall-bool* ] ] }
{ "char*" [ [ ] ] }
{ "uchar*" [ [ unmarshall-uchar* ] ] }
{ "short*" [ [ unmarshall-short* ] ] }
{ "ushort*" [ [ unmarshall-ushort* ] ] }
{ "int*" [ [ unmarshall-int* ] ] }
{ "uint*" [ [ unmarshall-uint* ] ] }
{ "long*" [ [ unmarshall-long* ] ] }
{ "ulong*" [ [ unmarshall-ulong* ] ] }
{ "longlong*" [ [ unmarshall-long* ] ] }
{ "ulonglong*" [ [ unmarshall-ulong* ] ] }
{ "float*" [ [ unmarshall-float* ] ] }
{ "double*" [ [ unmarshall-double* ] ] }
{ "bool&" [ [ unmarshall-bool* ] ] }
{ "boolean&" [ [ unmarshall-bool* ] ] }
{ "char&" [ [ unmarshall-char* ] ] }
{ "uchar&" [ [ unmarshall-uchar* ] ] }
{ "short&" [ [ unmarshall-short* ] ] }
{ "ushort&" [ [ unmarshall-ushort* ] ] }
{ "int&" [ [ unmarshall-int* ] ] }
{ "uint&" [ [ unmarshall-uint* ] ] }
{ "long&" [ [ unmarshall-long* ] ] }
{ "ulong&" [ [ unmarshall-ulong* ] ] }
{ "longlong&" [ [ unmarshall-longlong* ] ] }
{ "ulonglong&" [ [ unmarshall-ulonglong* ] ] }
{ "float&" [ [ unmarshall-float* ] ] }
{ "double&" [ [ unmarshall-double* ] ] }
[ drop f ]
} case ;
: ?malloc-byte-array ( c-type -- alien )
dup alien? [ malloc-byte-array ] unless ;
:: x-unmarshaller ( type type-quot superclass def clean -- quot/f )
type type-quot call current-vocab lookup [
dup superclasses superclass swap member?
[ def call ] [ drop clean call f ] if
] [ clean call f ] if* ; inline
: struct-unmarshaller ( type -- quot/f )
[ ] \ struct-wrapper
[ '[ ?malloc-byte-array _ new swap >>underlying ] ]
[ ]
x-unmarshaller ;
: class-unmarshaller ( type -- quot/f )
[ type-sans-pointer "#" append ] \ class-wrapper
[ '[ _ new swap >>underlying ] ]
[ ]
x-unmarshaller ;
: non-primitive-unmarshaller ( type -- quot/f )
{
{ [ dup pointer? ] [ class-unmarshaller ] }
[ struct-unmarshaller ]
} cond ;
: unmarshaller ( type -- quot )
factorize-type {
[ primitive-unmarshaller ]
[ non-primitive-unmarshaller ]
[ drop [ ] ]
} 1|| ;
: struct-field-unmarshaller ( type -- quot )
factorize-type {
[ struct-primitive-unmarshaller ]
[ non-primitive-unmarshaller ]
[ drop [ ] ]
} 1|| ;
: out-arg-unmarshaller ( type -- quot )
dup pointer-to-non-const-primitive?
[ factorize-type primitive-unmarshaller ]
[ drop [ drop ] ] if ;
]]
FILE: [[alien/marshall/private/private.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.c-types alien.inline arrays
combinators fry functors kernel lexer libc macros math
sequences specialized-arrays libc.private
combinators.short-circuit alien.data ;
SPECIALIZED-ARRAY: void*
IN: alien.marshall.private
: bool>arg ( ? -- 1/0/obj )
{
{ t [ 1 ] }
{ f [ 0 ] }
[ ]
} case ;
MACRO: marshall-x* ( num-quot seq-quot -- alien )
'[ bool>arg dup number? _ _ if ] ;
: ptr-pass-through ( obj quot -- alien )
over { [ c-ptr? ] [ ] } 1&& [ drop ] [ call ] if ; inline
: malloc-underlying ( obj -- alien )
underlying>> malloc-byte-array ;
FUNCTOR: define-primitive-marshallers ( TYPE -- )
<TYPE> IS <${TYPE}>
*TYPE IS *${TYPE}
>TYPE-array IS >${TYPE}-array
marshall-TYPE DEFINES marshall-${TYPE}
(marshall-TYPE*) DEFINES (marshall-${TYPE}*)
(marshall-TYPE**) DEFINES (marshall-${TYPE}**)
marshall-TYPE* DEFINES marshall-${TYPE}*
marshall-TYPE** DEFINES marshall-${TYPE}**
marshall-TYPE*-free DEFINES marshall-${TYPE}*-free
marshall-TYPE**-free DEFINES marshall-${TYPE}**-free
unmarshall-TYPE* DEFINES unmarshall-${TYPE}*
unmarshall-TYPE*-free DEFINES unmarshall-${TYPE}*-free
WHERE
<PRIVATE
: (marshall-TYPE*) ( n/seq -- alien )
[ <TYPE> malloc-byte-array ]
[ >TYPE-array malloc-underlying ]
marshall-x* ;
PRIVATE>
: marshall-TYPE* ( n/seq -- alien )
[ (marshall-TYPE*) ] ptr-pass-through ;
<PRIVATE
: (marshall-TYPE**) ( seq -- alien )
[ marshall-TYPE* ] void*-array{ } map-as malloc-underlying ;
PRIVATE>
: marshall-TYPE** ( seq -- alien )
[ (marshall-TYPE**) ] ptr-pass-through ;
: unmarshall-TYPE* ( alien -- n )
*TYPE ; inline
: unmarshall-TYPE*-free ( alien -- n )
[ unmarshall-TYPE* ] keep add-malloc free ;
;FUNCTOR
SYNTAX: PRIMITIVE-MARSHALLERS:
";" parse-tokens [ define-primitive-marshallers ] each ;
]]
FILE: [[alien/marshall/private/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/marshall/structs/structs-docs.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: classes help.markup help.syntax kernel quotations words
alien.marshall.structs strings alien.structs alien.marshall ;
IN: alien.marshall.structs
HELP: define-marshalled-struct
{ $values
{ "name" string } { "vocab" "a vocabulary specifier" } { "fields" "an alist" }
}
{ $description "Calls " { $link define-struct } " and " { $link define-struct-tuple } "." } ;
HELP: define-struct-tuple
{ $values
{ "name" string }
}
{ $description "Defines a subclass of " { $link struct-wrapper } ", a constructor, "
"and accessor words."
} ;
]]
FILE: [[alien/marshall/structs/structs.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.c-types alien.marshall arrays assocs
classes.tuple combinators destructors generalizations generic
kernel libc locals parser quotations sequences slots words
alien.structs lexer vocabs.parser fry effects alien.data ;
IN: alien.marshall.structs
<PRIVATE
: define-struct-accessor ( class name quot -- )
[ "accessors" create create-method dup make-inline ] dip define ;
: define-struct-getter ( class name word type -- )
[ ">>" append \ underlying>> ] 2dip
struct-field-unmarshaller \ call 4array >quotation
define-struct-accessor ;
: define-struct-setter ( class name word type -- )
[ "<<" append ] 2dip
marshaller [ underlying>> ] \ bi* roll 4array >quotation
define-struct-accessor ;
: define-struct-accessors ( class name type reader writer -- )
[ dup define-protocol-slot ] 3dip
[ drop swap define-struct-getter ]
[ nip swap define-struct-setter ] 5 nbi ;
: define-struct-constructor ( class -- )
{
[ name>> "<" prepend ">" append create-word-in ]
[ '[ _ new ] ]
[ name>> '[ _ malloc-struct >>underlying ] append ]
[ name>> 1array ]
} cleave { } swap <effect> define-declared ;
PRIVATE>
:: define-struct-tuple ( name -- )
name create-word-in :> class
class struct-wrapper { } define-tuple-class
class define-struct-constructor
name c-type fields>> [
class swap
{
[ name>> H{ { CHAR: space CHAR: - } } substitute ]
[ type>> ] [ reader>> ] [ writer>> ]
} cleave define-struct-accessors
] each ;
: define-marshalled-struct ( name vocab fields -- )
[ define-struct ] [ 2drop define-struct-tuple ] 3bi ;
]]
FILE: [[alien/marshall/structs/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/marshall/marshall-docs.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel quotations sequences
strings alien alien.c-types alien.data math byte-arrays ;
IN: alien.marshall
<PRIVATE
: $memory-note ( arg -- )
drop "This word returns a pointer to unmanaged memory."
print-element ;
: $c-ptr-note ( arg -- )
drop "Does nothing if its argument is a non false c-ptr."
print-element ;
: $see-article ( arg -- )
drop { "See " { $vocab-link "alien.inline" } "." }
print-element ;
PRIVATE>
HELP: ?malloc-byte-array
{ $values
{ "c-type" c-type }
{ "alien" alien }
}
{ $description "Does nothing if input is an alien, otherwise assumes it is a byte array and calls "
{ $snippet "malloc-byte-array" } "."
}
{ $notes $memory-note } ;
HELP: alien-wrapper
{ $var-description "For wrapping C pointers in a structure factor can dispatch on." } ;
HELP: unmarshall-cast
{ $values
{ "alien-wrapper" alien-wrapper }
{ "alien-wrapper'" alien-wrapper }
}
{ $description "Called immediately after unmarshalling. Useful for automatically casting to subtypes." } ;
HELP: marshall-bool
{ $values
{ "?" "a generalized boolean" }
{ "n" "0 or 1" }
}
{ $description "Marshalls objects to bool." }
{ $notes "Will treat " { $snippet "0" } " as " { $snippet "t" } "." } ;
HELP: marshall-bool*
{ $values
{ "?/seq" "t/f or sequence" }
{ "alien" alien }
}
{ $description "When the argument is a sequence, returns a pointer to an array of bool, "
"otherwise returns a pointer to a single bool value."
}
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-bool**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description "Takes a one or two dimensional array of generalized booleans "
"and returns a pointer to the equivalent C structure."
}
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-primitive
{ $values
{ "n" number }
{ "n" number }
}
{ $description "Marshall numbers to C primitives."
$nl
"Factor marshalls numbers to primitives for FFI calls, so all "
"this word does is convert " { $snippet "t" } " to " { $snippet "1" }
", " { $snippet "f" } " to " { $snippet "0" } ", and lets anything else "
"pass through untouched."
} ;
HELP: marshall-char*
{ $values
{ "n/seq" "number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-char**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-char**-or-strings
{ $values
{ "seq" "a sequence of strings" }
{ "alien" alien }
}
{ $description "Marshalls an array of strings or characters to an array of C strings." }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-char*-or-string
{ $values
{ "n/string" "a number or string" }
{ "alien" alien }
}
{ $description "Marshalls a string to a C string or a number to a pointer to " { $snippet "char" } "." }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-double*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-double**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-float*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-float**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-int*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-int**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-long*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-long**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-longlong*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-longlong**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-non-pointer
{ $values
{ "alien-wrapper/byte-array" "an alien-wrapper or byte-array" }
{ "byte-array" byte-array }
}
{ $description "Converts argument to a byte array." }
{ $notes "Not meant to be called directly. Use the output of " { $link marshaller } " instead." } ;
HELP: marshall-pointer
{ $values
{ "obj" object }
{ "alien" alien }
}
{ $description "Converts argument to a C pointer." }
{ $notes "Can marshall the following types: " { $snippet "alien, f, byte-array, alien-wrapper, struct-array" } "." } ;
HELP: marshall-short*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-short**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-uchar*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-uchar**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-uint*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-uint**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-ulong*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-ulong**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-ulonglong*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-ulonglong**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-ushort*
{ $values
{ "n/seq" "a number or sequence" }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-ushort**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description $see-article }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshall-void**
{ $values
{ "seq" sequence }
{ "alien" alien }
}
{ $description "Marshalls a sequence of objects to an array of pointers to void." }
{ $notes { $list $c-ptr-note $memory-note } } ;
HELP: marshaller
{ $values
{ "type" "a C type string" }
{ "quot" quotation }
}
{ $description "Given a C type, returns a quotation that will marshall its argument to that type." } ;
HELP: out-arg-unmarshaller
{ $values
{ "type" "a C type string" }
{ "quot" quotation }
}
{ $description "Like " { $link unmarshaller } " but returns an empty quotation "
"for all types except pointers to non-const primitives."
} ;
HELP: class-unmarshaller
{ $values
{ "type" " a C type string" }
{ "quot/f" quotation }
}
{ $description "If in the vocab in which this word is called, there is a subclass of " { $link alien-wrapper }
" named after the type argument, " { $snippet "pointer-unmarshaller" } " will return a quotation which "
"wraps its argument in an instance of that subclass. In any other case it returns an empty quotation."
}
{ $notes "Not meant to be called directly. Use the output of " { $link marshaller } " instead." } ;
HELP: primitive-marshaller
{ $values
{ "type" "a C type string" }
{ "quot/f" "a quotation or f" }
}
{ $description "Returns a quotation to marshall objects to the argument type." }
{ $notes "Not meant to be called directly. Use the output of " { $link marshaller } " instead." } ;
HELP: primitive-unmarshaller
{ $values
{ "type" "a C type string" }
{ "quot/f" "a quotation or f" }
}
{ $description "Returns a quotation to unmarshall objects from the argument type." }
{ $notes "Not meant to be called directly. Use the output of " { $link unmarshaller } " instead." } ;
HELP: struct-field-unmarshaller
{ $values
{ "type" "a C type string" }
{ "quot" quotation }
}
{ $description "Like " { $link unmarshaller } " but returns a quotation that "
"does not call " { $snippet "free" } " on its argument."
}
{ $notes "Not meant to be called directly. Use the output of " { $link unmarshaller } " instead." } ;
HELP: struct-primitive-unmarshaller
{ $values
{ "type" "a C type string" }
{ "quot/f" "a quotation or f" }
}
{ $description "Like " { $link primitive-unmarshaller } " but returns a quotation that "
"does not call " { $snippet "free" } " on its argument." }
{ $notes "Not meant to be called directly. Use the output of " { $link unmarshaller } " instead." } ;
HELP: struct-unmarshaller
{ $values
{ "type" "a C type string" }
{ "quot/f" quotation }
}
{ $description "Returns a quotation which wraps its argument in the subclass of "
{ $link struct-wrapper } " which matches the " { $snippet "type" } " arg."
}
{ $notes "Not meant to be called directly. Use the output of " { $link unmarshaller } " instead." } ;
HELP: struct-wrapper
{ $var-description "For wrapping C structs in a structure factor can dispatch on." } ;
HELP: unmarshall-bool
{ $values
{ "n" number }
{ "?" boolean }
}
{ $description "Unmarshalls a number to a boolean." } ;
HELP: unmarshall-bool*
{ $values
{ "alien" alien }
{ "?" boolean }
}
{ $description "Unmarshalls a C pointer to a boolean." } ;
HELP: unmarshall-bool*-free
{ $values
{ "alien" alien }
{ "?" boolean }
}
{ $description "Unmarshalls a C pointer to a boolean and frees the pointer." } ;
HELP: unmarshall-char*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-char*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-char*-to-string
{ $values
{ "alien" alien }
{ "string" string }
}
{ $description "Unmarshalls a " { $snippet "char" } " pointer to a factor string." } ;
HELP: unmarshall-char*-to-string-free
{ $values
{ "alien" alien }
{ "string" string }
}
{ $description "Unmarshalls a " { $snippet "char" } " pointer to a factor string and frees the pointer." } ;
HELP: unmarshall-double*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-double*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-float*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-float*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-int*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-int*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-long*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-long*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-longlong*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-longlong*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-short*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-short*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-uchar*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-uchar*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-uint*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-uint*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-ulong*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-ulong*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-ulonglong*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-ulonglong*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-ushort*
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshall-ushort*-free
{ $values
{ "alien" alien }
{ "n" number }
}
{ $description $see-article } ;
HELP: unmarshaller
{ $values
{ "type" "a C type string" }
{ "quot" quotation }
}
{ $description "Given a C type, returns a quotation that will unmarshall values of that type." } ;
ARTICLE: "alien.marshall" "C marshalling"
{ $vocab-link "alien.marshall" } " provides alien wrappers and marshalling words for the "
"automatic marshalling and unmarshalling of C function arguments, return values, and output parameters."
{ $subheading "Important words" }
"Wrap an alien:" { $subsections alien-wrapper }
"Wrap a struct:" { $subsections struct-wrapper }
"Get the marshaller for a C type:" { $subsections marshaller }
"Get the unmarshaller for a C type:" { $subsections unmarshaller }
"Get the unmarshaller for an output parameter:" { $subsections out-arg-unmarshaller }
"Get the unmarshaller for a struct field:" { $subsections struct-field-unmarshaller }
$nl
"Other marshalling and unmarshalling words in this vocabulary are not intended to be "
"invoked directly."
$nl
"Most marshalling words allow non false c-ptrs to pass through unchanged."
{ $subheading "Primitive marshallers" }
{ $subsections marshall-primitive } "for marshalling primitive values."
{ $subsections marshall-int* }
"marshalls a number or sequence of numbers. If argument is a sequence, returns a pointer "
"to a C array, otherwise returns a pointer to a single value."
{ $subsections marshall-int** }
"marshalls a 1D or 2D array of numbers. Returns an array of pointers to arrays."
{ $subheading "Primitive unmarshallers" }
{ $snippet "unmarshall-<prim>*" } " and " { $snippet "unmarshall-<prim>*-free" }
" for all values of " { $snippet "<prim>" } " in " { $link primitive-types } "."
{ $subsections unmarshall-int* }
"unmarshalls a pointer to primitive. Returns a number. "
"Assumes the pointer is not an array (if it is, only the first value is returned). "
"C functions that return arrays are not handled correctly by " { $snippet "alien.marshall" }
" and must be unmarshalled by hand."
{ $subsections unmarshall-int*-free }
"unmarshalls a pointer to primitive, and then frees the pointer."
$nl
"Primitive values require no unmarshalling. The factor FFI already does this."
;
ABOUT: "alien.marshall"
]]
FILE: [[alien/marshall/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/marshall/syntax/syntax.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien.inline alien.inline.types alien.marshall
combinators effects generalizations kernel locals make namespaces
quotations sequences words alien.marshall.structs lexer parser
vocabs.parser multiline ;
IN: alien.marshall.syntax
:: marshalled-function ( name types effect -- word quot effect )
name types effect factor-function
[ in>> ]
[ out>> types [ pointer-to-non-const-primitive? ] filter append ]
bi <effect>
[
[
types [ marshaller ] map , \ spread , ,
types length , \ nkeep ,
types [ out-arg-unmarshaller ] map
effect out>> dup empty?
[ drop ] [ first unmarshaller prefix ] if
, \ spread ,
] [ ] make
] dip ;
: define-c-marshalled ( name types effect body -- )
[
[ marshalled-function define-declared ]
[ prototype-string ] 3bi
] dip append-function-body c-strings get push ;
: define-c-marshalled' ( name effect body -- )
[
[ in>> ] keep
[ marshalled-function define-declared ]
[ out>> prototype-string' ] 3bi
] dip append-function-body c-strings get push ;
SYNTAX: CM-FUNCTION:
function-types-effect parse-here define-c-marshalled ;
SYNTAX: M-FUNCTION:
function-types-effect marshalled-function define-declared ;
SYNTAX: M-STRUCTURE:
scan current-vocab parse-definition
define-marshalled-struct ;
SYNTAX: CM-STRUCTURE:
scan current-vocab parse-definition
[ define-marshalled-struct ] [ nip define-c-struct ] 3bi ;
]]
FILE: [[alien/marshall/syntax/syntax-tests.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.inline.syntax alien.marshall.syntax destructors
tools.test accessors kernel ;
IN: alien.marshall.syntax.tests
DELETE-C-LIBRARY: test
C-LIBRARY: test
C-INCLUDE: <stdlib.h>
C-INCLUDE: <string.h>
C-INCLUDE: <stdbool.h>
CM-FUNCTION: void outarg1 ( int* a )
*a += 2;
;
CM-FUNCTION: unsigned-long* outarg2 ( unsigned-long a, unsigned-long* b )
unsigned long* x = malloc(sizeof(unsigned long*));
*b = 10 + *b;
*x = a + *b;
return x;
;
CM-STRUCTURE: wedge
{ "double" "degrees" } ;
CM-STRUCTURE: sundial
{ "double" "radius" }
{ "wedge" "wedge" } ;
CM-FUNCTION: double hours ( sundial* d )
return d->wedge.degrees / 30;
;
CM-FUNCTION: void change_time ( double hours, sundial* d )
d->wedge.degrees = hours * 30;
;
CM-FUNCTION: bool c_not ( bool p )
return !p;
;
CM-FUNCTION: char* upcase ( const-char* s )
int len = strlen(s);
char* t = malloc(sizeof(char) * len);
int i;
for (i = 0; i < len; i++)
t[i] = toupper(s[i]);
t[i] = '\0';
return t;
;
;C-LIBRARY
{ 1 1 } [ outarg1 ] must-infer-as
[ 3 ] [ 1 outarg1 ] unit-test
[ 3 ] [ t outarg1 ] unit-test
[ 2 ] [ f outarg1 ] unit-test
{ 2 2 } [ outarg2 ] must-infer-as
[ 18 15 ] [ 3 5 outarg2 ] unit-test
{ 1 1 } [ hours ] must-infer-as
[ 5.0 ] [ <sundial> <wedge> 150 >>degrees >>wedge hours ] unit-test
{ 2 0 } [ change_time ] must-infer-as
[ 150.0 ] [ 5 <sundial> <wedge> 11 >>degrees >>wedge [ change_time ] keep wedge>> degrees>> ] unit-test
{ 1 1 } [ c_not ] must-infer-as
[ f ] [ "x" c_not ] unit-test
[ f ] [ 0 c_not ] unit-test
{ 1 1 } [ upcase ] must-infer-as
[ "ABC" ] [ "abc" upcase ] unit-test
]]
FILE: [[alien/marshall/syntax/authors.txt]] [[Jeremy Hughes
]]
FILE: [[alien/marshall/syntax/syntax-docs.factor]] [[! Copyright (C) 2009 Jeremy Hughes.
! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax kernel quotations words
alien.inline alien.syntax effects alien.marshall
alien.marshall.structs strings sequences alien.inline.syntax ;
IN: alien.marshall.syntax
HELP: CM-FUNCTION:
{ $syntax "CM-FUNCTION: return name args\n body\n;" }
{ $description "Like " { $link POSTPONE: C-FUNCTION: } " but with marshalling "
"of arguments and return values."
}
{ $examples
{ $example
"USING: alien.inline.syntax alien.marshall.syntax prettyprint ;"
"IN: example"
""
"C-LIBRARY: exlib"
""
"C-INCLUDE: <stdio.h>"
"C-INCLUDE: <stdlib.h>"
"CM-FUNCTION: char* sum_diff ( const-int a, const-int b, int* x, int* y )"
" *x = a + b;"
" *y = a - b;"
" char* s = (char*) malloc(sizeof(char) * 64);"
" sprintf(s, \"sum %i, diff %i\", *x, *y);"
" return s;"
";"
""
";C-LIBRARY"
""
"8 5 0 0 sum_diff . . ."
"3\n13\n\"sum 13, diff 3\""
}
}
{ $see-also define-c-marshalled POSTPONE: C-FUNCTION: POSTPONE: M-FUNCTION: } ;
HELP: CM-STRUCTURE:
{ $syntax "CM-STRUCTURE: name fields ... ;" }
{ $description "Like " { $link POSTPONE: C-STRUCTURE: } " but with marshalling of fields. "
"Defines a subclass of " { $link struct-wrapper } " a constructor, and slot-like accessor words."
}
{ $see-also POSTPONE: C-STRUCTURE: POSTPONE: M-STRUCTURE: } ;
HELP: M-FUNCTION:
{ $syntax "M-FUNCTION: return name args ;" }
{ $description "Like " { $link POSTPONE: FUNCTION: } " but with marshalling "
"of arguments and return values."
}
{ $see-also marshalled-function POSTPONE: C-FUNCTION: POSTPONE: CM-FUNCTION: } ;
HELP: M-STRUCTURE:
{ $syntax "M-STRUCTURE: name fields ... ;" }
{ $description "Like " { $link POSTPONE: C-STRUCT: } " but with marshalling of fields. "
"Defines a subclass of " { $link struct-wrapper } " a constructor, and slot-like accessor words."
}
{ $see-also define-marshalled-struct POSTPONE: C-STRUCTURE: POSTPONE: CM-STRUCTURE: } ;
HELP: define-c-marshalled
{ $values
{ "name" string } { "types" sequence } { "effect" effect } { "body" string }
}
{ $description "Defines a C function and a factor word which calls it with marshalling of "
"args and return values."
}
{ $see-also define-c-marshalled' } ;
HELP: define-c-marshalled'
{ $values
{ "name" string } { "effect" effect } { "body" string }
}
{ $description "Like " { $link define-c-marshalled } ". "
"The effect elements must be C type strings."
} ;
HELP: marshalled-function
{ $values
{ "name" string } { "types" sequence } { "effect" effect }
{ "word" word } { "quot" quotation } { "effect" effect }
}
{ $description "Defines a word which calls the named C function. Arguments, "
"return value, and output parameters are marshalled and unmarshalled."
} ;
]]
FILE: [[specialized/specialized.factor]] [[! Copyright (C) 2009, 2010 Daniel Ehrenberg
! See http://factorcode.org/license.txt for BSD license.
USING: words kernel locals accessors compiler.tree.propagation.info
sequences kernel.private assocs fry parser math quotations
effects arrays definitions compiler.units namespaces
compiler.tree.debugger generalizations stack-checker ;
IN: specialized
: in-compilation-unit? ( -- ? )
changed-definitions get >boolean ;
: define-temp-in-unit ( quot effect -- word )
in-compilation-unit?
[ [ define-temp ] with-nested-compilation-unit ]
[ [ define-temp ] with-compilation-unit ]
if ;
: final-info-quot ( word -- quot )
[ stack-effect in>> length '[ _ ndrop ] ]
[ def>> [ final-info ] with-scope >quotation ] bi
compose ;
ERROR: bad-outputs word quot ;
: define-outputs ( word quot -- )
2dup [ stack-effect ] [ infer ] bi* effect<=
[ "outputs" set-word-prop ] [ bad-outputs ] if ;
: record-final-info ( word -- )
dup final-info-quot define-outputs ;
:: lookup-specialized ( #call word n -- special-word/f )
#call in-d>> n tail* >array [ value-info class>> ] map
dup [ object = ] all? [ drop f ] [
word "specialized-defs" word-prop [
[ declare ] curry word def>> compose
word stack-effect define-temp-in-unit
dup record-final-info
1quotation
] cache
] if ;
: specialized-quot ( word n -- quot )
'[ _ _ lookup-specialized ] ;
: make-specialized ( word n -- )
[ drop H{ } clone "specialized-defs" set-word-prop ]
[ dupd specialized-quot "custom-inlining" set-word-prop ] 2bi ;
SYNTAX: specialized
last-word dup stack-effect in>> length make-specialized ;
PREDICATE: specialized-word < word
"specialized-defs" word-prop >boolean ;
]]
FILE: [[math/newtons-method/newtons-method.factor]] [[! Copyright (c) 2008 Reginald Keith Ford II.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel math math.derivatives ;
IN: math.newtons-method
! Newton's method of approximating roots
<PRIVATE
: newton-step ( x function -- x2 )
dupd [ call ] [ derivative ] 2bi / - ; inline
: newton-precision ( -- n ) 13 ; inline
PRIVATE>
: newtons-method ( guess function -- x )
newton-precision [ [ newton-step ] keep ] times drop ;
]]
FILE: [[math/newtons-method/authors.txt]] [[Reginald Ford
]]
FILE: [[math/derivatives/derivatives.factor]] [[! Copyright (c) 2008 Reginald Keith Ford II, Eduardo Cavazos.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel continuations combinators sequences math math.order math.ranges
accessors float-arrays ;
IN: math.derivatives
TUPLE: state x func h err i j errt fac hh ans a done ;
: largest-float ( -- x ) 0x7fefffffffffffff bits>double ; foldable
: ntab ( -- val ) 8 ; inline
: con ( -- val ) 1.6 ; inline
: con2 ( -- val ) con con * ; inline
: big ( -- val ) largest-float ; inline
: safe ( -- val ) 2.0 ; inline
! Yes, this was ported from C code.
: a[i][i] ( state -- elt ) [ i>> ] [ i>> ] [ a>> ] tri nth nth ;
: a[j][i] ( state -- elt ) [ i>> ] [ j>> ] [ a>> ] tri nth nth ;
: a[j-1][i] ( state -- elt ) [ i>> ] [ j>> 1 - ] [ a>> ] tri nth nth ;
: a[j-1][i-1] ( state -- elt ) [ i>> 1 - ] [ j>> 1 - ] [ a>> ] tri nth nth ;
: a[i-1][i-1] ( state -- elt ) [ i>> 1 - ] [ i>> 1 - ] [ a>> ] tri nth nth ;
: check-h ( state -- state )
dup h>> 0 = [ "h must be nonzero in dfridr" throw ] when ;
: init-a ( state -- state ) ntab [ ntab <float-array> ] replicate >>a ;
: init-hh ( state -- state ) dup h>> >>hh ;
: init-err ( state -- state ) big >>err ;
: update-hh ( state -- state ) dup hh>> con / >>hh ;
: reset-fac ( state -- state ) con2 >>fac ;
: update-fac ( state -- state ) dup fac>> con2 * >>fac ;
! If error is decreased, save the improved answer
: error-decreased? ( state -- state ? ) [ ] [ errt>> ] [ err>> ] tri <= ;
: save-improved-answer ( state -- state )
dup err>> >>errt
dup a[j][i] >>ans ;
! If higher order is worse by a significant factor SAFE, then quit early.
: check-safe ( state -- state )
dup [ [ a[i][i] ] [ a[i-1][i-1] ] bi - abs ]
[ err>> safe * ] bi >= [ t >>done ] when ;
: x+hh ( state -- val ) [ x>> ] [ hh>> ] bi + ;
: x-hh ( state -- val ) [ x>> ] [ hh>> ] bi - ;
: limit-approx ( state -- val )
[
[ [ x+hh ] [ func>> ] bi call ]
[ [ x-hh ] [ func>> ] bi call ] bi -
] [ hh>> 2.0 * ] bi / ;
: a[0][0]! ( state -- state )
{ [ ] [ limit-approx ] [ drop 0 ] [ drop 0 ] [ a>> ] } cleave nth set-nth ;
: a[0][i]! ( state -- state )
{ [ ] [ limit-approx ] [ i>> ] [ drop 0 ] [ a>> ] } cleave nth set-nth ;
: a[j-1][i]*fac ( state -- val ) [ a[j-1][i] ] [ fac>> ] bi * ;
: new-a[j][i] ( state -- val )
[ [ a[j-1][i]*fac ] [ a[j-1][i-1] ] bi - ]
[ fac>> 1.0 - ] bi / ;
: a[j][i]! ( state -- state )
{ [ ] [ new-a[j][i] ] [ i>> ] [ j>> ] [ a>> ] } cleave nth set-nth ;
: update-errt ( state -- state )
dup [ [ a[j][i] ] [ a[j-1][i] ] bi - abs ]
[ [ a[j][i] ] [ a[j-1][i-1] ] bi - abs ] bi max >>errt ;
: not-done? ( state -- state ? ) dup done>> not ;
: derive ( state -- state )
init-a
check-h
init-hh
a[0][0]!
init-err
1 ntab [a,b) [
>>i not-done? [
update-hh
a[0][i]!
reset-fac
1 over i>> [a,b] [
>>j
a[j][i]!
update-fac
update-errt
error-decreased? [ save-improved-answer ] when
] each check-safe
] when
] each ;
: derivative-state ( x func h err -- state )
state new
swap >>err
swap >>h
swap >>func
swap >>x ;
! For scientists:
! h should be .001 to .5 -- too small can cause bad convergence,
! h should be small enough to give the correct sgn(f'(x))
! err is the max tolerance of gain in error for a single iteration-
: (derivative) ( x func h err -- ans error )
derivative-state derive [ ans>> ] [ errt>> ] bi ;
: derivative ( x func -- m ) 0.01 2.0 (derivative) drop ;
: derivative-func ( func -- der ) [ derivative ] curry ;
]]
FILE: [[math/derivatives/derivatives-tests.factor]] [[USING: math math.derivatives tools.test ;
IN: math.derivatives.test
[ 8 ] [ 4 [ sq ] derivative >integer ] unit-test
]]
FILE: [[math/derivatives/authors.txt]] [[Reginald Ford
Eduardo Cavazos
]]
FILE: [[math/derivatives/derivatives-docs.factor]] [[USING: help.markup help.syntax math math.functions ;
IN: math.derivatives
HELP: derivative
{ $values { "x" "a position on the function" } { "function" "a differentiable function" } { "m" number } }
{ $description
"Approximates the slope of the tangent line by using Ridders' "
"method of computing derivatives, from the chapter \"Accurate computation "
"of F'(x) and F'(x)F''(x)\", from \"Advances in Engineering Software, Vol. 4, pp. 75-76 ."
}
{ $examples
{ $example
"USING: math math.derivatives prettyprint ;"
"4 [ sq ] derivative >integer ."
"8"
}
{ $notes
"For applied scientists, you may play with the settings "
"in the source file to achieve arbitrary accuracy. "
}
} ;
HELP: (derivative)
{ $values
{ "x" "a position on the function" }
{ "func" "a differentiable function" }
{
"h" "distance between the points of the first secant line used for "
"approximation of the tangent. This distance will be divided "
"constantly, by " { $link con } ". See " { $link init-hh }
" for the code which enforces this. H should be .001 to .5 -- too "
"small can cause bad convergence. Also, h should be small enough "
"to give the correct sgn(f'(x)). In other words, if you're expecting "
"a positive derivative, make h small enough to give the same "
"when plugged into the academic limit definition of a derivative. "
"See " { $link update-hh } " for the code which performs this task."
}
{
"err" "maximum tolerance of increase in error. For example, if this "
"is set to 2.0, the program will terminate with its nearest answer "
"when the error multiplies by 2. See " { $link check-safe } " for "
"the enforcing code."
}
{ "ans" number }
{ "error" number }
}
{ $description
"Approximates the slope of the tangent line by using Ridders' "
"method of computing derivatives, from the chapter \"Accurate computation "
"of F'(x) and F'(x)F''(x)\", from \"Advances in Engineering Software, "
"Vol. 4, pp. 75-76 ."
}
{ $examples
{ $example
"USING: math math.derivatives prettyprint ;"
"4 [ sq ] derivative >integer ."
"8"
}
{ $notes
"For applied scientists, you may play with the settings "
"in the source file to achieve arbitrary accuracy. "
}
} ;
HELP: derivative-func
{ $values { "func" "a differentiable function" } { "der" "the derivative" } }
{ $description
"Provides the derivative of the function. The implementation simply "
"attaches the " { $link derivative } " word to the end of the function."
}
{ $examples
{ $example
"USING: kernel math.derivatives math.functions math.trig prettyprint ;"
"60 deg>rad [ sin ] derivative-func call 0.5 .001 ~ ."
"t"
}
{ $notes
"Without a heavy algebraic system, derivatives must be "
"approximated. With the current settings, there is a fair trade of "
"speed and accuracy; the first 12 digits "
"will always be correct with " { $link sin } " and " { $link cos }
". The following code performs a minumum and maximum error test."
{ $code
"USING: kernel math math.functions math.trig sequences sequences.lib ;"
"360"
"["
" deg>rad"
" [ [ sin ] derivative-func call ]"
" ! Note: the derivative of sin is cos"
" [ cos ]"
" bi - abs"
"] map minmax"
}
}
} ;
ARTICLE: "derivatives" "The Derivative Toolkit"
"A toolkit for computing the derivative of functions."
{ $subsections
derivative
derivative-func
(derivative)
} ;
ABOUT: "derivatives"
]]
FILE: [[math/physics/vel/vel.factor]] [[
USING: math.physics.pos ;
IN: math.physics.vel
TUPLE: vel < pos vel ;
]]
FILE: [[math/physics/pos/pos.factor]] [[
USING: kernel sequences multi-methods accessors math.vectors ;
IN: math.physics.pos
TUPLE: pos pos ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
GENERIC: distance ( a b -- c )
METHOD: distance { sequence sequence } v- norm ;
METHOD: distance { pos pos } [ pos>> ] bi@ distance ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
]]
FILE: [[mongodb/gridfs/gridfs/unmaintained-reason.txt]] [[Moved to unmaintained by Joe Groff October 13, 2011
The input stream protocol was changed; streams should now provide methods for
stream-read-unsafe and stream-read-partial-unsafe, which read into a caller-
provided buffer. This module has no tests so I didn't want to break it in the
process of updating it.
]]
FILE: [[mongodb/gridfs/gridfs/gridfs.factor]] [[USING: accessors arrays assocs base64 bson.constants
byte-arrays byte-vectors calendar combinators
combinators.short-circuit destructors formatting fry hashtables
io kernel linked-assocs locals math math.parser mongodb.cmd
mongodb.connection mongodb.driver mongodb.msg namespaces
sequences splitting strings ;
FROM: mongodb.driver => update ;
IN: mongodb.gridfs
CONSTANT: default-chunk-size 262144
TUPLE: gridfs
{ bucket string }
{ files string }
{ chunks string } ;
<PRIVATE
: gridfs> ( -- gridfs )
gridfs get ; inline
: files-collection ( -- str ) gridfs> files>> ; inline
: chunks-collection ( -- str ) gridfs> chunks>> ; inline
: init-gridfs ( gridfs -- )
chunks>> "ChunkIdx" H{ { "files_id" 1 } { "n" 1 } }
<index-spec> ensure-index ; inline
PRIVATE>
: <gridfs> ( bucket -- gridfs )
[ ]
[ "files" "%s.%s" sprintf ]
[ "chunks" "%s.%s" sprintf ] tri
gridfs boa [ init-gridfs ] keep ;
: with-gridfs ( gridfs quot -- * )
[ gridfs ] dip with-variable ; inline
TUPLE: entry
{ id oid }
{ filename string }
{ content-type string }
{ length integer }
{ chunk-size integer }
{ created timestamp }
{ aliases array }
{ metadata hashtable }
{ md5 string } ;
<PRIVATE
: id>base64 ( id -- str )
[ a>> >hex ] [ b>> >hex ] bi
2array "#" join >base64 >string ; inline
: base64>id ( str -- objid )
base64> >string "#" split
[ first ] [ second ] bi
[ hex> ] bi@ oid boa ; inline
PRIVATE>
: <entry> ( name content-type -- entry )
entry new
swap >>content-type swap >>filename
<oid> >>id 0 >>length default-chunk-size >>chunk-size
now >>created ; inline
<PRIVATE
TUPLE: chunk
{ id oid }
{ fileid oid }
{ n integer }
{ data byte-array } ;
: at> ( assoc key -- value/f )
swap at ; inline
:: >set-at ( assoc value key -- )
value key assoc set-at ; inline
: (update-file) ( entry assoc -- entry )
{
[ "_id" at> >>id ]
[ "filename" at> >>filename ]
[ "contentType" at> >>content-type ]
[ "length" at> >>length ]
[ "chunkSize" at> >>chunk-size ]
[ "uploadDate" at> >>created ]
[ "aliases" at> >>aliases ]
[ "metadata" at> >>metadata ]
[ "md5" at> >>md5 ]
} cleave ; inline
: assoc>chunk ( assoc -- chunk )
[ chunk new ] dip
{
[ "_id" at> >>id ]
[ "files_id" at> >>fileid ]
[ "n" at> >>n ]
[ "data" at> >>data ]
} cleave ;
: assoc>entry ( assoc -- entry )
[ entry new ] dip (update-file) ;
: entry>assoc ( entry -- assoc )
[ H{ } clone ] dip
{
[ id>> "_id" >set-at ]
[ filename>> "filename" >set-at ]
[ content-type>> "contentType" >set-at ]
[ length>> "length" >set-at ]
[ chunk-size>> "chunkSize" >set-at ]
[ created>> "uploadDate" >set-at ]
[ aliases>> "aliases" >set-at ]
[ metadata>> "metadata" >set-at ]
[ md5>> "md5" >set-at ]
[ drop ]
} 2cleave ; inline
: create-entry ( entry -- entry )
[ [ files-collection ] dip entry>assoc save ] [ ] bi ;
TUPLE: state bytes count ;
: <state> ( -- state )
0 0 state boa ; inline
: get-state ( -- n )
state get ; inline
: with-state ( quot -- state )
[ <state> state ] dip
[ get-state ] compose
with-variable ; inline
: update-state ( bytes -- )
[ get-state ] dip
'[ _ + ] change-bytes
[ 1 + ] change-count drop ; inline
:: store-chunk ( chunk entry n -- )
entry id>> :> id
H{ { "files_id" id }
{ "n" n } { "data" chunk } }
[ chunks-collection ] dip save ; inline
:: write-chunks ( stream entry -- length )
entry chunk-size>> :> chunk-size
[
[
chunk-size stream stream-read dup [
[ entry get-state count>> store-chunk ]
[ length update-state ] bi
] when*
] loop
] with-state bytes>> ;
: (entry-selector) ( entry -- selector )
id>> "_id" associate ; inline
:: file-md5 ( id -- md5-str )
filemd5-cmd make-cmd
id "filemd5" set-cmd-opt
gridfs> bucket>> "root" set-cmd-opt
send-cmd "md5" at> ; inline
: update-entry ( bytes entry -- entry )
[ swap >>length dup id>> file-md5 >>md5 ]
[ nip [ (entry-selector) ] [ ] bi
[ length>> "length" associate "$set" associate
[ files-collection ] 2dip <update> update ]
[ md5>> "md5" associate "$set" associate
[ files-collection ] 2dip <update> update ] 2bi
] 2bi ;
TUPLE: gridfs-input-stream entry chunk n offset cpos ;
: <gridfs-input-stream> ( entry -- stream )
[ gridfs-input-stream new ] dip
>>entry 0 >>offset 0 >>cpos -1 >>n ;
PRIVATE>
: write-entry ( input-stream entry -- entry )
create-entry [ write-chunks ] keep update-entry ;
: get-entry ( id -- entry )
[ files-collection ] dip
"_id" associate <query> find-one assoc>entry ;
: open-entry ( entry -- input-stream )
<gridfs-input-stream> ;
: entry-contents ( entry -- bytearray )
<gridfs-input-stream> stream-contents ;
<PRIVATE
: load-chunk ( stream -- chunk/f )
[ entry>> id>> "files_id" associate ]
[ n>> "n" associate ] bi assoc-union
[ chunks-collection ] dip
<query> find-one dup [ assoc>chunk ] when ;
: exhausted? ( stream -- boolean )
[ offset>> ] [ entry>> length>> ] bi = ; inline
: fresh? ( stream -- boolean )
[ offset>> 0 = ] [ chunk>> f = ] bi and ; inline
: data-available ( stream -- int/f )
[ cpos>> ] [ chunk>> data>> length ] bi
2dup < [ swap - ] [ 2drop f ] if ; inline
: next-chunk ( stream -- available chunk/f )
0 >>cpos [ 1 + ] change-n
[ ] [ load-chunk ] bi >>chunk
[ data-available ] [ chunk>> ] bi ; inline
: ?chunk ( stream -- available chunk/f )
dup fresh? [ next-chunk ] [
dup exhausted? [ drop 0 f ] [
dup data-available [ swap chunk>> ] [ next-chunk ] if*
] if
] if ; inline
: set-stream ( n stream -- )
swap {
[ >>offset drop ]
[ over entry>> chunk-size>> /mod [ >>n ] [ >>cpos ] bi* drop ]
[ drop dup load-chunk >>chunk drop ]
} 2cleave ; inline
:: advance-stream ( n stream -- )
stream [ n + ] change-cpos [ n + ] change-offset drop ; inline
: read-part ( n stream chunk -- seq/f )
[ [ cpos>> swap [ drop ] [ + ] 2bi ] [ data>> ] bi* <slice> ]
[ drop advance-stream ] 3bi ; inline
:: (stream-read-partial) ( n stream -- seq/f )
stream ?chunk :> chunk :> available
chunk [
n available <
[ n ] [ available ] if
stream chunk read-part
] [ f ] if ; inline
:: (stream-read) ( n stream acc -- )
n stream (stream-read-partial)
{
{ [ dup not ] [ drop ] }
{ [ dup length n = ] [ acc push-all ] }
{ [ dup length n < ] [
[ acc push-all ] [ length ] bi
n swap - stream acc (stream-read) ]
}
} cond ; inline recursive
PRIVATE>
M: gridfs-input-stream stream-element-type drop +byte+ ;
M: gridfs-input-stream stream-read ( n stream -- seq/f )
over <byte-vector> [ (stream-read) ] [ ] bi
[ f ] [ >byte-array ] if-empty ;
M: gridfs-input-stream stream-read-partial ( n stream -- seq/f )
(stream-read-partial) ;
M: gridfs-input-stream stream-tell ( stream -- n )
offset>> ;
M: gridfs-input-stream stream-seek ( n seek-type stream -- )
swap seek-absolute =
[ set-stream ]
[ "seek-type not supported" throw ] if ;
M: gridfs-input-stream dispose drop ;
]]
FILE: [[README.md]] [[# Factor
The Factor project is maintained and mirrored at [https://github.com/factor/factor](https://github.com/factor/factor)
## Unmaintained Factor Vocabularies
Unmaintained, neglected, bit-rotted, or just terrible vocabularies that were once in a subdirectory of the Factor project.
]]
FILE: [[fries/fries.factor]] [[USING: arrays vectors combinators effects kernel math sequences splitting
strings.parser parser fry sequences.extras ;
! a b c glue => acb
! c b a [ append ] dip prepend
IN: fries
: str-fry ( str on -- quot ) split
[ unclip-last [ [ [ append ] [ prepend ] bi* ] reduce-r ] 2curry ]
[ length 1 - 1 <effect> [ call-effect ] 2curry ] bi ;
: gen-fry ( str on -- quot ) split
[ unclip-last [ [ [ 1array ] [ append ] [ prepend ] tri* ] reduce-r ] 2curry ]
[ length 1 - 1 <effect> [ call-effect ] 2curry ] bi ;
SYNTAX: i" parse-string rest "_" str-fry append! ;
SYNTAX: i{ \ } parse-until >array { _ } gen-fry append! ;
SYNTAX: iV{ \ } parse-until >vector V{ _ } gen-fry append! ;
]]
FILE: [[fries/summary.txt]] [[Generalized Frying]]
FILE: [[fries/authors.txt]] [[Sam Anklesaria
]]
FILE: [[easy-help/expand-markup/expand-markup.factor]] [[
USING: accessors arrays kernel lexer locals math namespaces parser
sequences splitting ;
IN: easy-help.expand-markup
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: scan-one-array ( string -- array rest )
string-lines
lexer-factory get call
[
[
\ } parse-until >array
lexer get line-text>>
lexer get column>> tail
]
with-lexer
]
with-scope ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: contains-markup? ( string -- ? ) "{ $" swap subseq? ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: expand-markup ( LINE -- lines )
LINE contains-markup?
[
[let | N [ "{ $" LINE start ] |
LINE N head
LINE N 2 + tail scan-one-array dup " " head? [ 1 tail ] [ ] if
[ 2array ] dip
expand-markup
append ]
]
[ LINE 1array ]
if ;
]]
FILE: [[easy-help/easy-help.factor]] [[
USING: arrays assocs compiler.units
grouping help help.markup help.topics kernel lexer multiline
namespaces parser sequences splitting words
easy-help.expand-markup ;
IN: easy-help
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: parse-text-block ( -- array )
".." parse-multiline-string
string-lines
1 tail
[ dup " " head? [ 4 tail ] [ ] if ] map
[ expand-markup ] map
concat
[ dup "" = [ drop { $nl } ] [ ] if ] map ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: Text: parse-text-block parsed ; parsing
: Block: scan-word 1array parse-text-block append parsed ; parsing
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: Notes: { $notes } parse-text-block append parsed ; parsing
: Description: { $description } parse-text-block append parsed ; parsing
: Contract: { $contract } parse-text-block append parsed ; parsing
: Checked-Example: { $example } parse-text-block append parsed ; parsing
: Class-Description:
{ $class-description } parse-text-block append parsed ; parsing
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: Code:
{ $code }
parse-text-block [ dup array? [ drop "" ] [ ] if ] map
append
parsed
; parsing
: Example:
{ $heading "Example" }
{ $code }
parse-text-block
[ dup array? [ drop "" ] [ ] if ] map ! Each item in $code must be a string
append
2array parsed ; parsing
: Introduction:
{ $heading "Introduction" }
parse-text-block
2array parsed ; parsing
: Summary:
{ $heading "Summary" }
parse-text-block
2array parsed ; parsing
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: Values:
".." parse-multiline-string
string-lines
1 tail
[ dup " " head? [ 4 tail ] [ ] if ] map
[ " " split1 [ " " first = ] trim-head 2array ] map
\ $values prefix
parsed
; parsing
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: Word:
scan current-vocab create dup old-definitions get
[ delete-at ] with each dup set-word
bootstrap-word dup set-word
dup >link save-location
\ ; parse-until >array swap set-word-help ; parsing
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: Heading: { $heading } ".." parse-multiline-string suffix parsed ; parsing
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: List:
{ $list }
".." parse-multiline-string
string-lines
1 tail
[ dup " " head? [ 4 tail ] [ ] if ] map
[ expand-markup ] map
append parsed
; parsing
]]
FILE: [[sandbox/summary.txt]] [[Basic sandboxing
]]
FILE: [[sandbox/sandbox.factor]] [[! Copyright (C) 2009 Maxim Savchenko.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences vectors assocs namespaces parser lexer vocabs
combinators.short-circuit vocabs.parser ;
IN: sandbox
SYMBOL: whitelist
: with-sandbox-vocabs ( quot -- )
"sandbox.syntax" load-vocab vocab-words 1vector
use [ auto-use? off call ] with-variable ; inline
: parse-sandbox ( lines assoc -- quot )
whitelist [ [ parse-lines ] with-sandbox-vocabs ] with-variable ;
: reveal-in ( name -- )
[ { [ search ] [ no-word ] } 1|| ] keep current-vocab vocab-words set-at ;
SYNTAX: REVEAL: scan reveal-in ;
SYNTAX: REVEALING: ";" parse-tokens [ reveal-in ] each ;
]]
FILE: [[sandbox/sandbox-tests.factor]] [[! Copyright (C) 2009 Maxim Savchenko
! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors continuations lexer vocabs vocabs.parser
combinators.short-circuit sandbox tools.test ;
IN: sandbox.tests
<< "sandbox.syntax" load-vocab drop >>
USE: sandbox.syntax.private
: run-script ( x lines -- y )
H{ { "kernel" "kernel" } { "math" "math" } { "sequences" "sequences" } }
parse-sandbox call( x -- x! ) ;
[ 120 ]
[
5
{
"! Simple factorial example"
"APPLYING: kernel math sequences ;"
"1 swap [ 1+ * ] each"
} run-script
] unit-test
[
5
{
"! Jailbreak attempt with USE:"
"USE: io"
"\"Hello world!\" print"
} run-script
]
[
{
[ lexer-error? ]
[ error>> condition? ]
[ error>> error>> no-word-error? ]
[ error>> error>> name>> "USE:" = ]
} 1&&
] must-fail-with
[
5
{
"! Jailbreak attempt with unauthorized APPLY:"
"APPLY: io"
"\"Hello world!\" print"
} run-script
]
[
{
[ lexer-error? ]
[ error>> sandbox-error? ]
[ error>> vocab>> "io" = ]
} 1&&
] must-fail-with
]]
FILE: [[sandbox/authors.txt]] [[Maxim Savchenko
]]
FILE: [[sandbox/syntax/syntax.factor]] [[! Copyright (C) 2009 Maxim Savchenko.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel sequences assocs namespaces lexer vocabs.parser sandbox ;
IN: sandbox.syntax
<PRIVATE
ERROR: sandbox-error vocab ;
: sandbox-use+ ( alias -- )
dup whitelist get at [ add-use ] [ sandbox-error ] ?if ;
PRIVATE>
SYNTAX: APPLY: scan sandbox-use+ ;
SYNTAX: APPLYING: ";" parse-tokens [ sandbox-use+ ] each ;
REVEALING:
! !
HEX: OCT: BIN: f t CHAR: "
[ { T{
] } ;
REVEAL: ;
]]
FILE: [[recipes/summary.txt]] [[Database backed recipe sharing]]
FILE: [[recipes/icons/submit.tiff]] base64[[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+v9FRUV6AAAABgAAAAAAAAAAAAAAAAAAAAAAAAAPwsLC///////a2tr/ycnJ/+Li4v/MzMz/ycnJ/8nJyf/e3dr/9eST//zbYf/5uin/65cD/6liFf+Thnr/sbGx/9ra2v//////RkZGeQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAD8HBwf//////6enp/+np6f/p6en/6enp/+np6f/q6eX/9+OH//3cYP/3pQf/5ZEC/6dPAP+jkYL/x8fH/9/f3//q6ur//////0ZGRnkAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAA/BwcH//////+no6P/p6Oj/6ejo/+no6P/p6OX/9uOO//3jaP/6wDD/6JMC/6tSAP+ZcE7/sbGx/93c3P/n5ub/6+rq//////9GRkZ5AAAABgAAAAAAAAAAAAAAAAAAAAAAAAAPwcHB///////o6Oj/6Ojo/+jo6P/q5dH/+eN7//3gYP/6wjX/4o4F/6NcHf+XgGz/qamp/9XV1f/n5+f/6Ojo/+rq6v//////RkZGeQAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAD8TExP//////5+fn/+fn5//n5+f/49K2/9y4dP/vtEH/85wD/6hgGf+UlJT/s7Oz/9XV1f/m5ub/5+fn/+fn5//p6en//////0ZGRnkAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAA+urq7z/////+7u7v/u7u7/7u7u/9zDof/hwo//yo4h/7xmBf+ZemD/tbW1/9nZ2f/r6+v/7u7u/+7u7v/u7u7/8PDw//////9JSUl7AAAABgAAAAAAAAAAAAAAAAAAAAAAAAAOl5eX4P/////////////////////ewJH/yo4h/8aDAv+rbCT/sbCv/+fn5//7+/v/////////////////////////////////Pj4+dAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAC0lJSWsLCwtUCQkJVQkJCVWKdVScaE8r2lQ4AqsyIgOUDAoFeggICGUJCQlWCQkJVQkJCVUJCQlVCQkJVQkJCVUKCgpUCQkJSwICAiYAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAHAAAACQAAAAgAAAAIAAAACAAAABIAAAAbAAAAEwAAAAwAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAYAAAADAAAAAQAAAAAAAAAA]]
FILE: [[recipes/icons/love.tiff]] base64[[TU0AKgAAACAAAALQAAAACgAAAtAAAAAKAAgACAAIAAgADwD+AAQAAAABAAAAAAEAAAQAAAABAAAAGQEBAAQAAAABAAAAGQECAAMAAAAEAAAAGAEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAA2gEVAAMAAAABAAQAAAEWAAQAAAABAAAAGQEXAAQAAAABAAAJxAEaAAUAAAABAAAACAEbAAUAAAABAAAAEAEcAAMAAAABAAEAAAEoAAMAAAABAAIAAAFSAAMAAAABAAEAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD//fYA//z0AP/89AD//PQA//z0AP/89AD+998A/vTTFP733wL/+/EA//z0AP/89AD//PQA//z0AP/89AD///0A////AP///wD///8A////AP///wD///8A////AP///wD///8A/fTSAP3xxwD98ccA/fHHAP3xxwD98ccA+c4+WPe/Avj4xRu7/euuDf7xxwD+8ccA/vHHAP7xxwD+8ccA//32AP///wD///8A////AP///wD///8A////AP///wD///8A////AP3z0QD98MYA/fDGAP3wxgD98MYA+tdrUfa7A/v2uwL/9rsC//fDIrv97LYH/vDFAP7wxQD+8MUA/vDFAP/99QD///8A////AP///wD///8A////AP///wD///8A////AP///wD98tEA/e/GAP3vxgD978YA+tZtV/W4Bvj1twT/9bcE//W3BP/1twT/98Emu/zprw3978UA/e/FAP3vxQD//PUA////AP///wD///8A////AP///wD///8A////AP///wD///8A/fHQAP3txAD97cUA+dFnV/SzBf30swX/9LMF//SzBf/0swX/9LMF//SzBf/2vSTC/Om3Cv3vyQD978kA//z2AP///wD///8A////AP///wD///8A////AP///wD///8A////AP3wzgD97MMA+dR3SPOwCPnzsAb/87AG//OwBv/zsAb/87AG//OwBv/zsAb/87AG//W7KrP86LYF/ezDAP/89QD///8A////AP///wD///8A////AP///wD///8A////AP///wD98dMA+teGOfOtCvTzrAf/86wH//OsB//zrAf/86wH//OsB//zrAf/86wH//OsB//zrAf/9bw3o/zqwAL//PYA////AP///wD///8A////AP///wD///8A////AP///wD///8A+96iKPKrD+3yqQj/8qkI//KpCP/yqQj/8qkI//KpCP/yqQj/8qkI//KpCP/yqQj/8qkI//KpCP/1vUKN/vrxAP///wD///8A////AP///wD///8A////AP///wD///8A////APW/UITxpgrs8aUJ7vGlCfHxpQn/8aUJ//GlCf/xpQn/8aUJ//GlCf/xpQn/8aYL+fGnDvDxpw3w8acM6P3z3hP///8A////AP///wD///8A////AP///wD///8A////AP///wD40IAA868oAPGjCgD0tj8l8KIJ//CiCv/wogr/8KIK//CiCv/wogr/8KIK//W9UXX74q4A++CrAPfIagD++OoA////AP///wD///8A////AP///wD///8A////AP///wD///8A+NCAAPOvKAD0uUkA9cBeFPCfCf/vngv/754L/++eC//vngv/754L/++eC//0t0pH98p3APvgqgD3yGoA/vjqAP///wD///8A////AP///wD///8A////AP///wD///8A////APjRgQD1vlkA9cBlAPW/ZALwnw3u75oN/++aDf/vmg3/75oN/++aDf/vmg3/87FDKPS3UAD1wGUA98VlAP746gD///8A////AP///wD///8A////AP///wD///8A////AP///wD41JYA9sZ6APbGegD2xnoA8qonsu6WDv/ulg7/7pYO/+6WDv/ulg7/7pYN//fIfiD40JEA+NCRAPjOiQD++OwA////AP///wD///8A////AP///wD///8A////AP///wD///8A+dWgAPfKiAD3yogA98qIAPOzUmTvnAr/7ZMP/+2TD//tkw//7ZMP/+2TDv/yr0wk87VZAPO1WQDztVkA/fPjAP///wD///8A////AP///wD///8A////AP///wD///8A////APjUoQD2yYkA9smJAPbJiQD1xYEN8KAN7uyPEP/sjxD/7I8Q/+yPEP/sjxD/8atLOfO2YgDztmIA87ZiAP3z5QD///8A////AP///wD///8A////AP///wD///8A////AP///wD52bAA99CcAPfQnAD30JwA99CcAPKyVHXvnQn/64sR/+uLEf/rixH/64sR//CkRFvztWUA87VlAPO1ZQD98+UA////AP///wD///8A////AP///wD///8A////AP///wD///8A+uTHAPnduQD53bkA+d25APnduQD527UF8aYmx+2TDf/qiBL/6ogS/+qIEv/unz+O9cGDAPXBgwD1wYMA/fXqAP///wD///8A////AP///wD///8A////AP///wD///8A////APzp1AD748kA++PJAPvjyQD748kA++PJAPfRpRnwnwzi7I0P/+qEE//qhBP/64wi1PXIkgD1yJIA9ciSAP327QD///8A////AP///wD///8A////AP///wD///8A////AP///wD86dMA++PIAPvjyAD748gA++PIAPvjyAD52bUA7ps/K/ChD+TulQz/6YET/+mBE//ztng/98ufAPTAjwD++fUA////AP///wD///8A////AP///wD///8A////AP///wD///8A/OnTAPvjyAD748gA++PIAPPbwQDSvacA0LWXAMiHQQDJkVgRx4IiiO6ZDPDsjw7/6ocl2/GvcCTzt4AAuLOvAO7u7gD///8A////AP///wD///8A////AP///wD///8A////APzp0wDx2sAANS0oBQMAAA0DAAARAwAAFAMAABYDAAAXAwAAGAMAABgeEAYkfUgOgM5+ENHqhRL1i00XdAMAAAXNzMwA////AP///wD///8A////AP///wD///8A////AP///wD++vYAzMfDAAMAAAwDAAAbAwAAIQMAACQDAAAmAwAAJwMAACgDAAAoAwAAJwMAACYDAAAkHxEGMBgMBScDAAALzczMAP///wD///8A////AP///wD///8A////AP///wD///8A////ANfW1gA1MzMANTMzAjUzMwM1MzMENTMzBTUzMwY1MzMGNTMzBjUzMwY1MzMFNTMzBDUzMwM1MzMCNTMzANfW1gD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A]]
FILE: [[recipes/icons/more.tiff]] base64[[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]]
FILE: [[recipes/icons/hate.tiff]] base64[[TU0AKgAAACAAAALQAAAACgAAAtAAAAAKAAgACAAIAAgADwD+AAQAAAABAAAAAAEAAAQAAAABAAAAGQEBAAQAAAABAAAAGQECAAMAAAAEAAAAGAEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAA2gEVAAMAAAABAAQAAAEWAAQAAAABAAAAGQEXAAQAAAABAAAJxAEaAAUAAAABAAAACAEbAAUAAAABAAAAEAEcAAMAAAABAAEAAAEoAAMAAAABAAIAAAFSAAMAAAABAAEAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD//fUA//zzAP/88wD//PMA//zzAP/88wD/++8A/vTaAP734AD+9t0A/vbcAP723AD+9tsA/vXVEv733Q7//vwA////AP///wD///8A////AP///wD///8A////AP///wD///8A/fHPAP3uwwD97sMA/e7DAP3uwwD97sMA/OiwAPjJQwD61WQA+dNYAPrSTQ75zDZu+MgsyffDFvT60ENv//vuAP///wD///8A////AP///wD///8A////AP///wD///8A////AP3xzwD97sMA/e7DAP3uwwD97sMA/e7DAPzosAD4yUMA+tViA/jLPXD4yTft98Mm//a/EOn61Vss+910AP/99QD///8A////AP///wD///8A////AP///wD///8A////AP///wD98c8A/e7DAP3uwwD97sMA/e7DAP3uwwD86LAA98U3JPjIPMz3wy3/9bgI//W3BP/51GdM/OKVAPvfggD//PQA////AP///wD///8A////AP///wD///8A////AP///wD///8A/fHQAP3uxAD97sQA/e7EAP3uxAD97sQA++OeGffFN+L1uRX/9LMF//SzBf/1uBXU+t2LAPrdiwD63YsA/vnsAP///wD///8A////AP///wD///8A////AP///wD///8A////AP3txQD86LYA/Oi2APzotgD86LYA/OexBffGRMf1uRz/87AG//OwBv/zsAb/9sA2jvrXfwD6138A+td/AP746gD///8A////AP///wD///8A////AP///wD///8A////AP///wD75KwA+t2XAPrdlwD63ZcA+t2XAPfJWXb2vS3/86wH//OsB//zrAf/86wH//a/PVv4y2AA+MtgAPjLYAD+9uUA////AP///wD///8A////AP///wD///8A////AP///wD///8A+t6eAPnWhgD51oYA+daGAPjTfQ31uy/u8qkJ//KpCP/yqQj/8qkI//KpCP/2v0Y598ddAPfHXQD3x10A/vbkAP///wD///8A////AP///wD///8A////AP///wD///8A////APrcnQD504UA+dOFAPnThQD2wVRk87Ig//GlCf/xpQn/8aUJ//GlCf/xpQn/9b1JJPbCVgD2wlYA9sJWAP714wD///8A////AP///wD///8A////AP///wD///8A////AP///wD41pQA98x4APfMeAD3zHgA9Lg7svCiC//wogr/8KIK//CiCv/wogr/8KEJ//jOfCD51Y8A+dWPAPjRiAD+9+wA////AP///wD///8A////AP///wD///8A////AP///wD///8A9siDAPXAZAD2xWsA9sVrAfGoHOvvngv/754L/++eC//vngv/754L/++eC//ztUMm9LpPAPW/XQD0vWcA/vbrAP///wD///8A////AP///wD///8A////AP///wD///8A////APbIggDwoi0A87RPAPS8XhLwnxP/75oN/++aDf/vmg3/75oN/++aDf/vmg3/87RLQ/bFcwD52aYA9L9sAP726wD///8A////AP///wD///8A////AP///wD///8A////AP///wD2yIMA76ErAO2UDgDyrEEm7pgQ/+6WDv/ulg7/7pYO/+6WDv/ulg7/7pYO//O1U3b63K4A+dqqAPS+bAD+9usA////AP///wD///8A////AP///wD///8A////AP///wD///8A8rFUhO2TEO3tkw/v7ZMP8u2TD//tkw//7ZMP/+2TD//tkw//7ZMP/+2TD//tkxD67ZMQ8e2TEPHtkxHp/fHfE////wD///8A////AP///wD///8A////AP///wD///8A////APjVpSjtkhft7I8Q/+yPEP/sjxD/7I8Q/+yPEP/sjxD/7I8Q/+yPEP/sjxD/7I8Q/+yPEP/sjxD/8apJjf758QD///8A////AP///wD///8A////AP///wD///8A////AP///wD869UA9siLOOuMFPTrixH/64sR/+uLEf/rixH/64sR/+uLEf/rixH/64sR/+uLEf/rixH/76I/o/vjxAL++/YA////AP///wD///8A////AP///wD///8A////AP///wD///8A/OnRAPvjxgD0v35H6okT+eqIEv/qiBL/6ogS/+qIEv/qiBL/6ogS/+qIEv/qiBL/7pk1s/reuwT748UA/vr1AP///wD///8A////AP///wD///8A////AP///wD///8A////APzp0gD748cA++PIAPK1b1fqhBP96oQT/+qEE//qhBP/6oQT/+qEE//qhBP/7ZQwwvnduwn75cwA++XMAP779wD///8A////AP///wD///8A////AP///wD///8A////AP///wD86dUA++PKAPvjygD748oA8a1laOmBFP7pgRT/6YEU/+mBFP/pgRT/64wp0PjVsBD748kA++PJAPvjyQD++vYA////AP///wD///8A////AP///wD///8A////AP///wD///8A/OnWAPvjzAD748wA2cWxANG9qgDOjExo6H0W++h9Ff/ofRX/2nwgxs+ujhPaxLAA++LKAPviygD74soA/vr2AP///wD///8A////AP///wD///8A////AP///wD///8A////AIR7dAINCQgLAwAADwMAABMDAAAVAwAAF2k5EGvleBb5vWUWxRwRCCMDAAAVAwAAEwMAAA8NCQgLemxhAv769wD///8A////AP///wD///8A////AP///wD///8A////AP///wA1MzMFAwAAFgMAAB4DAAAiAwAAJQMAACcDAAAnIBAFOQgDASgDAAAnAwAAJQMAACMDAAAfAwAAFw0JCAXd3NsA////AP///wD///8A////AP///wD///8A////AP///wD///8AXVxcADUzMwE1MzMCNTMzAzUzMwQ1MzMFNTMzBjUzMwY1MzMGNTMzBTUzMwQ1MzMDNTMzAjUzMwE1MzMA3d3dAP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A]]
FILE: [[recipes/icons/back.tiff]] base64[[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]]
FILE: [[recipes/authors.txt]] [[Sam Anklesaria
]]
FILE: [[recipes/recipes.factor]] [[USING: accessors arrays colors.constants combinators
db.sqlite db.tuples db.types kernel locals math
monads persistency sequences sequences.extras ui ui.gadgets.controls
ui.gadgets.layout models.combinators ui.gadgets.labels
ui.gadgets.scrollers ui.pens.solid io.files.temp ;
FROM: sets => prune ;
IN: recipes
STORED-TUPLE: recipe { title { VARCHAR 100 } } { votes INTEGER } { txt TEXT } { genre { VARCHAR 100 } } ;
: <recipe> ( title genre text -- recipe ) recipe new swap >>txt swap >>genre swap >>title 0 >>votes ;
"recipes.db" temp-file <sqlite-db> recipe define-db
: top-recipes ( offset search -- recipes ) <query> T{ recipe } rot >>title >>tuple
"votes" >>order 30 >>limit swap >>offset get-tuples ;
: top-genres ( -- genres ) f f top-recipes [ genre>> ] map prune 4 short head-slice ;
: interface ( -- book ) [
[
[ $ TOOLBAR $ ] <hbox> COLOR: AliceBlue <solid> >>interior ,
[ "Genres:" <label> , <spacer> $ ALL $ $ GENRES $ ] <hbox>
{ 5 0 } >>gap COLOR: gray <solid> >>interior ,
$ RECIPES $
] <vbox> ,
[
[ "Title:" <label> , $ TITLE $ "Genre:" <label> , $ GENRE $ ] <hbox> ,
$ BODY $
$ BUTTON $
] <vbox> ,
] <book*> { 350 245 } >>pref-dim ;
:: recipe-browser ( -- ) [ [
interface
<table*> :> tbl
"okay" <model-border-btn> BUTTON -> :> ok
IMG-MODEL-BTN: submit [ store-tuple ] >>value TOOLBAR -> :> submit
IMG-MODEL-BTN: love 1 >>value TOOLBAR ->
IMG-MODEL-BTN: hate -1 >>value -> 2array merge :> votes
IMG-MODEL-BTN: back -> [ -30 ] <$
IMG-MODEL-BTN: more -> [ 30 ] <$ 2array merge :> viewed
<spacer> <model-field*> ->% 1 :> search
submit ok [ [ drop ] ] <$ 2array merge [ drop ] >>value :> quot
viewed 0 [ + ] fold search ok t <basic> "all" <model-btn> ALL ->
tbl selection>> votes [ [ + ] curry change-votes modify-tuple ] 2$>
4array merge
[ drop [ f ] [ "%" dup surround <pattern> ] if-empty top-recipes ] 3fmap :> ups
ups [ top-genres [ <model-btn> GENRES -> ] map merge ] bind*
[ text>> T{ recipe } swap >>genre get-tuples ] fmap
tbl swap ups 2merge >>model
[ [ title>> ] [ genre>> ] bi 2array ] >>quot
{ "Title" "Genre" } >>column-titles dup <scroller> RECIPES ,% 1 actions>>
submit [ "" dup dup <recipe> ] <$ 2array merge
{ [ [ title>> ] fmap <model-field> TITLE ->% .5 ]
[ [ genre>> ] fmap <model-field> GENRE ->% .5 ]
[ [ txt>> ] fmap <model-editor> BODY ->% 1 ]
} cleave
[ <recipe> ] 3fmap
[ [ 1 ] <$ ]
[ quot ok updates #1 [ call( recipe -- ) 0 ] 2fmap ] bi
2merge 0 <basic> switch-models >>model
] with-interface "recipes" open-window ] with-ui ;
MAIN: recipe-browser
]]
FILE: [[L-system/models/abop-5-angular/abop-5-angular.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.abop-5-angular
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: abop-5-angular ( <L-system> -- <L-system> )
L-parser-dialect >>commands
"&(90)+(90)a" >>axiom
{
{ "a" "F[+(45)l][-(45)l]^;ca" }
{ "l" "j" }
{ "j" "h" }
{ "h" "s" }
{ "s" "d" }
{ "d" "x" }
{ "x" "a" }
{ "F" "'(1.17)F'(.855)" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system abop-5-angular "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/models/abop-1/abop-1.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.abop-1
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: abop-1 ( <L-system> -- <L-system> )
L-parser-dialect >>commands
"c(12)FFAL" >>axiom
{
{ "A" "F [ & '(.8) ! B L ] >(137) ' !(.9) A" }
{ "B" "F [ - '(.8) !(.9) $ C L ] ' !(.9) C" }
{ "C" "F [ + '(.8) !(.9) $ B L ] ' !(.9) B" }
{ "L" " ~ c(8) { +(30) f -(120) f -(120) f }" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system abop-1 "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/models/abop-6/abop-6.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.abop-6
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: abop-6 ( <L-system> -- <L-system> )
L-parser-dialect >>commands
[ 5 >>angle ] >>turtle-values
! "&(90)+(90)FFF[-(120)'(.6)x][-(60)'(.8)x][+(120)'(.6)x][+(60)'(.8)x]x"
"FFF[-(120)'(.6)x][-(60)'(.8)x][+(120)'(.6)x][+(60)'(.8)x]x"
>>axiom
{
{ "a" "F[cdx][cex]F!(.9)a" }
{ "x" "a" }
{ "d" "+d" }
{ "e" "-e" }
{ "F" "'(1.25)F'(.8)" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system abop-6 "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/models/abop-5/abop-5.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.abop-5
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: abop-5 ( <L-system> -- <L-system> )
L-parser-dialect >>commands
[ 5 >>angle ] >>turtle-values
"a" >>axiom
{
{ "a" "F[+(45)l][-(45)l]^;ca" }
{ "l" "j" }
{ "j" "h" }
{ "h" "s" }
{ "s" "d" }
{ "d" "x" }
{ "x" "a" }
{ "F" "'(1.17)F'(.855)" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system abop-5 "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/models/abop-2/abop-2.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.abop-2
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: abop-2 ( <L-system> -- <L-system> )
L-parser-dialect >>commands
[ 30 >>angle ] >>turtle-values
"c(12)FAL" >>axiom
{
{ "A" "F [&'(.7)!BL] >(137) [&'(.6)!BL] >(137) '(.9) !(.9) A" }
{ "B" "F [- '(.7) !(.9) $ C L] '(.9) !(.9) C" }
{ "C" "F [+ '(.7) !(.9) $ B L] '(.9) !(.9) B" }
{ "L" "~c(8){+f(.1)-f(.1)-f(.1)+|+f(.1)-f(.1)-f(.1)}" }
} >>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system abop-2 "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/models/tree-5/tree-5.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.tree-5
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: tree-5 ( <L-system> -- <L-system> )
L-parser-dialect >>commands
[ 5 >>angle ] >>turtle-values
"c(4)FFS" >>axiom
{
{ "S" "FFR>(60)R>(60)R>(60)R>(60)R>(60)R>(30)S" }
{ "R" "[Ba]" }
{ "a" "$tF[Cx]Fb" }
{ "b" "$tF[Dy]Fa" }
{ "B" "&B" }
{ "C" "+C" }
{ "D" "-D" }
{ "x" "a" }
{ "y" "b" }
{ "F" "'(1.25)F'(.8)" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system tree-5 "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/models/airhorse/airhorse.factor]] [=[
USING: accessors ui L-system ;
IN: L-system.models.airhorse
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: airhorse ( <L-system> -- <L-system> )
L-parser-dialect >>commands
[ 10 >>angle ] >>turtle-values
"C" >>axiom
{
{ "C" "LBW" }
{ "B" "[[''aH]|[g]]" }
{ "a" "Fs+;'a" }
{ "g" "Ft+;'g" }
{ "s" "[::cc!!!!&&[FFcccZ]^^^^FFcccZ]" }
{ "t" "[c!!!!&[FF]^^FF]" }
{ "L" "O" }
{ "O" "P" }
{ "P" "Q" }
{ "Q" "R" }
{ "R" "U" }
{ "U" "X" }
{ "X" "Y" }
{ "Y" "V" }
{ "V" "[cc!!!&(90)[Zp]|[Zp]]" }
{ "p" "h>(120)h>(120)h" }
{ "h" "[+(40)!F'''p]" }
{ "H" "[cccci[>(50)dcFFF][<(50)ecFFF]]" }
{ "d" "Z!&Z!&:'d" }
{ "e" "Z!^Z!^:'e" }
{ "i" "-:/i" }
{ "W" "[%[!!cb][<<<!!cb][>>>!!cb]]" }
{ "b" "Fl!+Fl+;'b" }
{ "l" "[-cc{--z++z++z--|--z++z++z}]" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system airhorse "L-system" open-window ] with-ui ;
MAIN: main
]=]
FILE: [[L-system/models/abop-3/abop-3.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.abop-3
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: abop-3 ( <L-system> -- <L-system> )
L-parser-dialect >>commands
[ 30 >>angle ] >>turtle-values
"c(12)FA" >>axiom
{
{ "A" "!(.9)t(.4)FB>(94)B>(132)B" }
{ "B" "[&t(.4)F$A]" }
{ "F" "'(1.25)F'(.8)" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system abop-3 "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/models/abop-4/abop-4.factor]] [[
USING: accessors ui L-system ;
IN: L-system.models.abop-4
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: abop-4 ( <L-system> -- <L-system> )
L-parser-dialect >>commands
[ 18 >>angle ] >>turtle-values
"c(12)&(20)N" >>axiom
{
{
"N"
"FII[&(60)rY]>(90)[&(45)'(0.8)rA]>(90)[&(60)rY]>(90)[&(45)'(0.8)rD]!FIK"
}
{ "Y" "[c(4){++l.--l.--l.++|++l.--l.--l.}]" }
{ "l" "g(.2)l" }
{ "K" "[!c(2)FF>w>(72)w>(72)w>(72)w>(72)w]" }
{ "w" "[c(2)^!F][c(5)&(72){-(54)f(3)+(54)f(3)|-(54)f(3)+(54)f(3)}]" }
{ "f" "_" }
{ "A" "B" }
{ "B" "C" }
{ "C" "D" }
{ "D" "E" }
{ "E" "G" }
{ "G" "H" }
{ "H" "N" }
{ "I" "FoO" }
{ "O" "FoP" }
{ "P" "FoQ" }
{ "Q" "FoR" }
{ "R" "FoS" }
{ "S" "FoT" }
{ "T" "FoU" }
{ "U" "FoV" }
{ "V" "FoW" }
{ "W" "FoX" }
{ "X" "_" }
{ "o" "$t(-0.03)" }
{ "r" "~(30)" }
}
>>rules ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: main ( -- ) [ L-system abop-4 "L-system" open-window ] with-ui ;
MAIN: main
]]
FILE: [[L-system/L-system.factor]] [[
USING: accessors arrays assocs calendar colors
combinators.short-circuit help.markup help.syntax kernel locals
math math.functions math.matrices math.order math.parser
math.trig math.vectors opengl opengl.demo-support opengl.gl
sbufs sequences strings threads ui.gadgets ui.gadgets.worlds
ui.gestures ui.render ui.tools.workspace ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
IN: L-system
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: <turtle> pos ori angle length thickness color vertices saved ;
DEFER: default-L-parser-values
: reset-turtle ( turtle -- turtle )
{ 0 0 0 } clone >>pos
3 identity-matrix >>ori
V{ } clone >>vertices
V{ } clone >>saved
default-L-parser-values ;
: turtle ( -- turtle ) <turtle> new reset-turtle ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: step-turtle ( TURTLE LENGTH -- turtle )
TURTLE
TURTLE pos>> TURTLE ori>> { 0 0 LENGTH } m.v v+
>>pos ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: Rx ( ANGLE -- Rx )
[let | ANGLE [ ANGLE deg>rad ] |
[let | A [ ANGLE cos ]
B [ ANGLE sin neg ]
C [ ANGLE sin ]
D [ ANGLE cos ] |
{ { 1 0 0 }
{ 0 A B }
{ 0 C D } }
] ] ;
:: Ry ( ANGLE -- Ry )
[let | ANGLE [ ANGLE deg>rad ] |
[let | A [ ANGLE cos ]
B [ ANGLE sin ]
C [ ANGLE sin neg ]
D [ ANGLE cos ] |
{ { A 0 B }
{ 0 1 0 }
{ C 0 D } }
] ] ;
:: Rz ( ANGLE -- Rz )
[let | ANGLE [ ANGLE deg>rad ] |
[let | A [ ANGLE cos ]
B [ ANGLE sin neg ]
C [ ANGLE sin ]
D [ ANGLE cos ] |
{ { A B 0 }
{ C D 0 }
{ 0 0 1 } }
] ] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: apply-rotation ( TURTLE ROTATION -- turtle )
TURTLE TURTLE ori>> ROTATION m. >>ori ;
: rotate-x ( turtle angle -- turtle ) Rx apply-rotation ;
: rotate-y ( turtle angle -- turtle ) Ry apply-rotation ;
: rotate-z ( turtle angle -- turtle ) Rz apply-rotation ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: pitch-up ( turtle angle -- turtle ) neg rotate-x ;
: pitch-down ( turtle angle -- turtle ) rotate-x ;
: turn-left ( turtle angle -- turtle ) rotate-y ;
: turn-right ( turtle angle -- turtle ) neg rotate-y ;
: roll-left ( turtle angle -- turtle ) neg rotate-z ;
: roll-right ( turtle angle -- turtle ) rotate-z ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: V ( -- V ) { 0 1 0 } ;
: X ( turtle -- 3array ) ori>> [ first ] map ;
: Y ( turtle -- 3array ) ori>> [ second ] map ;
: Z ( turtle -- 3array ) ori>> [ third ] map ;
: set-X ( turtle seq -- turtle ) over ori>> [ set-first ] 2each ;
: set-Y ( turtle seq -- turtle ) over ori>> [ set-second ] 2each ;
: set-Z ( turtle seq -- turtle ) over ori>> [ set-third ] 2each ;
:: roll-until-horizontal ( TURTLE -- turtle )
TURTLE
V TURTLE Z cross normalize set-X
TURTLE Z TURTLE X cross normalize set-Y ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: strafe-up ( TURTLE LENGTH -- turtle )
TURTLE 90 pitch-up LENGTH step-turtle 90 pitch-down ;
:: strafe-down ( TURTLE LENGTH -- turtle )
TURTLE 90 pitch-down LENGTH step-turtle 90 pitch-up ;
:: strafe-left ( TURTLE LENGTH -- turtle )
TURTLE 90 turn-left LENGTH step-turtle 90 turn-right ;
:: strafe-right ( TURTLE LENGTH -- turtle )
TURTLE 90 turn-right LENGTH step-turtle 90 turn-left ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: polygon ( vertices -- ) GL_POLYGON glBegin [ first3 glVertex3d ] each glEnd ;
: start-polygon ( turtle -- turtle ) dup vertices>> delete-all ;
: finish-polygon ( turtle -- turtle ) dup vertices>> polygon ;
: polygon-vertex ( turtle -- turtle ) dup [ pos>> ] [ vertices>> ] bi push ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: record-vertex ( turtle -- turtle ) dup pos>> first3 glVertex3d ;
: draw-forward ( turtle length -- turtle )
GL_LINES glBegin [ record-vertex ] dip step-turtle record-vertex glEnd ;
: move-forward ( turtle length -- turtle ) step-turtle polygon-vertex ;
: sneak-forward ( turtle length -- turtle ) step-turtle ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: scale-length ( turtle m -- turtle ) over length>> * >>length ;
: scale-angle ( turtle m -- turtle ) over angle>> * >>angle ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: set-thickness ( turtle i -- turtle ) dup glLineWidth >>thickness ;
: scale-thickness ( turtle m -- turtle )
over thickness>> * 0.5 max set-thickness ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: color-table ( -- colors )
{
T{ rgba f 0 0 0 1 } ! black
T{ rgba f 0.5 0.5 0.5 1 } ! grey
T{ rgba f 1 0 0 1 } ! red
T{ rgba f 1 1 0 1 } ! yellow
T{ rgba f 0 1 0 1 } ! green
T{ rgba f 0.25 0.88 0.82 1 } ! turquoise
T{ rgba f 0 0 1 1 } ! blue
T{ rgba f 0.63 0.13 0.94 1 } ! purple
T{ rgba f 0.00 0.50 0.00 1 } ! dark green
T{ rgba f 0.00 0.82 0.82 1 } ! dark turquoise
T{ rgba f 0.00 0.00 0.50 1 } ! dark blue
T{ rgba f 0.58 0.00 0.82 1 } ! dark purple
T{ rgba f 0.50 0.00 0.00 1 } ! dark red
T{ rgba f 0.25 0.25 0.25 1 } ! dark grey
T{ rgba f 0.75 0.75 0.75 1 } ! medium grey
T{ rgba f 1 1 1 1 } ! white
} ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! : material-color ( color -- )
! GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE rot gl-material ;
: material-color ( color -- )
GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE rot color>raw 4array gl-material ;
: set-color ( turtle i -- turtle )
dup color-table nth dup gl-color material-color >>color ;
: inc-color ( turtle -- turtle ) dup color>> 1 + set-color ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: save-turtle ( turtle -- turtle ) dup clone over saved>> push ;
: restore-turtle ( turtle -- turtle ) saved>> pop dup color>> set-color ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: default-L-parser-values ( turtle -- turtle )
1 >>length 45 >>angle 1 >>thickness 2 >>color ;
: L-parser-dialect ( -- commands )
{
{ "+" [ dup angle>> turn-left ] }
{ "-" [ dup angle>> turn-right ] }
{ "&" [ dup angle>> pitch-down ] }
{ "^" [ dup angle>> pitch-up ] }
{ "<" [ dup angle>> roll-left ] }
{ ">" [ dup angle>> roll-right ] }
{ "|" [ 180.0 rotate-y ] }
{ "%" [ 180.0 rotate-z ] }
{ "$" [ roll-until-horizontal ] }
{ "F" [ dup length>> draw-forward ] }
{ "Z" [ dup length>> 2 / draw-forward ] }
{ "f" [ dup length>> move-forward ] }
{ "z" [ dup length>> 2 / move-forward ] }
{ "g" [ dup length>> sneak-forward ] }
{ "." [ polygon-vertex ] }
{ "[" [ save-turtle ] }
{ "]" [ restore-turtle ] }
{ "{" [ start-polygon ] }
{ "}" [ finish-polygon ] }
{ "/" [ 1.1 scale-length ] } ! double quote command in lparser
{ "'" [ 0.9 scale-length ] }
{ ";" [ 1.1 scale-angle ] }
{ ":" [ 0.9 scale-angle ] }
{ "?" [ 1.4 scale-thickness ] }
{ "!" [ 0.7 scale-thickness ] }
{ "c" [ dup color>> 1 + color-table length mod set-color ] }
}
;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: <L-system> < gadget
camera display-list pedestal paused
turtle-values
commands axiom rules string ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: iterate-system ( GADGET -- ) GADGET pedestal>> 0.5 + GADGET pedestal<< ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: start-rotation-thread ( GADGET -- )
GADGET f >>paused drop
[
[
GADGET paused>>
[ f ]
[ GADGET iterate-system GADGET relayout-1 25 milliseconds sleep t ]
if
]
loop
]
in-thread ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: open-paren ( -- ch ) CHAR: ( ;
: close-paren ( -- ch ) CHAR: ) ;
: open-paren? ( obj -- ? ) open-paren = ;
: close-paren? ( obj -- ? ) close-paren = ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: read-instruction ( STRING -- next rest )
{ [ STRING length 1 > ] [ STRING second open-paren? ] } 0&&
[ STRING close-paren STRING index 1 + cut ]
[ STRING 1 cut ]
if ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: iterate-string-loop ( STRING RULES ACCUM -- )
STRING empty? not
[
STRING read-instruction
[let | REST [ ] NEXT [ ] |
NEXT 1 head RULES at NEXT or ACCUM push-all
REST RULES ACCUM iterate-string-loop ]
]
when ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: iterate-string ( STRING RULES -- string )
[let | ACCUM [ STRING length 10 * <sbuf> ] |
STRING RULES ACCUM iterate-string-loop
ACCUM >string ] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: interpret-string ( STRING COMMANDS -- )
STRING empty? not
[
STRING read-instruction
[let | REST [ ] NEXT [ ] |
[let | COMMAND [ NEXT 1 head COMMANDS at ] |
COMMAND
[
NEXT length 1 =
[ COMMAND call ]
[
NEXT 2 tail 1 head* string>number
COMMAND 1 tail*
call
]
if
]
when ]
REST COMMANDS interpret-string ]
]
when ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: iterate-L-system-string ( L-SYSTEM -- )
L-SYSTEM string>> L-SYSTEM axiom>> or
L-SYSTEM rules>>
iterate-string
L-SYSTEM string<< ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: do-camera-look-at ( CAMERA -- )
[let | EYE [ CAMERA pos>> ]
FOCUS [ CAMERA clone 1 step-turtle pos>> ]
UP [ CAMERA clone 90 pitch-up 1 step-turtle pos>> CAMERA pos>> v- ]
|
EYE FOCUS UP gl-look-at ] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: generate-display-list ( L-SYSTEM -- )
L-SYSTEM find-gl-context
L-SYSTEM display-list>> GL_COMPILE glNewList
turtle
L-SYSTEM turtle-values>> [ ] or call
L-SYSTEM string>> L-SYSTEM axiom>> or
L-SYSTEM commands>>
interpret-string
drop
glEndList ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
M:: <L-system> draw-gadget* ( L-SYSTEM -- )
black gl-clear
GL_FLAT glShadeModel
GL_PROJECTION glMatrixMode
glLoadIdentity
-1 1 -1 1 1.5 200 glFrustum
GL_MODELVIEW glMatrixMode
glLoadIdentity
L-SYSTEM camera>> do-camera-look-at
GL_FRONT_AND_BACK GL_LINE glPolygonMode
! draw axis
white gl-color GL_LINES glBegin { 0 0 0 } gl-vertex { 0 0 1 } gl-vertex glEnd
! rotate pedestal
L-SYSTEM pedestal>> 0 0 1 glRotated
L-SYSTEM display-list>> glCallList ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
M:: <L-system> graft* ( L-SYSTEM -- )
L-SYSTEM find-gl-context
1 glGenLists L-SYSTEM display-list<< ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
M:: <L-system> pref-dim* ( L-SYSTEM -- dim ) { 400 400 } ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
:: with-camera ( L-SYSTEM QUOT -- )
L-SYSTEM camera>> QUOT call drop
L-SYSTEM relayout-1 ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
<L-system>
H{
{ T{ key-down f f "LEFT" } [ [ 5 turn-left ] with-camera ] }
{ T{ key-down f f "RIGHT" } [ [ 5 turn-right ] with-camera ] }
{ T{ key-down f f "UP" } [ [ 5 pitch-down ] with-camera ] }
{ T{ key-down f f "DOWN" } [ [ 5 pitch-up ] with-camera ] }
{ T{ key-down f f "a" } [ [ 1 step-turtle ] with-camera ] }
{ T{ key-down f f "z" } [ [ -1 step-turtle ] with-camera ] }
{ T{ key-down f f "q" } [ [ 5 roll-left ] with-camera ] }
{ T{ key-down f f "w" } [ [ 5 roll-right ] with-camera ] }
{ T{ key-down f { A+ } "LEFT" } [ [ 1 strafe-left ] with-camera ] }
{ T{ key-down f { A+ } "RIGHT" } [ [ 1 strafe-right ] with-camera ] }
{ T{ key-down f { A+ } "UP" } [ [ 1 strafe-up ] with-camera ] }
{ T{ key-down f { A+ } "DOWN" } [ [ 1 strafe-down ] with-camera ] }
{ T{ key-down f f "r" } [ start-rotation-thread ] }
{
T{ key-down f f "x" }
[
dup iterate-L-system-string
dup generate-display-list
dup relayout-1
drop
]
}
{ T{ key-down f f "F1" } [ drop "L-system" help-window ] }
}
set-gestures
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: L-system ( -- L-system )
<L-system> new-gadget
0 >>pedestal
! turtle 45 turn-left 45 pitch-up 5 step-turtle 180 turn-left >>camera ;
turtle 90 pitch-down -5 step-turtle 2 strafe-up >>camera
dup start-rotation-thread
;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ARTICLE: "L-system" "L-system"
"Press 'x' to iterate the L-system." $nl
"Camera control:"
{ $table
{ "a" "Forward" }
{ "z" "Backward" }
{ "LEFT" "Turn left" }
{ "RIGHT" "Turn right" }
{ "UP" "Pitch down" }
{ "DOWN" "Pitch up" }
{ "q" "Roll left" }
{ "w" "Roll right" } } ;
ABOUT: "L-system"
]]
FILE: [[persistency/persistency.factor]] [[USING: accessors arrays byte-arrays calendar classes
classes.tuple classes.tuple.parser combinators db db.queries
db.tuples db.types kernel math nmake parser sequences strings
strings.parser unicode urls words ;
IN: persistency
TUPLE: persistent id ;
: add-types ( table -- table' ) [ dup array? [ [ first dup >upper ] [ second ] bi 3array ]
[ dup >upper FACTOR-BLOB 3array ] if
] map { "id" "ID" +db-assigned-id+ } prefix ;
: remove-types ( table -- table' ) [ dup array? [ first ] when ] map ;
SYNTAX: STORED-TUPLE: parse-tuple-definition [ drop persistent ] dip [ remove-types define-tuple-class ]
[ nip [ dup name>> >upper ] [ add-types ] bi* define-persistent ] 3bi ;
: define-db ( database class -- ) swap [ [ ensure-table ] with-db ] [ "database" set-word-prop ] 2bi ;
: query>tuple ( tuple/query -- tuple ) dup query? [ tuple>> ] when ;
: w/db ( query quot -- ) [ dup query>tuple class-of "database" word-prop ] dip with-db ; inline
: get-tuples ( query -- tuples ) [ select-tuples ] w/db ;
: get-tuple ( query -- tuple ) [ select-tuple ] w/db ;
: store-tuple ( tuple -- ) [ insert-tuple ] w/db ;
: modify-tuple ( tuple -- ) [ update-tuple ] w/db ;
: remove-tuples ( tuple -- ) [ delete-tuples ] w/db ;
TUPLE: pattern value ; C: <pattern> pattern
SYNTAX: %" parse-string <pattern> suffix! ;
M: pattern where value>> over column-name>> 0% " LIKE " 0% bind# ;
]]
FILE: [[persistency/authors.txt]] [[Sam Anklesaria
]]
FILE: [[cfdg/cfdg.factor]] [[
USING: kernel alien.c-types combinators namespaces make arrays
sequences splitting
math math.functions math.vectors math.trig
opengl.gl opengl.glu opengl ui ui.gadgets.slate
vars colors self self.slots
random-weighted colors.hsv cfdg.gl accessors
ui.gadgets.handler ui.gestures assocs ui.gadgets macros
specialized-arrays.double ;
QUALIFIED: syntax
IN: cfdg
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SELF-SLOTS: hsva
: clear-color ( color -- ) gl-clear-color GL_COLOR_BUFFER_BIT glClear ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! if (adjustment < 0)
! base + base * adjustment
! if (adjustment > 0)
! base + (1 - base) * adjustment
: adjust ( val num -- val ) dup 0 > [ 1 pick - * + ] [ dupd * + ] if ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: hue ( num -- ) hue-> + 360 mod ->hue ;
: saturation ( num -- ) saturation-> swap adjust ->saturation ;
: brightness ( num -- ) value-> swap adjust ->value ;
: alpha ( num -- ) alpha-> swap adjust ->alpha ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: h ( num -- ) hue ;
: sat ( num -- ) saturation ;
: b ( num -- ) brightness ;
: a ( num -- ) alpha ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VAR: color-stack
: init-color-stack ( -- ) V{ } clone >color-stack ;
: push-color ( -- ) self> color-stack> push self> clone >self ;
: pop-color ( -- ) color-stack> pop dup >self gl-color ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! : double-nth* ( c-array indices -- seq ) swap [ double-nth ] curry map ;
: double-nth* ( c-array indices -- seq )
swap byte-array>double-array [ nth ] curry map ;
: check-size ( modelview -- num ) { 0 1 4 5 } double-nth* [ abs ] map supremum ;
VAR: threshold
: iterate? ( -- ? ) get-modelview-matrix check-size threshold> > ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! cos 2a sin 2a 0 0
! sin 2a -cos 2a 0 0
! 0 0 1 0
! 0 0 0 1
! column major order
: gl-flip ( angle -- ) deg>rad dup dup dup
[ 2 * cos , 2 * sin , 0 , 0 ,
2 * sin , 2 * cos neg , 0 , 0 ,
0 , 0 , 1 , 0 ,
0 , 0 , 0 , 1 , ]
double-array{ } make underlying>> glMultMatrixd ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: circle ( -- )
self> gl-color
gluNewQuadric dup 0 0.5 20 10 gluDisk gluDeleteQuadric ;
: triangle ( -- )
self> gl-color
GL_POLYGON glBegin
0 0.577 glVertex2d
0.5 -0.289 glVertex2d
-0.5 -0.289 glVertex2d
glEnd ;
: square ( -- )
self> gl-color
GL_POLYGON glBegin
-0.5 0.5 glVertex2d
0.5 0.5 glVertex2d
0.5 -0.5 glVertex2d
-0.5 -0.5 glVertex2d
glEnd ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: size ( scale -- ) dup 1 glScaled ;
: size* ( scale-x scale-y -- ) 1 glScaled ;
: rotate ( angle -- ) 0 0 1 glRotated ;
: x ( x -- ) 0 0 glTranslated ;
: y ( y -- ) 0 swap 0 glTranslated ;
: flip ( angle -- ) gl-flip ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: s ( scale -- ) size ;
: s* ( scale-x scale-y -- ) size* ;
: r ( angle -- ) rotate ;
: f ( angle -- ) flip ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: do ( quot -- )
push-modelview-matrix
push-color
call
pop-modelview-matrix
pop-color ; inline
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: recursive ( quot -- ) iterate? swap when ; inline
: multi ( seq -- ) random-weighted* call ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: [rules] ( seq -- quot )
[ unclip swap [ [ do ] curry ] map concat 2array ] map
[ call-random-weighted ] swap prefix
[ when ] swap prefix
[ iterate? ] swap append ;
MACRO: rules ( seq -- quot ) [rules] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: [rule] ( seq -- quot )
[ [ do ] swap prefix ] map concat
[ when ] swap prefix
[ iterate? ] prepend ;
MACRO: rule ( seq -- quot ) [rule] ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VAR: background
: set-initial-background ( -- ) T{ hsva f 0 0 1 1 } clone >self ;
: set-background ( -- )
set-initial-background
background> call
self> clear-color ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
USING: rewrite-closures ;
VAR: viewport ! { left width bottom height }
VAR: start-shape
: set-initial-color ( -- ) T{ hsva f 0 0 0 1 } clone >self ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SYMBOL: dlist
! : build-model-dlist ( -- )
! 1 glGenLists dlist set
! dlist get GL_COMPILE_AND_EXECUTE glNewList
! start-shape> call
! glEndList ;
: build-model-dlist ( -- )
1 glGenLists dlist set
dlist get GL_COMPILE_AND_EXECUTE glNewList
set-initial-color
self> gl-color
start-shape> call
glEndList ;
: display ( -- )
GL_PROJECTION glMatrixMode
glLoadIdentity
viewport> first dup viewport> second +
viewport> third dup viewport> fourth + gluOrtho2D
GL_MODELVIEW glMatrixMode
glLoadIdentity
set-background
GL_COLOR_BUFFER_BIT glClear
init-modelview-matrix-stack
init-color-stack
dlist get not
[ build-model-dlist ]
[ dlist get glCallList ]
if ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: delete-dlist ( -- ) dlist get [ dlist get 1 glDeleteLists dlist off ] when ;
: cfdg-window* ( -- slate )
C[ display ] <slate>
{ 500 500 } >>pdim
C[ delete-dlist ] >>ungraft
dup "CFDG" open-window ;
: cfdg-window ( -- slate ) [ cfdg-window* ] with-ui ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SYMBOL: the-slate
: rebuild ( -- ) delete-dlist the-slate get relayout-1 ;
: <cfdg-gadget> ( -- slate )
C[ display ] <slate>
dup the-slate set
{ 500 500 } >>pdim
C[ dlist get [ dlist get 1 glDeleteLists ] when ] >>ungraft
<handler>
H{ } clone
T{ key-down f f "ENTER" } C[ drop rebuild ] swap pick set-at
T{ button-down } C[ drop rebuild ] swap pick set-at
>>table ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
USE: fry
: cfdg-window. ( quot -- )
'[ [ @ <cfdg-gadget> "CFDG" open-window ] with-scope ] with-ui ;
]]
FILE: [[cfdg/models/sierpinski/sierpinski.factor]] [[
USING: kernel namespaces math opengl.gl opengl.glu ui ui.gadgets.slate
random-weighted cfdg ;
IN: cfdg.models.sierpinski
: shape ( -- ) circle ;
! : sierpinski ( -- )
! iterate? [
! shape
! [ 0.6 s 5 r 0.2 b -1.5 y 0 x sierpinski ] do
! [ 0.6 s 5 r -0.2 b 0.75 y -1.2990375 x sierpinski ] do
! [ 0.6 s 5 r 0.75 y 1.2990375 x sierpinski ] do
! ] when ;
: sierpinski ( -- )
iterate? [
shape
[ -1.5 y 0 x 0.6 s 5 r 0.2 b sierpinski ] do
[ 0.75 y -1.2990375 x 0.6 s 5 r -0.2 b sierpinski ] do
[ 0.75 y 1.2990375 x 0.6 s 5 r sierpinski ] do
] when ;
: top ( -- ) [ -13.5 r 0.5 b sierpinski ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ ] >background
{ -4 8 -4 8 } >viewport
0.01 >threshold
[ top ] >start-shape ;
: run ( -- ) [ init ] cfdg-window. ;
MAIN: run
]]
FILE: [[cfdg/models/sierpinski/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/models/sierpinski/tags.txt]] [[demos
]]
FILE: [[cfdg/models/game1-turn6/game1-turn6.factor]] [[
USING: kernel namespaces math opengl.gl opengl.glu ui ui.gadgets.slate
random-weighted cfdg ;
IN: cfdg.models.game1-turn6
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: f-triangles ( -- )
{
[ 0.1 x 0.1 y -0.33 alpha 20 hue 0.7 sat 0.80 b triangle ]
[ 10 hue 0.9 sat 0.33 b triangle ]
[ 0.9 s 10 hue 0.5 sat 1.00 b triangle ]
[ 0.8 s 5 r f-triangles ]
}
rule ;
: f-squares ( -- )
{
[ 0.1 x 0.1 y -0.33 alpha 250 hue 0.70 sat 0.80 b square ]
[ 220 hue 0.90 sat 0.33 b square ]
[ 0.9 s 220 hue 0.25 sat 1.00 b square ]
[ 0.8 s 5 r f-squares ]
}
rule ;
DEFER: start
: spiral ( -- )
{
{ 1 [ f-squares ]
[ 0.5 x 0.5 y 45 r f-triangles ]
[ 1 y 25 r 0.9 s spiral ] }
{ 0.022 [ 90 flip 50 hue start ] }
}
rules ;
: start ( -- )
[ spiral ] do
[ 120 r spiral ] do
[ 240 r spiral ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ 66 hue 0.4 sat 0.5 b ] >background
{ -5 10 -5 10 } >viewport
0.001 >threshold
[ start ] >start-shape ;
: run ( -- ) [ init ] cfdg-window. ;
MAIN: run
]]
FILE: [[cfdg/models/game1-turn6/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/models/game1-turn6/tags.txt]] [[demos
]]
FILE: [[cfdg/models/aqua-star/aqua-star.factor]] [[
USING: kernel namespaces math random opengl.gl opengl.glu ui ui.gadgets.slate
random-weighted cfdg ;
IN: cfdg.models.aqua-star
: tentacle ( -- )
iterate? [
{ { 1 [ circle
[ .23 y .99 s .002 b tentacle ] do ] }
{ 1 [ circle
[ .17 y 2 r .99 s .002 b tentacle ] do ] }
{ 1 [ circle
[ .12 y -2 r .99 s .001 b tentacle ] do ] } }
call-random-weighted
] when ;
: anemone ( -- )
iterate? [
tentacle
[ 10 x -11 r .995 s -.002 b anemone ] do
] when ;
: anemone-begin ( -- ) [ 196 hue 0.8324 sat 1 b anemone ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ -1 b ] >background
{ -60 140 -120 140 } >viewport
0.1 >threshold
[ anemone-begin ] >start-shape ;
: run ( -- ) [ init ] cfdg-window. ;
MAIN: run
]]
FILE: [[cfdg/models/aqua-star/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/models/aqua-star/tags.txt]] [[demos
]]
FILE: [[cfdg/models/flower6/deploy.factor]] [[USING: tools.deploy.config ;
V{
{ deploy-ui? t }
{ deploy-io 1 }
{ deploy-reflection 2 }
{ deploy-compiler? t }
{ deploy-math? t }
{ deploy-word-props? f }
{ deploy-c-types? f }
{ "stop-after-last-window?" t }
{ "bundle-name" "cfdg.models.flower6.app" }
}
]]
FILE: [[cfdg/models/flower6/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/models/flower6/tags.txt]] [[demos
]]
FILE: [[cfdg/models/flower6/flower6.factor]] [[
USING: kernel namespaces sequences math
opengl.gl opengl.glu ui ui.gadgets.slate
random-weighted cfdg ;
IN: cfdg.models.flower6
: petal6 ( -- )
iterate? [
[ 1 0.001 s* square ] do
[ -0.5 x 0.01 s -1 b circle ] do
[ 0.5 x 120.21 r 0.996 s 0.5 x 0.005 b petal6 ] do
] when ;
: flower6 ( -- )
12 [ [ [ 30 r ] times petal6 ] do ] each
12 [ [ [ 30 r ] times 90 flip petal6 ] do ] each ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ ] >background
{ -1 2 -1 2 } >viewport
0.01 >threshold
[ flower6 ] >start-shape ;
: run ( -- ) [ init ] cfdg-window. ;
MAIN: run
]]
FILE: [[cfdg/models/snowflake/snowflake.factor]] [[
USING: kernel namespaces math opengl.gl opengl.glu ui ui.gadgets.slate
random-weighted cfdg ;
IN: cfdg.models.snowflake
: spike ( -- )
iterate? [
{ { 1 [ square
[ 0.95 y 0.97 s spike ] do ] }
{ 0.03 [ square
[ 60 r spike ] do
[ -60 r spike ] do
[ 0.95 y 0.97 s spike ] do ] } }
call-random-weighted
] when ;
: snowflake ( -- )
spike
[ 60 r spike ] do
[ 120 r spike ] do
[ 180 r spike ] do
[ 240 r spike ] do
[ 300 r spike ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ ] >background
{ -40 80 -40 80 } >viewport
0.1 >threshold
[ snowflake ] >start-shape ;
: run ( -- ) [ init ] cfdg-window. ;
MAIN: run
]]
FILE: [[cfdg/models/snowflake/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/models/snowflake/tags.txt]] [[demos
]]
FILE: [[cfdg/models/rules08/rules08.factor]] [[
USING: namespaces sequences math random-weighted cfdg ;
IN: cfdg.models.rules08
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: insct ( -- )
[ 1.5 5.5 size* -1 brightness triangle ] do
10
[ [ [ 1 0.9 size* -0.15 y 0.05 brightness ] times 1 5 size* triangle ] do ]
each ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
DEFER: line
: ligne ( -- )
{
{ 1 [ 4.5 y 1.15 0.8 size* -0.3 b line ] }
{ 0.5 [ ] }
}
rules ;
: line ( -- ) { [ insct ligne ] } rule ;
: sole ( -- )
{
{ 1 [ 1 brightness 0.5 saturation ligne ] [ 140 r 1 hue sole ] }
{ 0.01 [ ] }
}
rules ;
: centre ( -- ) { [ 1 b 5 s circle ] [ sole ] } rule ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ -1 b ] >background
{ -20 40 -20 40 } viewport set
[ centre ] >start-shape
0.0001 >threshold ;
: run ( -- ) [ init ] cfdg-window. ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
MAIN: run
]]
FILE: [[cfdg/models/rules08/tags.txt]] [[demos
]]
FILE: [[cfdg/models/spirales/spirales.factor]] [[
USING: namespaces sequences math random-weighted cfdg ;
IN: cfdg.models.spirales
DEFER: line
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: block ( -- ) { [ circle ] [ 0.3 s 60 flip line ] } rule ;
: a1 ( -- ) { [ 0.95 s 2 x 12 r 0.5 b 10 hue 1.5 sat a1 ] [ block ] } rule ;
: line ( -- ) -0.3 a { [ 0 r a1 ] [ 120 r a1 ] [ 240 r a1 ] } rule ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ -1 b ] >background
{ -20 40 -20 40 } >viewport
[ line ] >start-shape
0.04 >threshold ;
: run ( -- ) [ init ] cfdg-window. ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
MAIN: run
]]
FILE: [[cfdg/models/spirales/tags.txt]] [[demos
]]
FILE: [[cfdg/models/chiaroscuro/chiaroscuro.factor]] [[
USING: kernel namespaces sequences math
opengl.gl opengl.glu ui ui.gadgets.slate
random-weighted cfdg ;
IN: cfdg.models.chiaroscuro
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
DEFER: white
: black ( -- )
{
{ 60 [ 0.6 s circle ] [ 0.1 x 5 r 0.99 s -0.01 b -0.01 a black ] }
{ 1 [ white black ] }
}
rules ;
: white ( -- )
{
{ 60 [ 0.6 s circle ] [ 0.1 x -5 r 0.99 s 0.01 b -0.01 a white ] }
{ 1 [ black white ] }
}
rules ;
: chiaroscuro ( -- ) { [ 0.5 b black ] } rule ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ -0.5 b ] >background
{ -3 6 -2 6 } >viewport
0.03 >threshold
[ chiaroscuro ] >start-shape ;
: run ( -- ) [ init ] cfdg-window. ;
MAIN: run
]]
FILE: [[cfdg/models/chiaroscuro/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/models/chiaroscuro/tags.txt]] [[demos
]]
FILE: [[cfdg/models/lesson/lesson.factor]] [[
USING: kernel namespaces math opengl.gl opengl.glu ui ui.gadgets.slate
random-weighted cfdg ;
IN: cfdg.models.lesson
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: shapes ( -- )
[ square ] do
[ 0.3 b circle ] do
[ 0.5 b triangle ] do
[ 0.7 b 60 r triangle ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: chapter-1 ( -- )
[ 2 x 5 y 3 size square ] do
[ 6 x 5 y 3 size circle ] do
[ 4 x 2 y 3 size triangle ] do
[ 1 y 3 size shapes ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: foursquare ( -- )
[ 0 x 0 y 5 3 size* square ] do
[ 0 x 5 y 2 4 size* square ] do
[ 5 x 5 y 3 size square ] do
[ 5 x 0 y 2 size square ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: chapter-2 ( -- )
[ square ] do
[ 3 x 7 y square ] do
[ 5 x 7 y 30 r square ] do
[ 3 x 5 y 0.75 size square ] do
[ 5 x 5 y 0.5 b square ] do
[ 7 x 6 y 45 r 0.7 size 0.7 b square ] do
[ 5 x 1 y 10 r 0.2 size foursquare ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: spiral ( -- )
iterate? [
[ 0.5 size circle ] do
[ 0.2 y -3 r 0.995 size spiral ] do
] when ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: chapter-3 ( -- ) [ 0 x 3 y spiral ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
DEFER: tree
: branch-left ( -- )
{ { 1 [ 20 r tree ] }
{ 1 [ 30 r tree ] }
{ 1 [ 40 r tree ] }
{ 1 [ ] } } random-weighted* do ;
: branch-right ( -- )
{ { 1 [ -20 r tree ] }
{ 1 [ -30 r tree ] }
{ 1 [ -40 r tree ] }
{ 1 [ ] } } random-weighted* do ;
: branch ( -- ) branch-left branch-right ;
: tree ( -- )
iterate? [
{
{ 20 [ [ 0.25 size circle ] do
[ 0.1 y 0.97 size tree ] do ] }
{ 1.5 [ branch ] }
} random-weighted* do
] when ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: chapter-4 ( -- )
[ 1 x 0 y tree ] do
[ 6 x 0 y tree ] do
[ 1 x 4 y tree ] do
[ 6 x 4 y tree ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: toc ( -- )
[ 0 x 0 y chapter-1 ] do
[ 10 x 0 y chapter-2 ] do
[ 0 x -10 y chapter-3 ] do
[ 10 x -10 y chapter-4 ] do ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: init ( -- )
[ ] >background
{ -5 25 -15 25 } >viewport
0.03 >threshold
[ toc ] >start-shape ;
: run ( -- ) [ init ] cfdg-window. ;
MAIN: run
]]
FILE: [[cfdg/models/lesson/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/models/lesson/tags.txt]] [[demos
]]
FILE: [[cfdg/summary.txt]] [[Implementation of: http://contextfreeart.org
]]
FILE: [[cfdg/gl/gl.factor]] [[
USING: kernel alien.c-types namespaces sequences opengl.gl ;
IN: cfdg.gl
: get-modelview-matrix ( -- alien )
GL_MODELVIEW_MATRIX 16 "GLdouble" <c-array> tuck glGetDoublev ;
SYMBOL: modelview-matrix-stack
: init-modelview-matrix-stack ( -- ) V{ } clone modelview-matrix-stack set ;
: push-modelview-matrix ( -- )
get-modelview-matrix modelview-matrix-stack get push ;
: pop-modelview-matrix ( -- ) modelview-matrix-stack get pop glLoadMatrixd ;
]]
FILE: [[cfdg/gl/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[cfdg/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[golden-section/summary.txt]] [[Golden section demo
]]
FILE: [[golden-section/deploy.factor]] [[USING: tools.deploy.config ;
V{
{ deploy-ui? t }
{ deploy-io 1 }
{ deploy-reflection 1 }
{ deploy-compiler? t }
{ deploy-math? t }
{ deploy-word-props? f }
{ deploy-c-types? f }
{ "stop-after-last-window?" t }
{ deploy-name "Golden Section" }
}
]]
FILE: [[golden-section/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[golden-section/tags.txt]] [[demos
]]
FILE: [[golden-section/golden-section.factor]] [[
USING: kernel namespaces math math.constants math.functions math.order
arrays sequences
opengl opengl.gl opengl.glu ui ui.render ui.gadgets ui.gadgets.theme
ui.gadgets.cartesian colors accessors combinators.cleave
processing.shapes ;
IN: golden-section
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! omega(i) = 2*pi*i*(phi-1)
! x(i) = 0.5*i*cos(omega(i))
! y(i) = 0.5*i*sin(omega(i))
! radius(i) = 10*sin((pi*i)/720)
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: omega ( i -- omega ) phi 1- * 2 * pi * ;
: x ( i -- x ) [ omega cos ] [ 0.5 * ] bi * ;
: y ( i -- y ) [ omega sin ] [ 0.5 * ] bi * ;
: center ( i -- point ) { x y } 1arr ;
: radius ( i -- radius ) pi * 720 / sin 10 * ;
: color ( i -- i ) dup 360.0 / dup 0.25 1 rgba boa >fill-color ;
: line-width ( i -- i ) dup radius 0.5 * 1 max glLineWidth ;
: draw ( i -- ) [ center ] [ radius 1.5 * 2 * ] bi circle ;
: dot ( i -- ) color line-width draw ;
: golden-section ( -- ) 720 [ dot ] each ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: <golden-section> ( -- gadget )
<cartesian>
{ 600 600 } >>pdim
{ -400 400 } x-range
{ -400 400 } y-range
[ golden-section ] >>action ;
: golden-section-window ( -- )
[ <golden-section> "Golden Section" open-window ] with-ui ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
MAIN: golden-section-window
]]
FILE: [[db/mysql/ffi/ffi.factor]] [[! Copyright (C) 2007 Berlin Brown, 2008 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
! Adapted from mysql.h and mysql.c
! Tested with MySQL version - 5.0.24a
USING: alien alien.syntax combinators kernel system ;
IN: db.mysql.ffi
<< "mysql" {
{ [ os winnt? ] [ "libmySQL.dll" stdcall ] }
{ [ os macosx? ] [ "libmysqlclient.14.dylib" cdecl ] }
{ [ os unix? ] [ "libmysqlclient.so.14" cdecl ] }
} cond add-library >>
LIBRARY: mysql
FUNCTION: void* mysql_init ( void* mysql ) ;
FUNCTION: char* mysql_error ( void* mysql ) ;
FUNCTION: void* mysql_real_connect ( void* mysql, char* host, char* user, char* passwd, char* db, int port, char* unixsocket, long clientflag ) ;
FUNCTION: void mysql_close ( void* sock ) ;
FUNCTION: int mysql_query ( void* mysql, char* q ) ;
FUNCTION: void* mysql_use_result ( void* mysql ) ;
FUNCTION: void mysql_free_result ( void* result ) ;
FUNCTION: char** mysql_fetch_row ( void* result ) ;
FUNCTION: int mysql_num_fields ( void* result ) ;
FUNCTION: ulong mysql_affected_rows ( void* mysql ) ;
]]
FILE: [[db/mysql/lib/lib.factor]] [[! Copyright (C) 2007 Berlin Brown, 2008 Doug Coleman.
! See http://factorcode.org/license.txt for license.
! Adapted from mysql.h and mysql.c
! Tested with MySQL version - 5.0.24a
USING: kernel alien io prettyprint sequences
namespaces arrays math db.mysql.ffi system accessors ;
IN: db.mysql.lib
SYMBOL: my-conn
TUPLE: mysql-db handle host user password db port ;
TUPLE: mysql-statement ;
TUPLE: mysql-result-set ;
: new-mysql ( -- conn )
f mysql_init ;
: mysql-error ( mysql -- )
[ mysql_error throw ] when* ;
! : mysql-connect ( mysql-connection -- )
! new-mysql over set-mysql-db-handle
! dup {
! mysql-db-handle
! mysql-db-host
! mysql-db-user
! mysql-db-password
! mysql-db-db
! mysql-db-port
! } get-slots f 0 mysql_real_connect mysql-error ;
! =========================================================
! Low level mysql utility definitions
! =========================================================
: (mysql-query) ( mysql-connection query -- ret )
>r db-handle>> r> mysql_query ;
! : (mysql-result) ( mysql-connection -- ret )
! [ mysql-db-handle mysql_use_result ] keep
! [ set-mysql-connection-resulthandle ] keep ;
! : (mysql-affected-rows) ( mysql-connection -- n )
! mysql-connection-mysqlconn mysql_affected_rows ;
! : (mysql-free-result) ( mysql-connection -- )
! mysql-connection-resulthandle drop ;
! : (mysql-row) ( mysql-connection -- row )
! mysql-connection-resulthandle mysql_fetch_row ;
! : (mysql-num-cols) ( mysql-connection -- n )
! mysql-connection-resulthandle mysql_num_fields ;
! : mysql-char*-nth ( index object -- str )
! ! Utility based on 'char*-nth' to perform an additional sanity check on the value
! ! extracted from the array of strings.
! void*-nth [ alien>char-string ] [ "" ] if* ;
! : mysql-row>seq ( object n -- seq )
! [ swap mysql-char*-nth ] map-with ;
! : (mysql-result>seq) ( seq -- seq )
! my-conn get (mysql-row) dup [
! my-conn get (mysql-num-cols) mysql-row>seq
! over push
! (mysql-result>seq)
! ] [ drop ] if
! ! Perform needed cleanup on fetched results
! my-conn get (mysql-free-result) ;
! : mysql-query ( query -- ret )
! >r my-conn get r> (mysql-query) drop
! my-conn get (mysql-result) ;
! : mysql-command ( query -- n )
! mysql-query drop
! my-conn get (mysql-affected-rows) ;
]]
FILE: [[db/mysql/mysql.factor]] [[! Copyright (C) 2008 Doug Coleman.
! See http://factorcode.org/license.txt for license.
USING: alien continuations destructors io kernel prettyprint
sequences db db.mysql.ffi ;
IN: db.mysql
TUPLE: mysql-db handle host user password db port ;
TUPLE: mysql-statement ;
TUPLE: mysql-result-set ;
M: mysql-db db-open ( mysql-db -- )
;
M: mysql-db dispose ( mysql-db -- )
mysql-db-handle mysql_close ;
M: mysql-db <simple-statement> ( str in out -- statement )
3drop f ;
M: mysql-db <prepared-statement> ( str in out -- statement )
3drop f ;
M: mysql-statement prepare-statement ( statement -- )
drop ;
M: mysql-statement bind-statement* ( statement -- )
drop ;
M: mysql-statement query-results ( query -- result-set )
drop f ;
M: mysql-result-set #rows ( result-set -- n )
drop 0 ;
M: mysql-result-set #columns ( result-set -- n )
drop 0 ;
M: mysql-result-set row-column ( result-set n -- obj )
2drop f ;
M: mysql-result-set advance-row ( result-set -- )
drop ;
M: mysql-db begin-transaction ( -- )
;
M: mysql-db commit-transaction ( -- )
;
M: mysql-db rollback-transaction ( -- )
;
]]
FILE: [[springies/ui/ui.factor]] [[
USING: kernel namespaces threads sequences math math.vectors
opengl.gl opengl colors ui ui.gadgets ui.gadgets.slate
fry rewrite-closures vars springies accessors math.geometry.rect ;
IN: springies.ui
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: draw-node ( node -- ) pos>> { -5 -5 } v+ [ { 10 10 } gl-rect ] with-translation ;
: draw-spring ( spring -- )
[ node-a>> pos>> ] [ node-b>> pos>> ] bi gl-line ;
: draw-nodes ( -- ) nodes> [ draw-node ] each ;
: draw-springs ( -- ) springs> [ draw-spring ] each ;
: set-projection ( -- )
GL_PROJECTION glMatrixMode
glLoadIdentity
0 world-width 1- 0 world-height 1- -1 1 glOrtho
GL_MODELVIEW glMatrixMode
glLoadIdentity ;
! : display ( -- ) set-projection black gl-color draw-nodes draw-springs ;
: display ( -- ) set-projection black gl-color draw-nodes draw-springs ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VAR: slate
VAR: loop
: update-world-size ( -- ) slate> rect-dim >world-size ;
: refresh-slate ( -- ) slate> relayout-1 ;
DEFER: maybe-loop
: run ( -- )
update-world-size
iterate-system
refresh-slate
yield
maybe-loop ;
: maybe-loop ( -- ) loop> [ run ] when ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: springies-window* ( -- )
C[ display ] <slate>
{ 800 600 } >>pdim
C[ { 500 500 } >world-size loop on [ run ] in-thread ] >>graft
C[ loop off ] >>ungraft
[ >slate ] [ "Springies" open-window ] bi ;
: springies-window ( -- ) [ [ springies-window* ] with-scope ] with-ui ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: go* ( quot -- ) '[ [ springies-window* 1000 sleep @ ] with-scope ] with-ui ;
]]
FILE: [[springies/ui/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/belt-tire/belt-tire.factor]] [[
USING: kernel namespaces arrays sequences threads math ui random
springies springies.ui ;
IN: springies.models.belt-tire
: model ( -- )
{ } clone >nodes
{ } clone >springs
0.008 >time-slice
gravity on
1 274.078806900597328 346.307117178664043 0 0 1 0.5 mass
2 284.142891110742823 329.83402842231834 0 0 1 0.5 mass
3 295.307158356938658 355.695013578746227 0 0 1 0.5 mass
4 300.698527801927128 337.003548930923216 0 0 1 0.5 mass
5 318.093036910029696 359.203044347904552 0 0 1 0.5 mass
6 318.542098798246286 339.592403450546044 0 0 1 0.5 mass
7 340.949296214486822 356.831259237330983 0 0 1 0.5 mass
8 336.494524828869885 337.754019325244656 0 0 1 0.5 mass
9 362.534986907234952 348.770558940029559 0 0 1 0.5 mass
10 353.491265306914897 331.642140359094469 0 0 1 0.5 mass
11 381.368850422101502 335.37878701564847 0 0 1 0.5 mass
12 368.085531061140216 321.055018811315335 0 0 1 0.5 mass
13 396.117634938806759 317.519287773537314 0 0 1 0.5 mass
14 379.675208211408915 307.277961968837246 0 0 1 0.5 mass
15 405.655157991023771 296.391903048606025 0 0 1 0.5 mass
16 387.124676448692242 290.862310093183567 0 0 1 0.5 mass
17 409.337178964708642 273.594658653786666 0 0 1 0.5 mass
18 389.76569804010461 273.012494879567555 0 0 1 0.5 mass
19 407.11203230551871 250.712646124396059 0 0 1 0.5 mass
20 387.966228461346304 255.061007930370067 0 0 1 0.5 mass
21 399.188308328902735 229.098161823607285 0 0 1 0.5 mass
22 381.896222954111181 238.073977723246998 0 0 1 0.5 mass
23 385.883224011375262 210.148208473511374 0 0 1 0.5 mass
24 371.614761646970464 223.279700317395225 0 0 1 0.5 mass
25 367.955378160003875 195.334436550727929 0 0 1 0.5 mass
26 357.817091674528911 211.717360072075536 0 0 1 0.5 mass
27 346.743525482831387 185.884698478394085 0 0 1 0.5 mass
28 341.291169697238729 204.55711005838188 0 0 1 0.5 mass
29 323.935265230381788 182.330460182137188 0 0 1 0.5 mass
30 323.466187791799882 201.937076877994031 0 0 1 0.5 mass
31 301.04141769400843 184.703602685435726 0 0 1 0.5 mass
32 305.532794735419941 203.763859300438838 0 0 1 0.5 mass
33 279.442362700896183 192.851996602076866 0 0 1 0.5 mass
34 288.551113492738239 209.893932668644339 0 0 1 0.5 mass
35 260.65997798024199 206.334196608396638 0 0 1 0.5 mass
36 273.960657978745814 220.516324161880476 0 0 1 0.5 mass
37 246.029909853431349 224.197583023911335 0 0 1 0.5 mass
38 262.719165304227545 234.58428660123181 0 0 1 0.5 mass
39 236.458142984593252 245.235572499606377 0 0 1 0.5 mass
40 254.870454491934908 250.81914136861181 0 0 1 0.5 mass
41 232.703447579492519 268.042376651164432 0 0 1 0.5 mass
42 252.226120754560156 268.679895159358864 0 0 1 0.5 mass
43 234.96767702938331 291.007702051922024 0 0 1 0.5 mass
44 254.040589506795527 286.621843971355872 0 0 1 0.5 mass
45 242.759412026738119 312.577114225657738 0 0 1 0.5 mass
46 260.111088599530603 303.593264087352964 0 0 1 0.5 mass
47 256.101782779606651 331.52509923420655 0 0 1 0.5 mass
48 270.373388641766439 318.366074596339615 0 0 1 0.5 mass
49 320.448537383965288 270.292364746678743 0 0 10 0.5 mass
1 1 4 200 2 28.284271247461902 spng
2 4 5 200 2 28.284271247461902 spng
3 5 8 200 2 28.284271247461902 spng
4 8 9 200 2 28.284271247461902 spng
5 9 12 200 2 28.284271247461902 spng
6 12 13 200 2 28.284271247461902 spng
7 13 16 200 2 28.284271247461902 spng
8 16 17 200 2 28.284271247461902 spng
9 17 20 200 2 28.284271247461902 spng
10 20 21 200 2 28.284271247461902 spng
11 21 24 200 2 28.284271247461902 spng
12 24 25 200 2 28.284271247461902 spng
13 25 28 200 2 28.284271247461902 spng
14 28 29 200 2 28.284271247461902 spng
15 29 32 200 2 28.284271247461902 spng
16 32 33 200 2 28.284271247461902 spng
17 33 36 200 2 28.284271247461902 spng
18 36 37 200 2 28.284271247461902 spng
19 37 40 200 2 28.284271247461902 spng
20 40 41 200 2 28.284271247461902 spng
21 41 44 200 2 28.284271247461902 spng
22 44 45 200 2 28.284271247461902 spng
23 45 48 200 2 28.284271247461902 spng
24 3 6 200 2 28.284271247461902 spng
25 7 10 200 2 28.284271247461902 spng
26 11 14 200 2 28.284271247461902 spng
27 15 18 200 2 28.284271247461902 spng
28 19 22 200 2 28.284271247461902 spng
29 23 26 200 2 28.284271247461902 spng
30 27 30 200 2 28.284271247461902 spng
31 31 34 200 2 28.284271247461902 spng
32 35 38 200 2 28.284271247461902 spng
33 39 44 200 2 44.7213595499957961 spng
34 39 42 200 2 28.284271247461902 spng
35 43 46 200 2 28.284271247461902 spng
36 47 46 200 2 28.284271247461902 spng
37 43 42 200 2 28.284271247461902 spng
38 39 38 200 2 28.284271247461902 spng
39 35 34 200 2 28.284271247461902 spng
40 2 3 200 2 28.284271247461902 spng
41 6 7 200 2 28.284271247461902 spng
42 10 11 200 2 28.284271247461902 spng
43 14 15 200 2 28.284271247461902 spng
44 18 19 200 2 28.284271247461902 spng
45 22 23 200 2 28.284271247461902 spng
46 26 27 200 2 28.284271247461902 spng
47 30 31 200 2 28.284271247461902 spng
48 1 6 200 2 44.7213595499957961 spng
49 3 8 200 2 44.7213595499957961 spng
50 5 10 200 2 44.7213595499957961 spng
51 7 12 200 2 44.7213595499957961 spng
52 9 14 200 2 44.7213595499957961 spng
53 11 16 200 2 44.7213595499957961 spng
54 13 18 200 2 44.7213595499957961 spng
55 15 20 200 2 44.7213595499957961 spng
56 17 22 200 2 44.7213595499957961 spng
57 19 24 200 2 44.7213595499957961 spng
58 21 26 200 2 44.7213595499957961 spng
59 23 28 200 2 44.7213595499957961 spng
60 25 30 200 2 44.7213595499957961 spng
61 27 32 200 2 44.7213595499957961 spng
62 29 34 200 2 44.7213595499957961 spng
63 31 36 200 2 44.7213595499957961 spng
64 33 38 200 2 44.7213595499957961 spng
65 35 40 200 2 44.7213595499957961 spng
66 37 42 200 2 44.7213595499957961 spng
67 41 46 200 2 44.7213595499957961 spng
68 43 48 200 2 44.7213595499957961 spng
69 2 5 200 2 44.7213595499957961 spng
70 4 7 200 2 44.7213595499957961 spng
71 6 9 200 2 44.7213595499957961 spng
72 8 11 200 2 44.7213595499957961 spng
73 10 13 200 2 44.7213595499957961 spng
74 12 15 200 2 44.7213595499957961 spng
75 14 17 200 2 44.7213595499957961 spng
76 16 19 200 2 44.7213595499957961 spng
77 18 21 200 2 44.7213595499957961 spng
78 20 23 200 2 44.7213595499957961 spng
79 22 25 200 2 44.7213595499957961 spng
80 24 27 200 2 44.7213595499957961 spng
81 26 29 200 2 44.7213595499957961 spng
82 28 31 200 2 44.7213595499957961 spng
83 30 33 200 2 44.7213595499957961 spng
84 32 35 200 2 44.7213595499957961 spng
85 34 37 200 2 44.7213595499957961 spng
86 36 39 200 2 44.7213595499957961 spng
87 38 41 200 2 44.7213595499957961 spng
88 40 43 200 2 44.7213595499957961 spng
89 42 45 200 2 44.7213595499957961 spng
90 44 47 200 2 44.7213595499957961 spng
91 1 8 200 2 63.2455532033675851 spng
92 3 10 200 2 63.2455532033675851 spng
93 5 12 200 2 63.2455532033675851 spng
94 7 14 200 2 63.2455532033675851 spng
95 9 16 200 2 63.2455532033675851 spng
96 11 18 200 2 63.2455532033675851 spng
97 13 20 200 2 63.2455532033675851 spng
98 15 22 200 2 63.2455532033675851 spng
99 17 24 200 2 63.2455532033675851 spng
100 19 26 200 2 63.2455532033675851 spng
101 21 28 200 2 63.2455532033675851 spng
102 23 30 200 2 63.2455532033675851 spng
103 25 32 200 2 63.2455532033675851 spng
104 27 34 200 2 63.2455532033675851 spng
105 29 36 200 2 63.2455532033675851 spng
106 31 38 200 2 63.2455532033675851 spng
107 33 40 200 2 63.2455532033675851 spng
108 35 42 200 2 63.2455532033675851 spng
109 37 44 200 2 63.2455532033675851 spng
110 39 46 200 2 63.2455532033675851 spng
111 48 41 200 2 63.2455532033675851 spng
112 2 7 200 2 63.2455532033675851 spng
113 4 9 200 2 63.2455532033675851 spng
114 6 11 200 2 63.2455532033675851 spng
115 8 13 200 2 63.2455532033675851 spng
116 10 15 200 2 63.2455532033675851 spng
117 12 17 200 2 63.2455532033675851 spng
118 14 19 200 2 63.2455532033675851 spng
119 16 21 200 2 63.2455532033675851 spng
120 18 23 200 2 63.2455532033675851 spng
121 20 25 200 2 63.2455532033675851 spng
122 22 27 200 2 63.2455532033675851 spng
123 24 29 200 2 63.2455532033675851 spng
124 26 31 200 2 63.2455532033675851 spng
125 28 33 200 2 63.2455532033675851 spng
126 30 35 200 2 63.2455532033675851 spng
127 32 37 200 2 63.2455532033675851 spng
128 34 39 200 2 63.2455532033675851 spng
129 36 41 200 2 63.2455532033675851 spng
130 38 43 200 2 63.2455532033675851 spng
131 40 45 200 2 63.2455532033675851 spng
132 42 47 200 2 63.2455532033675851 spng
133 1 3 200 2 20 spng
134 3 5 200 2 20 spng
135 5 7 200 2 20 spng
136 7 9 200 2 20 spng
137 9 11 200 2 20 spng
138 11 13 200 2 20 spng
139 13 15 200 2 20 spng
140 15 17 200 2 20 spng
141 17 19 200 2 20 spng
142 19 21 200 2 20 spng
143 21 23 200 2 20 spng
144 23 25 200 2 20 spng
145 25 27 200 2 20 spng
146 27 29 200 2 20 spng
147 29 31 200 2 20 spng
148 31 33 200 2 20 spng
149 33 35 200 2 20 spng
150 35 37 200 2 20 spng
151 37 39 200 2 20 spng
152 39 41 200 2 20 spng
153 41 43 200 2 20 spng
154 43 45 200 2 20 spng
155 45 47 200 2 20 spng
156 2 4 200 2 20 spng
157 4 6 200 2 20 spng
158 6 8 200 2 20 spng
159 8 10 200 2 20 spng
160 10 12 200 2 20 spng
161 12 14 200 2 20 spng
162 14 16 200 2 20 spng
163 16 18 200 2 20 spng
164 18 20 200 2 20 spng
165 20 22 200 2 20 spng
166 22 24 200 2 20 spng
167 24 26 200 2 20 spng
168 26 28 200 2 20 spng
169 28 30 200 2 20 spng
170 30 32 200 2 20 spng
171 32 34 200 2 20 spng
172 34 36 200 2 20 spng
173 36 38 200 2 20 spng
174 38 40 200 2 20 spng
175 40 42 200 2 20 spng
176 42 44 200 2 20 spng
177 44 46 200 2 20 spng
178 46 48 200 2 20 spng
179 1 2 200 2 20 spng
180 3 4 200 2 20 spng
181 5 6 200 2 20 spng
182 7 8 200 2 20 spng
183 9 10 200 2 20 spng
184 11 12 200 2 20 spng
185 13 14 200 2 20 spng
186 15 16 200 2 20 spng
187 17 18 200 2 20 spng
188 19 20 200 2 20 spng
189 21 22 200 2 20 spng
190 23 24 200 2 20 spng
191 25 26 200 2 20 spng
192 27 28 200 2 20 spng
193 29 30 200 2 20 spng
194 31 32 200 2 20 spng
195 33 34 200 2 20 spng
196 35 36 200 2 20 spng
197 37 38 200 2 20 spng
198 39 40 200 2 20 spng
199 41 42 200 2 20 spng
200 43 44 200 2 20 spng
201 45 46 200 2 20 spng
202 47 48 200 2 20 spng
203 47 2 200 2 28.284271247461902 spng
204 1 48 200 2 28.284271247461902 spng
205 1 46 200 2 44.7213595499957961 spng
206 1 44 200 2 63.2455532033675851 spng
207 47 4 200 2 44.7213595499957961 spng
208 48 3 200 2 44.7213595499957961 spng
209 47 6 200 2 63.2455532033675851 spng
210 48 5 200 2 63.2455532033675851 spng
211 46 3 200 2 63.2455532033675851 spng
212 45 4 200 2 63.2455532033675851 spng
213 47 1 200 2 20 spng
214 48 2 200 2 20 spng
215 18 49 300 3 69.2603782836911677 spng
216 49 20 300 3 69.050706006528273 spng
217 22 49 300 3 69.3541635375988079 spng
218 49 24 300 3 69.5269731830747872 spng
219 26 49 300 3 69.6347614342147381 spng
220 49 28 300 3 68.9492567037527948 spng
221 30 49 300 3 68.2641926635040477 spng
222 49 32 300 3 68.0661443009665419 spng
223 34 49 300 3 68.4470598345904051 spng
224 49 36 300 3 68.1175454637056106 spng
225 38 49 300 3 67.6756972627545252 spng
226 49 40 300 3 68.6221538571910514 spng
227 42 49 300 3 68.1835757349231386 spng
228 49 44 300 3 68.249542123006222 spng
229 46 49 300 3 68.8767014308902503 spng
230 49 48 300 3 69.4262198308391305 spng
231 2 49 300 3 69.8927750200262068 spng
232 49 4 300 3 69.5701085237043486 spng
233 6 49 300 3 69.1809222257119103 spng
234 8 49 300 3 69.2314957226839027 spng
235 49 10 300 3 69.7782200976780445 spng
236 12 49 300 3 69.5269731830747872 spng
237 49 14 300 3 69.8927750200262068 spng
238 16 49 300 3 69.8927750200262068 spng
nodes> 200 random -100 + 100 2array [ swap set-node-vel ] curry each ;
: go ( -- ) [ model ] go* ;
MAIN: go
]]
FILE: [[springies/models/belt-tire/deploy.factor]] [[USING: tools.deploy.config ;
V{
{ deploy-ui? t }
{ deploy-io 2 }
{ deploy-reflection 1 }
{ deploy-compiler? t }
{ deploy-math? t }
{ deploy-word-props? f }
{ deploy-word-defs? f }
{ deploy-c-types? f }
{ "stop-after-last-window?" t }
{ "bundle-name" "Belt Tire.app" }
}
]]
FILE: [[springies/models/belt-tire/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/belt-tire/tags.txt]] [[demos
]]
FILE: [[springies/models/2x2snake/deploy.factor]] [[USING: tools.deploy.config ;
H{
{ deploy-compiler? t }
{ deploy-word-props? f }
{ deploy-ui? t }
{ deploy-reflection 1 }
{ deploy-name "springies.models.2x2snake" }
{ deploy-c-types? f }
{ deploy-word-defs? f }
{ "stop-after-last-window?" t }
{ deploy-math? t }
{ deploy-io 1 }
}
]]
FILE: [[springies/models/2x2snake/2x2snake.factor]] [[
USING: kernel namespaces arrays sequences threads math math.vectors
ui random springies springies.ui ;
IN: springies.models.2x2snake
: model ( -- )
{ } clone >nodes
{ } clone >springs
0.002 >time-slice
gravity off
1 147.0 324.0 0.0 0.0 1.0 1.0 mass
2 164.0 324.0 0.0 0.0 1.0 1.0 mass
3 182.0 324.0 0.0 0.0 1.0 1.0 mass
4 200.0 324.0 0.0 0.0 1.0 1.0 mass
5 218.0 324.0 0.0 0.0 1.0 1.0 mass
6 236.0 324.0 0.0 0.0 1.0 1.0 mass
7 254.0 324.0 0.0 0.0 1.0 1.0 mass
8 272.0 324.0 0.0 0.0 1.0 1.0 mass
9 290.0 324.0 0.0 0.0 1.0 1.0 mass
10 308.0 324.0 0.0 0.0 1.0 1.0 mass
11 326.0 324.0 0.0 0.0 1.0 1.0 mass
12 344.0 324.0 0.0 0.0 1.0 1.0 mass
13 362.0 324.0 0.0 0.0 1.0 1.0 mass
14 380.0 324.0 0.0 0.0 1.0 1.0 mass
15 398.0 324.0 0.0 0.0 1.0 1.0 mass
16 416.0 324.0 0.0 0.0 1.0 1.0 mass
17 434.0 324.0 0.0 0.0 1.0 1.0 mass
18 452.0 324.0 0.0 0.0 1.0 1.0 mass
19 470.0 324.0 0.0 0.0 1.0 1.0 mass
20 147.0 298.0 0.0 0.0 1.0 1.0 mass
21 164.0 298.0 0.0 0.0 1.0 1.0 mass
22 182.0 298.0 0.0 0.0 1.0 1.0 mass
23 200.0 298.0 0.0 0.0 1.0 1.0 mass
24 218.0 298.0 0.0 0.0 1.0 1.0 mass
25 236.0 298.0 0.0 0.0 1.0 1.0 mass
26 254.0 298.0 0.0 0.0 1.0 1.0 mass
27 272.0 298.0 0.0 0.0 1.0 1.0 mass
28 290.0 298.0 0.0 0.0 1.0 1.0 mass
29 308.0 298.0 0.0 0.0 1.0 1.0 mass
30 326.0 298.0 0.0 0.0 1.0 1.0 mass
31 344.0 298.0 0.0 0.0 1.0 1.0 mass
32 362.0 298.0 0.0 0.0 1.0 1.0 mass
33 380.0 298.0 0.0 0.0 1.0 1.0 mass
34 398.0 298.0 0.0 0.0 1.0 1.0 mass
35 416.0 298.0 0.0 0.0 1.0 1.0 mass
36 434.0 298.0 0.0 0.0 1.0 1.0 mass
37 452.0 298.0 0.0 0.0 1.0 1.0 mass
38 470.0 298.0 0.0 0.0 1.0 1.0 mass
1 1 2 200.0 1.500000 18.0 spng
2 3 2 200.0 1.500000 18.0 spng
3 3 4 200.0 1.500000 18.0 spng
4 4 5 200.0 1.500000 18.0 spng
5 5 6 200.0 1.500000 18.0 spng
6 6 7 200.0 1.500000 18.0 spng
7 7 8 200.0 1.500000 18.0 spng
8 8 9 200.0 1.500000 18.0 spng
9 9 10 200.0 1.500000 18.0 spng
10 10 11 200.0 1.500000 18.0 spng
11 11 12 200.0 1.500000 18.0 spng
12 12 13 200.0 1.500000 18.0 spng
13 13 14 200.0 1.500000 18.0 spng
14 14 15 200.0 1.500000 18.0 spng
15 15 16 200.0 1.500000 18.0 spng
16 16 17 200.0 1.500000 18.0 spng
17 17 18 200.0 1.500000 18.0 spng
18 18 19 200.0 1.500000 18.0 spng
19 1 3 200.0 1.500000 36.0 spng
20 2 4 200.0 1.500000 36.0 spng
21 3 5 200.0 1.500000 36.0 spng
22 4 6 200.0 1.500000 36.0 spng
23 5 7 200.0 1.500000 36.0 spng
24 6 8 200.0 1.500000 36.0 spng
25 7 9 200.0 1.500000 36.0 spng
26 8 10 200.0 1.500000 36.0 spng
27 9 11 200.0 1.500000 36.0 spng
28 10 12 200.0 1.500000 36.0 spng
29 11 13 200.0 1.500000 36.0 spng
30 12 14 200.0 1.500000 36.0 spng
31 13 15 200.0 1.500000 36.0 spng
32 14 16 200.0 1.500000 36.0 spng
33 15 17 200.0 1.500000 36.0 spng
34 16 18 200.0 1.500000 36.0 spng
35 17 19 200.0 1.500000 36.0 spng
36 20 21 200.0 1.500000 18.0 spng
37 22 21 200.0 1.500000 18.0 spng
38 22 23 200.0 1.500000 18.0 spng
39 23 24 200.0 1.500000 18.0 spng
40 24 25 200.0 1.500000 18.0 spng
41 25 26 200.0 1.500000 18.0 spng
42 26 27 200.0 1.500000 18.0 spng
43 27 28 200.0 1.500000 18.0 spng
44 28 29 200.0 1.500000 18.0 spng
45 29 30 200.0 1.500000 18.0 spng
46 30 31 200.0 1.500000 18.0 spng
47 31 32 200.0 1.500000 18.0 spng
48 32 33 200.0 1.500000 18.0 spng
49 33 34 200.0 1.500000 18.0 spng
50 34 35 200.0 1.500000 18.0 spng
51 35 36 200.0 1.500000 18.0 spng
52 36 37 200.0 1.500000 18.0 spng
53 37 38 200.0 1.500000 18.0 spng
54 20 22 200.0 1.500000 36.0 spng
55 21 23 200.0 1.500000 36.0 spng
56 22 24 200.0 1.500000 36.0 spng
57 23 25 200.0 1.500000 36.0 spng
58 24 26 200.0 1.500000 36.0 spng
59 25 27 200.0 1.500000 36.0 spng
60 26 28 200.0 1.500000 36.0 spng
61 27 29 200.0 1.500000 36.0 spng
62 28 30 200.0 1.500000 36.0 spng
63 29 31 200.0 1.500000 36.0 spng
64 30 32 200.0 1.500000 36.0 spng
65 31 33 200.0 1.500000 36.0 spng
66 32 34 200.0 1.500000 36.0 spng
67 33 35 200.0 1.500000 36.0 spng
68 34 36 200.0 1.500000 36.0 spng
69 35 37 200.0 1.500000 36.0 spng
70 36 38 200.0 1.500000 36.0 spng
71 1 20 200.0 1.500000 26.0 spng
72 2 21 200.0 1.500000 26.0 spng
73 3 22 200.0 1.500000 26.0 spng
74 4 23 200.0 1.500000 26.0 spng
75 5 24 200.0 1.500000 26.0 spng
76 25 6 200.0 1.500000 26.0 spng
77 7 26 200.0 1.500000 26.0 spng
78 27 8 200.0 1.500000 26.0 spng
79 9 28 200.0 1.500000 26.0 spng
80 29 10 200.0 1.500000 26.0 spng
81 11 30 200.0 1.500000 26.0 spng
82 31 12 200.0 1.500000 26.0 spng
83 13 32 200.0 1.500000 26.0 spng
84 33 14 200.0 1.500000 26.0 spng
85 15 34 200.0 1.500000 26.0 spng
86 35 16 200.0 1.500000 26.0 spng
87 17 36 200.0 1.500000 26.0 spng
88 37 18 200.0 1.500000 26.0 spng
89 19 38 200.0 1.500000 26.0 spng
90 1 21 200.0 1.500000 31.064449 spng
91 2 20 200.0 1.500000 31.064449 spng
92 2 22 200.0 1.500000 31.622777 spng
93 3 21 200.0 1.500000 31.622777 spng
94 3 23 200.0 1.500000 31.622777 spng
95 4 22 200.0 1.500000 31.622777 spng
96 4 24 200.0 1.500000 31.622777 spng
97 5 23 200.0 1.500000 31.622777 spng
98 5 25 200.0 1.500000 31.622777 spng
99 6 24 200.0 1.500000 31.622777 spng
100 6 26 200.0 1.500000 31.622777 spng
101 7 25 200.0 1.500000 31.622777 spng
102 7 27 200.0 1.500000 31.622777 spng
103 8 26 200.0 1.500000 31.622777 spng
104 8 28 200.0 1.500000 31.622777 spng
105 9 27 200.0 1.500000 31.622777 spng
106 9 29 200.0 1.500000 31.622777 spng
107 10 28 200.0 1.500000 31.622777 spng
108 10 30 200.0 1.500000 31.622777 spng
109 11 29 200.0 1.500000 31.622777 spng
110 11 31 200.0 1.500000 31.622777 spng
111 12 30 200.0 1.500000 31.622777 spng
112 12 32 200.0 1.500000 31.622777 spng
113 13 31 200.0 1.500000 31.622777 spng
114 13 33 200.0 1.500000 31.622777 spng
115 14 32 200.0 1.500000 31.622777 spng
116 14 34 200.0 1.500000 31.622777 spng
117 15 33 200.0 1.500000 31.622777 spng
118 15 35 200.0 1.500000 31.622777 spng
119 16 34 200.0 1.500000 31.622777 spng
120 16 36 200.0 1.500000 31.622777 spng
121 17 35 200.0 1.500000 31.622777 spng
122 17 37 200.0 1.500000 31.622777 spng
123 18 36 200.0 1.500000 31.622777 spng
124 18 38 200.0 1.500000 31.622777 spng
125 19 37 200.0 1.500000 31.622777 spng
126 1 22 200.0 1.500000 43.600459 spng
127 3 20 200.0 1.500000 43.600459 spng
128 2 23 200.0 1.500000 44.407207 spng
129 4 21 200.0 1.500000 44.407207 spng
130 3 24 200.0 1.500000 44.407207 spng
131 5 22 200.0 1.500000 44.407207 spng
132 4 25 200.0 1.500000 44.407207 spng
133 6 23 200.0 1.500000 44.407207 spng
134 5 26 200.0 1.500000 44.407207 spng
135 7 24 200.0 1.500000 44.407207 spng
136 6 27 200.0 1.500000 44.407207 spng
137 8 25 200.0 1.500000 44.407207 spng
138 7 28 200.0 1.500000 44.407207 spng
139 9 26 200.0 1.500000 44.407207 spng
140 8 29 200.0 1.500000 44.407207 spng
141 10 27 200.0 1.500000 44.407207 spng
142 9 30 200.0 1.500000 44.407207 spng
143 11 28 200.0 1.500000 44.407207 spng
144 10 31 200.0 1.500000 44.407207 spng
145 12 29 200.0 1.500000 44.407207 spng
146 11 32 200.0 1.500000 44.407207 spng
147 13 30 200.0 1.500000 44.407207 spng
148 12 33 200.0 1.500000 44.407207 spng
149 14 31 200.0 1.500000 44.407207 spng
150 13 34 200.0 1.500000 44.407207 spng
151 15 33 200.0 1.500000 31.622777 spng
152 32 15 200.0 1.500000 44.407207 spng
153 14 35 200.0 1.500000 44.407207 spng
154 16 33 200.0 1.500000 44.407207 spng
155 15 36 200.0 1.500000 44.407207 spng
156 34 17 200.0 1.500000 44.407207 spng
157 16 37 200.0 1.500000 44.407207 spng
158 18 35 200.0 1.500000 44.407207 spng
159 17 38 200.0 1.500000 44.407207 spng
160 19 36 200.0 1.500000 44.407207 spng
! Send the half of the snake in a random direction
nodes> 10 [ swap nth ] with map
nodes> 10 [ 19 + swap nth ] with map append
100 random -50 + 100 random 100 + { -1 1 } random * 2array
[ swap set-node-vel ] curry
each ;
: go ( -- ) [ model ] go* ;
MAIN: go
]]
FILE: [[springies/models/2x2snake/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/2x2snake/tags.txt]] [[demos
]]
FILE: [[springies/models/2snake/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/2snake/2snake.factor]] [[
USING: kernel namespaces arrays sequences math math.vectors random
springies springies.ui ;
IN: springies.models.2snake
: model ( -- )
{ } clone >nodes
{ } clone >springs
0.001 >time-slice
gravity off
1 19.0 328.0 0.0 0.0 1.0 1.0 mass
2 36.0 328.0 0.0 0.0 1.0 1.0 mass
3 54.0 328.0 0.0 0.0 1.0 1.0 mass
4 72.0 328.0 0.0 0.0 1.0 1.0 mass
5 90.0 328.0 0.0 0.0 1.0 1.0 mass
6 108.0 328.0 0.0 0.0 1.0 1.0 mass
7 126.0 328.0 0.0 0.0 1.0 1.0 mass
8 144.0 328.0 0.0 0.0 1.0 1.0 mass
9 162.0 328.0 0.0 0.0 1.0 1.0 mass
10 180.0 328.0 0.0 0.0 1.0 1.0 mass
11 198.0 328.0 0.0 0.0 1.0 1.0 mass
12 216.0 328.0 0.0 0.0 1.0 1.0 mass
13 234.0 328.0 0.0 0.0 1.0 1.0 mass
14 252.0 328.0 0.0 0.0 1.0 1.0 mass
15 270.0 328.0 0.0 0.0 1.0 1.0 mass
16 288.0 328.0 0.0 0.0 1.0 1.0 mass
17 306.0 328.0 0.0 0.0 1.0 1.0 mass
18 324.0 328.0 0.0 0.0 1.0 1.0 mass
19 342.0 328.0 0.0 0.0 1.0 1.0 mass
20 360.0 328.0 0.0 0.0 1.0 1.0 mass
21 378.0 328.0 0.0 0.0 1.0 1.0 mass
22 396.0 328.0 0.0 0.0 1.0 1.0 mass
23 414.0 328.0 0.0 0.0 1.0 1.0 mass
24 432.0 328.0 0.0 0.0 1.0 1.0 mass
25 450.0 328.0 0.0 0.0 1.0 1.0 mass
26 468.0 328.0 0.0 0.0 1.0 1.0 mass
27 504.0 328.0 0.0 0.0 1.0 1.0 mass
28 486.0 328.0 0.0 0.0 1.0 1.0 mass
29 522.0 328.0 0.0 0.0 1.0 1.0 mass
30 540.0 328.0 0.0 0.0 1.0 1.0 mass
31 558.0 328.0 0.0 0.0 1.0 1.0 mass
32 576.0 328.0 0.0 0.0 1.0 1.0 mass
33 594.0 328.0 0.0 0.0 1.0 1.0 mass
34 612.0 328.0 0.0 0.0 1.0 1.0 mass
35 630.0 328.0 0.0 0.0 1.0 1.0 mass
1 1 2 200.0 1.500000 18.0 spng
2 3 2 200.0 1.500000 18.0 spng
3 3 4 200.0 1.500000 18.0 spng
4 4 5 200.0 1.500000 18.0 spng
5 5 6 200.0 1.500000 18.0 spng
6 6 7 200.0 1.500000 18.0 spng
7 7 8 200.0 1.500000 18.0 spng
8 8 9 200.0 1.500000 18.0 spng
9 9 10 200.0 1.500000 18.0 spng
10 10 11 200.0 1.500000 18.0 spng
11 11 12 200.0 1.500000 18.0 spng
12 12 13 200.0 1.500000 18.0 spng
13 13 14 200.0 1.500000 18.0 spng
14 14 15 200.0 1.500000 18.0 spng
15 15 16 200.0 1.500000 18.0 spng
16 16 17 200.0 1.500000 18.0 spng
17 17 18 200.0 1.500000 18.0 spng
18 18 19 200.0 1.500000 18.0 spng
19 19 20 200.0 1.500000 18.0 spng
20 20 21 200.0 1.500000 18.0 spng
21 21 22 200.0 1.500000 18.0 spng
22 22 23 200.0 1.500000 18.0 spng
23 23 24 200.0 1.500000 18.0 spng
24 24 25 200.0 1.500000 18.0 spng
25 25 26 200.0 1.500000 18.0 spng
26 26 28 200.0 1.500000 18.0 spng
27 28 27 200.0 1.500000 18.0 spng
28 27 29 200.0 1.500000 18.0 spng
29 29 30 200.0 1.500000 18.0 spng
30 30 31 200.0 1.500000 18.0 spng
31 31 32 200.0 1.500000 18.0 spng
32 32 33 200.0 1.500000 18.0 spng
33 33 34 200.0 1.500000 18.0 spng
34 34 35 200.0 1.500000 18.0 spng
35 1 3 200.0 1.500000 36.0 spng
36 2 4 200.0 1.500000 36.0 spng
37 3 5 200.0 1.500000 36.0 spng
38 4 6 200.0 1.500000 36.0 spng
39 5 7 200.0 1.500000 36.0 spng
40 6 8 200.0 1.500000 36.0 spng
41 7 9 200.0 1.500000 36.0 spng
42 8 10 200.0 1.500000 36.0 spng
43 9 11 200.0 1.500000 36.0 spng
44 10 12 200.0 1.500000 36.0 spng
45 11 13 200.0 1.500000 36.0 spng
46 12 14 200.0 1.500000 36.0 spng
47 13 15 200.0 1.500000 36.0 spng
48 14 16 200.0 1.500000 36.0 spng
49 15 17 200.0 1.500000 36.0 spng
50 16 18 200.0 1.500000 36.0 spng
51 17 19 200.0 1.500000 36.0 spng
52 18 20 200.0 1.500000 36.0 spng
53 19 21 200.0 1.500000 36.0 spng
54 20 22 200.0 1.500000 36.0 spng
55 21 23 200.0 1.500000 36.0 spng
56 22 24 200.0 1.500000 36.0 spng
57 23 25 200.0 1.500000 36.0 spng
58 24 26 200.0 1.500000 36.0 spng
59 25 28 200.0 1.500000 36.0 spng
60 26 27 200.0 1.500000 36.0 spng
61 28 29 200.0 1.500000 36.0 spng
62 27 30 200.0 1.500000 36.0 spng
63 29 31 200.0 1.500000 36.0 spng
64 30 32 200.0 1.500000 36.0 spng
65 31 33 200.0 1.500000 36.0 spng
66 32 34 200.0 1.500000 36.0 spng
67 33 35 200.0 1.500000 36.0 spng
nodes> [ 400 random -200 + 400 random -200 + 2array swap set-node-vel ] each ;
USING: threads ui ;
: go ( -- ) [ [ springies-window* 1000 sleep model ] with-scope ] with-ui ;
MAIN: go
]]
FILE: [[springies/models/2snake/tags.txt]] [[demos
]]
FILE: [[springies/models/ball/ball.factor]] [[
USING: kernel namespaces sequences springies springies.ui ;
IN: springies.models.ball
: model ( -- )
{ } clone >nodes
{ } clone >springs
0.01 >time-slice
gravity on
1 325.191871 140.872641 40.832215 -5.301529 1.0 1.0 mass
2 313.933994 149.011616 55.240875 5.026852 1.0 1.0 mass
3 309.133386 162.523019 72.798059 5.594199 1.0 1.0 mass
4 312.887152 176.436760 83.754277 -1.370025 1.0 1.0 mass
5 321.660596 187.895952 91.634021 -8.308630 1.0 1.0 mass
6 335.256132 192.503856 94.772924 -18.985044 1.0 1.0 mass
7 348.254504 188.731936 92.657963 -29.982110 1.0 1.0 mass
8 359.050972 180.780059 86.668616 -39.817638 1.0 1.0 mass
9 363.685639 167.752177 76.554871 -47.987107 1.0 1.0 mass
10 360.449954 154.092353 57.992242 -48.045772 1.0 1.0 mass
11 352.201411 142.382665 41.200547 -39.924209 1.0 1.0 mass
12 338.754859 137.460615 32.306364 -22.707784 1.0 1.0 mass
13 312.911184 114.835962 8.342965 5.878311 1.0 1.0 mass
14 290.521818 132.872407 33.212103 28.391710 1.0 1.0 mass
15 281.048450 160.314206 66.319674 32.935324 1.0 1.0 mass
16 287.450075 188.730522 93.898071 21.966741 1.0 1.0 mass
17 305.987715 211.206959 112.571044 5.089593 1.0 1.0 mass
18 333.289699 220.830317 121.166705 -17.204713 1.0 1.0 mass
19 361.089678 214.901909 117.183695 -41.776506 1.0 1.0 mass
20 382.690515 197.005784 101.789802 -63.980298 1.0 1.0 mass
21 392.095364 170.108402 75.453780 -78.414351 1.0 1.0 mass
22 386.286391 142.033621 41.812216 -77.402424 1.0 1.0 mass
23 368.355658 119.326317 12.658676 -58.885262 1.0 1.0 mass
24 341.159901 109.253775 -0.645459 -27.346079 1.0 1.0 mass
25 300.792976 88.652764 -23.770230 17.788258 1.0 1.0 mass
26 266.917041 116.942125 11.387083 52.603190 1.0 1.0 mass
27 252.824303 157.992984 59.144863 62.163730 1.0 1.0 mass
28 261.812599 201.245775 103.542171 47.141708 1.0 1.0 mass
29 290.323965 234.792944 133.016945 18.136362 1.0 1.0 mass
30 330.805232 249.331769 145.899409 -16.478401 1.0 1.0 mass
31 373.715232 241.181453 141.068680 -55.103677 1.0 1.0 mass
32 406.314817 213.217096 116.087430 -90.844012 1.0 1.0 mass
33 420.647493 172.661774 73.304028 -110.880720 1.0 1.0 mass
34 412.375908 129.697207 24.072484 -106.129512 1.0 1.0 mass
35 384.555754 95.915740 -16.565355 -77.142380 1.0 1.0 mass
36 344.134757 80.886540 -34.250916 -30.871105 1.0 1.0 mass
37 288.774590 62.672780 -55.431084 28.821437 1.0 1.0 mass
38 244.055965 100.457489 -9.756397 76.701354 1.0 1.0 mass
39 224.574635 156.693148 53.845562 91.755892 1.0 1.0 mass
40 235.856891 213.935639 112.462316 73.437061 1.0 1.0 mass
41 273.697931 257.991035 152.320671 33.701056 1.0 1.0 mass
42 329.129445 277.782400 170.727571 -15.899371 1.0 1.0 mass
43 386.065290 267.474982 165.436658 -68.761273 1.0 1.0 mass
44 429.946314 229.605765 132.087682 -116.795195 1.0 1.0 mass
45 449.164590 174.189613 73.084826 -143.228528 1.0 1.0 mass
46 438.674101 117.351918 9.340834 -136.225613 1.0 1.0 mass
47 401.586435 72.955570 -42.523445 -98.317857 1.0 1.0 mass
48 346.207804 52.561279 -67.447974 -34.980297 1.0 1.0 mass
1 1 2 150.0 2.0 14.0 spng
2 2 3 150.0 2.0 14.0 spng
3 3 4 150.0 2.0 14.0 spng
4 4 5 150.0 2.0 14.0 spng
5 5 6 150.0 2.0 14.0 spng
6 6 7 150.0 2.0 14.0 spng
7 7 8 150.0 2.0 14.0 spng
8 8 9 150.0 2.0 14.0 spng
9 9 10 150.0 2.0 14.0 spng
10 10 11 150.0 2.0 14.0 spng
11 11 12 150.0 2.0 14.0 spng
12 12 1 150.0 2.0 14.0 spng
13 13 14 150.0 2.0 28.0 spng
14 14 15 150.0 2.0 28.0 spng
15 15 16 150.0 2.0 28.0 spng
16 16 17 150.0 2.0 28.0 spng
17 17 18 150.0 2.0 28.0 spng
18 18 19 150.0 2.0 28.0 spng
19 19 20 150.0 2.0 28.0 spng
20 20 21 150.0 2.0 28.0 spng
21 21 22 150.0 2.0 28.0 spng
22 22 23 150.0 2.0 28.0 spng
23 23 24 150.0 2.0 28.0 spng
24 24 13 150.0 2.0 28.0 spng
25 25 26 150.0 2.0 44.0 spng
26 26 27 150.0 2.0 43.0 spng
27 27 28 150.0 2.0 44.0 spng
28 28 29 150.0 2.0 44.0 spng
29 29 30 150.0 2.0 43.0 spng
30 30 31 150.0 2.0 44.0 spng
31 31 32 150.0 2.0 43.0 spng
32 32 33 150.0 2.0 43.0 spng
33 33 34 150.0 2.0 44.0 spng
34 34 35 150.0 2.0 44.0 spng
35 35 36 150.0 2.0 43.0 spng
36 36 25 150.0 2.0 44.0 spng
37 37 38 150.0 2.0 58.0 spng
38 38 39 150.0 2.0 59.0 spng
39 39 40 150.0 2.0 58.0 spng
40 40 41 150.0 2.0 58.0 spng
41 41 42 150.0 2.0 59.0 spng
42 42 43 150.0 2.0 58.0 spng
43 43 44 150.0 2.0 58.0 spng
44 44 45 150.0 2.0 59.0 spng
45 45 46 150.0 2.0 58.0 spng
46 46 47 150.0 2.0 58.0 spng
47 47 48 150.0 2.0 59.0 spng
48 48 37 150.0 2.0 58.0 spng
49 1 13 150.0 2.0 29.0 spng
50 2 14 150.0 2.0 28.0 spng
51 3 15 150.0 2.0 28.0 spng
52 4 16 150.0 2.0 29.0 spng
53 5 17 150.0 2.0 28.0 spng
54 6 18 150.0 2.0 28.0 spng
55 7 19 150.0 2.0 29.0 spng
56 8 20 150.0 2.0 28.0 spng
57 9 21 150.0 2.0 28.0 spng
58 10 22 150.0 2.0 29.0 spng
59 11 23 150.0 2.0 28.0 spng
60 12 24 150.0 2.0 28.0 spng
61 13 25 150.0 2.0 29.0 spng
62 14 26 150.0 2.0 28.0 spng
63 15 27 150.0 2.0 28.0 spng
64 16 28 150.0 2.0 29.0 spng
65 17 29 150.0 2.0 28.0 spng
66 18 30 150.0 2.0 28.0 spng
67 19 31 150.0 2.0 29.0 spng
68 20 32 150.0 2.0 28.0 spng
69 21 33 150.0 2.0 28.0 spng
70 22 34 150.0 2.0 29.0 spng
71 23 35 150.0 2.0 28.0 spng
72 24 36 150.0 2.0 28.0 spng
73 25 37 150.0 2.0 29.0 spng
74 26 38 150.0 2.0 28.0 spng
75 27 39 150.0 2.0 28.0 spng
76 28 40 150.0 2.0 29.0 spng
77 29 41 150.0 2.0 28.0 spng
78 30 42 150.0 2.0 28.0 spng
79 31 43 150.0 2.0 29.0 spng
80 32 44 150.0 2.0 28.0 spng
81 33 45 150.0 2.0 28.0 spng
82 34 46 150.0 2.0 29.0 spng
83 35 47 150.0 2.0 28.0 spng
84 36 48 150.0 2.0 28.0 spng
85 1 14 150.0 2.0 35.0 spng
86 2 15 150.0 2.0 35.0 spng
87 3 16 150.0 2.0 34.0 spng
88 4 17 150.0 2.0 35.0 spng
89 5 18 150.0 2.0 35.0 spng
90 6 19 150.0 2.0 34.0 spng
91 7 20 150.0 2.0 35.0 spng
92 8 21 150.0 2.0 35.0 spng
93 9 22 150.0 2.0 34.0 spng
94 10 23 150.0 2.0 35.0 spng
95 11 24 150.0 2.0 35.0 spng
96 12 13 150.0 2.0 34.0 spng
97 13 26 150.0 2.0 46.0 spng
98 14 27 150.0 2.0 45.0 spng
99 15 28 150.0 2.0 45.0 spng
100 16 29 150.0 2.0 46.0 spng
101 17 30 150.0 2.0 45.0 spng
102 18 31 150.0 2.0 45.0 spng
103 19 32 150.0 2.0 45.0 spng
104 20 33 150.0 2.0 45.0 spng
105 21 34 150.0 2.0 45.0 spng
106 22 35 150.0 2.0 46.0 spng
107 23 36 150.0 2.0 45.0 spng
108 24 25 150.0 2.0 45.0 spng
109 25 38 150.0 2.0 58.0 spng
110 26 39 150.0 2.0 58.0 spng
111 27 40 150.0 2.0 58.0 spng
112 28 41 150.0 2.0 58.0 spng
113 29 42 150.0 2.0 58.0 spng
114 30 43 150.0 2.0 58.0 spng
115 31 44 150.0 2.0 58.0 spng
116 32 45 150.0 2.0 58.0 spng
117 33 46 150.0 2.0 58.0 spng
118 34 47 150.0 2.0 58.0 spng
119 35 48 150.0 2.0 58.0 spng
120 36 37 150.0 2.0 58.0 spng
121 1 24 150.0 2.0 35.0 spng
122 2 13 150.0 2.0 34.0 spng
123 3 14 150.0 2.0 35.0 spng
124 4 15 150.0 2.0 35.0 spng
125 5 16 150.0 2.0 34.0 spng
126 6 17 150.0 2.0 35.0 spng
127 7 18 150.0 2.0 35.0 spng
128 8 19 150.0 2.0 34.0 spng
129 9 20 150.0 2.0 35.0 spng
130 10 21 150.0 2.0 35.0 spng
131 11 22 150.0 2.0 34.0 spng
132 12 23 150.0 2.0 35.0 spng
133 13 36 150.0 2.0 46.0 spng
134 14 25 150.0 2.0 45.0 spng
135 15 26 150.0 2.0 45.0 spng
136 16 27 150.0 2.0 46.0 spng
137 17 28 150.0 2.0 45.0 spng
138 18 29 150.0 2.0 45.0 spng
139 19 30 150.0 2.0 46.0 spng
140 20 31 150.0 2.0 45.0 spng
141 21 32 150.0 2.0 45.0 spng
142 22 33 150.0 2.0 46.0 spng
143 23 34 150.0 2.0 45.0 spng
144 24 35 150.0 2.0 45.0 spng
145 25 48 150.0 2.0 58.0 spng
146 26 37 150.0 2.0 58.0 spng
147 27 38 150.0 2.0 58.0 spng
148 28 39 150.0 2.0 58.0 spng
149 29 40 150.0 2.0 58.0 spng
150 30 41 150.0 2.0 58.0 spng
151 31 42 150.0 2.0 58.0 spng
152 32 43 150.0 2.0 58.0 spng
153 33 44 150.0 2.0 58.0 spng
154 34 45 150.0 2.0 58.0 spng
155 35 46 150.0 2.0 58.0 spng
156 36 47 150.0 2.0 58.0 spng
157 10 4 150.0 2.0 52.331631 spng
158 7 1 150.0 2.0 52.436772 spng
159 12 6 150.0 2.0 54.680698 spng
160 5 11 150.0 2.0 54.589379 spng
161 9 3 150.0 2.0 54.451569 spng
162 2 8 150.0 2.0 54.482231 spng
163 45 11 150.0 2.0 101.408150 spng
164 46 12 150.0 2.0 101.542452 spng
165 47 1 150.0 2.0 101.963064 spng
166 48 2 150.0 2.0 101.517329 spng
167 37 3 150.0 2.0 101.603694 spng
168 38 4 150.0 2.0 102.014031 spng
169 39 5 150.0 2.0 101.547660 spng
170 40 6 150.0 2.0 101.573762 spng
171 41 7 150.0 2.0 101.897300 spng
172 42 8 150.0 2.0 101.497982 spng
173 43 9 150.0 2.0 101.870594 spng
174 44 10 150.0 2.0 102.043753 spng
175 45 11 150.0 2.0 101.408150 spng
176 46 8 150.0 2.0 101.548938 spng
177 47 10 150.0 2.0 90.645939 spng
178 48 10 150.0 2.0 101.952119 spng
179 37 11 150.0 2.0 101.552352 spng
180 38 12 150.0 2.0 101.491447 spng
181 39 1 150.0 2.0 101.971524 spng
182 40 2 150.0 2.0 101.587400 spng
183 41 3 150.0 2.0 101.519279 spng
184 42 4 150.0 2.0 101.976181 spng
185 43 5 150.0 2.0 101.714570 spng
186 44 6 150.0 2.0 101.388747 spng
187 45 7 150.0 2.0 101.773286 spng
nodes> [ { 0 100 } swap set-node-vel ] each ;
USING: threads ui ;
: go ( -- ) [ [ springies-window* 1000 sleep model ] with-scope ] with-ui ;
MAIN: go
]]
FILE: [[springies/models/ball/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/ball/tags.txt]] [[demos
]]
FILE: [[springies/models/3snake/3snake.factor]] [[
USING: kernel namespaces arrays sequences threads math ui random fry
springies springies.ui ;
IN: springies.models.3snake
: random-range ( a b -- n ) 1+ over - random + ;
: model ( -- )
{ } clone >nodes
{ } clone >springs
0.001 >time-slice
gravity off
1 19.0 328.0 0.0 0.0 1.0 1.0 mass
2 36.0 328.0 0.0 0.0 1.0 1.0 mass
3 54.0 328.0 0.0 0.0 1.0 1.0 mass
4 72.0 328.0 0.0 0.0 1.0 1.0 mass
5 90.0 328.0 0.0 0.0 1.0 1.0 mass
6 108.0 328.0 0.0 0.0 1.0 1.0 mass
7 126.0 328.0 0.0 0.0 1.0 1.0 mass
8 144.0 328.0 0.0 0.0 1.0 1.0 mass
9 162.0 328.0 0.0 0.0 1.0 1.0 mass
10 180.0 328.0 0.0 0.0 1.0 1.0 mass
11 198.0 328.0 0.0 0.0 1.0 1.0 mass
12 216.0 328.0 0.0 0.0 1.0 1.0 mass
13 234.0 328.0 0.0 0.0 1.0 1.0 mass
14 252.0 328.0 0.0 0.0 1.0 1.0 mass
15 270.0 328.0 0.0 0.0 1.0 1.0 mass
16 288.0 328.0 0.0 0.0 1.0 1.0 mass
17 306.0 328.0 0.0 0.0 1.0 1.0 mass
18 324.0 328.0 0.0 0.0 1.0 1.0 mass
19 342.0 328.0 0.0 0.0 1.0 1.0 mass
20 360.0 328.0 0.0 0.0 1.0 1.0 mass
21 378.0 328.0 0.0 0.0 1.0 1.0 mass
22 396.0 328.0 0.0 0.0 1.0 1.0 mass
23 414.0 328.0 0.0 0.0 1.0 1.0 mass
24 432.0 328.0 0.0 0.0 1.0 1.0 mass
25 450.0 328.0 0.0 0.0 1.0 1.0 mass
26 468.0 328.0 0.0 0.0 1.0 1.0 mass
27 504.0 328.0 0.0 0.0 1.0 1.0 mass
28 486.0 328.0 0.0 0.0 1.0 1.0 mass
29 522.0 328.0 0.0 0.0 1.0 1.0 mass
30 540.0 328.0 0.0 0.0 1.0 1.0 mass
31 558.0 328.0 0.0 0.0 1.0 1.0 mass
32 576.0 328.0 0.0 0.0 1.0 1.0 mass
33 594.0 328.0 0.0 0.0 1.0 1.0 mass
34 612.0 328.0 0.0 0.0 1.0 1.0 mass
35 626.0 328.0 0.0 0.0 1.0 1.0 mass
1 1 2 200.0 1.500000 18.0 spng
2 3 2 200.0 1.500000 18.0 spng
3 3 4 200.0 1.500000 18.0 spng
4 4 5 200.0 1.500000 18.0 spng
5 5 6 200.0 1.500000 18.0 spng
6 6 7 200.0 1.500000 18.0 spng
7 7 8 200.0 1.500000 18.0 spng
8 8 9 200.0 1.500000 18.0 spng
9 9 10 200.0 1.500000 18.0 spng
10 10 11 200.0 1.500000 18.0 spng
11 11 12 200.0 1.500000 18.0 spng
12 12 13 200.0 1.500000 18.0 spng
13 13 14 200.0 1.500000 18.0 spng
14 14 15 200.0 1.500000 18.0 spng
15 15 16 200.0 1.500000 18.0 spng
16 16 17 200.0 1.500000 18.0 spng
17 17 18 200.0 1.500000 18.0 spng
18 18 19 200.0 1.500000 18.0 spng
19 19 20 200.0 1.500000 18.0 spng
20 20 21 200.0 1.500000 18.0 spng
21 21 22 200.0 1.500000 18.0 spng
22 22 23 200.0 1.500000 18.0 spng
23 23 24 200.0 1.500000 18.0 spng
24 24 25 200.0 1.500000 18.0 spng
25 25 26 200.0 1.500000 18.0 spng
26 26 28 200.0 1.500000 18.0 spng
27 28 27 200.0 1.500000 18.0 spng
28 27 29 200.0 1.500000 18.0 spng
29 29 30 200.0 1.500000 18.0 spng
30 30 31 200.0 1.500000 18.0 spng
31 31 32 200.0 1.500000 18.0 spng
32 32 33 200.0 1.500000 18.0 spng
33 33 34 200.0 1.500000 18.0 spng
34 34 35 200.0 1.500000 18.0 spng
35 1 3 200.0 1.500000 36.0 spng
36 2 4 200.0 1.500000 36.0 spng
37 3 5 200.0 1.500000 36.0 spng
38 4 6 200.0 1.500000 36.0 spng
39 5 7 200.0 1.500000 36.0 spng
40 6 8 200.0 1.500000 36.0 spng
41 7 9 200.0 1.500000 36.0 spng
42 8 10 200.0 1.500000 36.0 spng
43 9 11 200.0 1.500000 36.0 spng
44 10 12 200.0 1.500000 36.0 spng
45 11 13 200.0 1.500000 36.0 spng
46 12 14 200.0 1.500000 36.0 spng
47 13 15 200.0 1.500000 36.0 spng
48 14 16 200.0 1.500000 36.0 spng
49 15 17 200.0 1.500000 36.0 spng
50 16 18 200.0 1.500000 36.0 spng
51 17 19 200.0 1.500000 36.0 spng
52 18 20 200.0 1.500000 36.0 spng
53 19 21 200.0 1.500000 36.0 spng
54 20 22 200.0 1.500000 36.0 spng
55 21 23 200.0 1.500000 36.0 spng
56 22 24 200.0 1.500000 36.0 spng
57 23 25 200.0 1.500000 36.0 spng
58 24 26 200.0 1.500000 36.0 spng
59 25 28 200.0 1.500000 36.0 spng
60 26 27 200.0 1.500000 36.0 spng
61 28 29 200.0 1.500000 36.0 spng
62 27 30 200.0 1.500000 36.0 spng
63 29 31 200.0 1.500000 36.0 spng
64 30 32 200.0 1.500000 36.0 spng
65 31 33 200.0 1.500000 36.0 spng
66 32 34 200.0 1.500000 36.0 spng
67 33 35 200.0 1.500000 36.0 spng
68 1 4 200.0 1.500000 53.0 spng
69 2 5 200.0 1.500000 54.0 spng
70 3 6 200.0 1.500000 54.0 spng
71 4 7 200.0 1.500000 54.0 spng
72 5 8 200.0 1.500000 54.0 spng
73 6 9 200.0 1.500000 54.0 spng
74 7 10 200.0 1.500000 54.0 spng
75 8 11 200.0 1.500000 54.0 spng
76 9 12 200.0 1.500000 54.0 spng
77 10 13 200.0 1.500000 54.0 spng
78 11 14 200.0 1.500000 54.0 spng
79 12 15 200.0 1.500000 54.0 spng
80 13 16 200.0 1.500000 54.0 spng
81 14 17 200.0 1.500000 54.0 spng
82 15 18 200.0 1.500000 54.0 spng
83 16 19 200.0 1.500000 54.0 spng
84 17 20 200.0 1.500000 54.0 spng
85 18 21 200.0 1.500000 54.0 spng
86 19 22 200.0 1.500000 54.0 spng
87 20 23 200.0 1.500000 54.0 spng
88 21 24 200.0 1.500000 54.0 spng
89 22 25 200.0 1.500000 54.0 spng
90 23 26 200.0 1.500000 54.0 spng
91 24 28 200.0 1.500000 54.0 spng
92 25 27 200.0 1.500000 54.0 spng
93 26 29 200.0 1.500000 54.0 spng
94 28 30 200.0 1.500000 54.0 spng
95 27 31 200.0 1.500000 54.0 spng
96 29 32 200.0 1.500000 54.0 spng
97 30 33 200.0 1.500000 54.0 spng
98 31 34 200.0 1.500000 54.0 spng
99 32 35 200.0 1.500000 50.0 spng
10
[
-400 400 random-range -400 400 random-range 2array
nodes> random
set-node-vel
]
times
;
! : go* ( quot -- )
! [ [ [ springies-window* 1000 sleep % ] with-scope ] with-ui ] bake call ;
: go* ( quot -- ) '[ [ springies-window* 1000 sleep @ ] with-scope ] with-ui ;
! : go ( -- ) [ [ springies-window* 1000 sleep model ] with-scope ] with-ui ;
: go ( -- ) [ model ] go* ;
MAIN: go
]]
FILE: [[springies/models/3snake/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/3snake/tags.txt]] [[demos
]]
FILE: [[springies/models/urchin/urchin.factor]] [[
USING: kernel namespaces arrays sequences threads math math.vectors
ui random
springies springies.ui ;
IN: springies.models.urchin
: model ( -- )
{ } clone >nodes
{ } clone >springs
0.007 >time-slice
gravity on
1 507.296953 392.174236 -11.451186 -71.267273 1.0 1.0 mass
2 514.879820 372.128025 11.950035 -70.858717 1.0 1.0 mass
3 536.571268 364.423706 18.394466 -41.159445 1.0 1.0 mass
4 554.886966 369.953895 15.173664 -11.009243 1.0 1.0 mass
5 572.432935 379.927626 8.228103 -1.120846 1.0 1.0 mass
6 585.774508 392.380791 5.443281 -8.186599 1.0 1.0 mass
7 584.650543 411.934530 -15.582843 -24.911756 1.0 1.0 mass
8 569.409148 424.155713 -24.100159 -42.285960 1.0 1.0 mass
9 553.751996 434.663690 -26.069217 -41.610454 1.0 1.0 mass
10 536.684374 444.915694 -30.702349 -45.021926 1.0 1.0 mass
11 516.677286 435.936238 -33.128410 -60.977340 1.0 1.0 mass
12 514.170680 414.649472 -24.471518 -64.104425 1.0 1.0 mass
13 602.101547 478.298945 1.612646 -53.040881 1.0 1.0 mass
14 637.0 427.598266 0.0 0.0 1.0 1.0 mass
15 608.000171 350.425575 31.812856 23.456940 1.0 1.0 mass
16 484.367809 332.414622 42.575378 -91.238351 1.0 1.0 mass
17 480.857379 475.215663 -24.240991 -53.909049 1.0 1.0 mass
18 548.580015 492.173168 -34.565312 -52.436468 1.0 1.0 mass
19 578.155338 487.173526 22.544495 -71.920721 1.0 1.0 mass
20 630.992588 379.333707 16.662115 37.873709 1.0 1.0 mass
21 591.256916 324.817423 63.036114 27.988433 1.0 1.0 mass
22 539.051461 311.597938 159.501014 -27.955219 1.0 1.0 mass
23 448.396171 396.882674 -15.045910 -138.652372 1.0 1.0 mass
24 448.194414 419.993896 -27.625008 -84.936708 1.0 1.0 mass
1 1 2 200.0 3.0 20.0 spng
2 2 3 200.0 3.0 20.0 spng
3 3 4 200.0 3.0 20.0 spng
4 4 5 200.0 3.0 20.0 spng
5 5 6 200.0 3.0 20.0 spng
6 6 7 200.0 3.0 20.0 spng
7 7 8 200.0 3.0 20.0 spng
8 8 9 200.0 3.0 20.0 spng
9 9 10 200.0 3.0 20.0 spng
10 10 11 200.0 3.0 20.0 spng
11 11 12 200.0 3.0 20.0 spng
12 1 3 200.0 3.0 40.0 spng
13 2 4 200.0 3.0 40.0 spng
14 3 5 200.0 3.0 40.0 spng
15 4 6 200.0 3.0 40.0 spng
16 6 8 200.0 3.0 40.0 spng
17 7 9 200.0 3.0 40.0 spng
18 8 10 200.0 3.0 40.0 spng
19 9 11 200.0 3.0 40.0 spng
20 10 12 200.0 3.0 40.0 spng
21 12 1 200.0 3.0 21.0 spng
22 12 2 200.0 3.0 41.0 spng
23 11 1 200.0 3.0 41.0 spng
24 6 12 200.0 3.0 72.681733 spng
25 5 11 200.0 3.0 81.191259 spng
26 10 4 200.0 3.0 76.026311 spng
27 3 9 200.0 3.0 72.615425 spng
28 8 2 200.0 3.0 74.966659 spng
29 1 7 200.0 3.0 80.280757 spng
30 17 11 200.0 3.0 55.036352 spng
31 10 18 200.0 3.0 49.819675 spng
32 19 9 200.0 3.0 54.918121 spng
33 8 13 200.0 3.0 62.201286 spng
34 14 7 200.0 3.0 58.600341 spng
35 6 20 200.0 3.0 46.400431 spng
36 15 5 200.0 3.0 44.045431 spng
37 4 21 200.0 3.0 57.454330 spng
38 22 3 200.0 3.0 53.823787 spng
39 2 16 200.0 3.0 51.039201 spng
40 23 1 200.0 3.0 58.668561 spng
41 12 24 200.0 3.0 64.404969 spng
42 24 11 200.0 3.0 71.217975 spng
43 17 12 200.0 3.0 65.0 spng
44 11 18 200.0 3.0 60.745370 spng
45 18 9 200.0 3.0 60.406953 spng
46 9 13 200.0 3.0 67.779053 spng
47 13 7 200.0 3.0 66.708320 spng
48 7 20 200.0 3.0 55.659680 spng
49 20 5 200.0 3.0 60.0 spng
50 5 21 200.0 3.0 61.846584 spng
51 21 3 200.0 3.0 64.031242 spng
52 3 16 200.0 3.0 63.568860 spng
53 16 1 200.0 3.0 59.774577 spng
54 1 24 200.0 3.0 65.802736 spng
55 17 10 200.0 3.0 64.845971 spng
56 10 19 200.0 3.0 58.249464 spng
57 19 8 200.0 3.0 67.268120 spng
58 8 14 200.0 3.0 67.268120 spng
59 14 6 200.0 3.0 64.629715 spng
60 6 15 200.0 3.0 50.089919 spng
61 15 4 200.0 3.0 56.320511 spng
62 4 22 200.0 3.0 60.728906 spng
63 22 2 200.0 3.0 61.032778 spng
64 2 23 200.0 3.0 66.528190 spng
65 23 12 200.0 3.0 72.277244 spng
nodes>
75 random -75 + 0 2array [ over node-vel v+ swap set-node-vel ]
curry each
;
: go ( -- ) [ model ] go* ;
MAIN: go
]]
FILE: [[springies/models/urchin/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/urchin/tags.txt]] [[demos
]]
FILE: [[springies/models/nifty/nifty.factor]] [[
USING: kernel namespaces arrays sequences threads math math.vectors
ui random springies springies.ui ;
IN: springies.models.nifty
: model ( -- )
{ } clone >nodes
{ } clone >springs
0.007 >time-slice
gravity off
1 148.581450999999987 350.573888000000011 0 -7.75 1 0.1 mass
2 168.564277000000004 351.402524000000028 0 -7.75 1 0.1 mass
3 188.54710399999999 352.231158999999991 0 -7.75 1 0.1 mass
4 208.529931000000005 353.059794000000011 0 -7.75 1 0.1 mass
5 228.512757999999991 353.888428999999974 0 -7.75 1 0.1 mass
6 248.495584000000008 354.717063999999993 0 -7.75 1 0.1 mass
7 149.410086000000007 330.591061000000025 0 -7.75 1 0.1 mass
8 150.238720999999998 310.608234999999979 0 -7.75 1 0.1 mass
9 151.06735599999999 290.625407999999993 0 -7.75 1 0.1 mass
10 151.895991000000009 270.642581000000007 0 -7.75 1 0.1 mass
11 152.724626000000001 250.65975499999999 0 -7.75 1 0.1 mass
12 172.707452999999987 251.48839000000001 0 -7.749999 1 0.1 mass
13 192.690280000000001 252.317025000000001 0 -7.75 1 0.1 mass
14 212.67310599999999 253.145659999999992 0 -7.75 1 0.1 mass
15 232.655933000000005 253.974295000000012 0 -7.75 1 0.1 mass
16 252.638759999999991 254.802930000000003 0 -7.75 1 0.1 mass
17 251.810124999999999 274.78575699999999 0 -7.75 1 0.1 mass
18 250.98148900000001 294.768583999999976 0 -7.75 1 0.1 mass
19 249.324218999999999 334.734237000000007 0 -7.75 1 0.1 mass
20 250.152853999999991 314.751410000000021 0 -7.75 1 0.1 mass
1 1 2 200 1.5 20 spng
2 2 3 200 1.5 20 spng
3 3 4 200 1.5 20 spng
4 4 5 200 1.5 20 spng
5 5 6 200 1.5 20 spng
6 6 19 200 1.5 20 spng
7 19 20 200 1.5 20 spng
8 20 18 200 1.5 20 spng
9 18 17 200 1.5 20 spng
10 17 16 200 1.5 20 spng
11 16 15 200 1.5 20 spng
12 15 14 200 1.5 20 spng
13 14 13 200 1.5 20 spng
14 13 12 200 1.5 20 spng
15 12 11 200 1.5 20 spng
16 11 10 200 1.5 20 spng
17 10 9 200 1.5 20 spng
18 9 8 200 1.5 20 spng
19 8 7 200 1.5 20 spng
20 7 1 200 1.5 20 spng
21 1 19 200 1.5 101.98039 spng
22 19 14 200 1.5 89.4427189999999968 spng
23 14 8 200 1.5 84.8528139999999951 spng
24 8 5 200 1.5 89.4427189999999968 spng
25 5 16 200 1.5 101.98039 spng
26 16 10 200 1.5 101.98039 spng
27 10 3 200 1.5 89.4427189999999968 spng
28 3 18 200 1.5 84.8528139999999951 spng
29 18 12 200 1.5 89.4427189999999968 spng
30 12 1 200 1.5 101.98039 spng
31 2 20 200 1.5 89.4427189999999968 spng
32 20 13 200 1.5 84.8528139999999951 spng
33 13 7 200 1.5 89.4427189999999968 spng
34 7 6 200 1.5 101.98039 spng
35 6 15 200 1.5 101.98039 spng
36 15 9 200 1.5 89.4427189999999968 spng
37 9 4 200 1.5 84.8528139999999951 spng
38 4 17 200 1.5 89.4427189999999968 spng
39 17 11 200 1.5 101.98039 spng
40 11 2 200 1.5 101.98039 spng
nodes> 200 random -100 + 200 random -100 + 2array [ swap set-node-vel ] curry
each ;
: go ( -- ) [ model ] go* ;
MAIN: go
]]
FILE: [[springies/models/nifty/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/models/nifty/tags.txt]] [[demos
]]
FILE: [[springies/summary.txt]] [[Mass and spring simulation (inspired by xspringies)
]]
FILE: [[springies/springies.factor]] [[
USING: kernel combinators sequences arrays math math.vectors
generalizations vars accessors math.physics.vel ;
IN: springies
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: scalar-projection ( a b -- n ) [ v. ] [ nip norm ] 2bi / ;
: vector-projection ( a b -- vec )
[ nip normalize ] [ scalar-projection ] 2bi v*n ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
VAR: nodes
VAR: springs
VAR: time-slice
VAR: world-size
: world-width ( -- width ) world-size> first ;
: world-height ( -- height ) world-size> second ;
VAR: gravity
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! node
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: node < vel mass elas force ;
C: <node> node
: node-vel ( node -- vel ) vel>> ;
: set-node-vel ( vel node -- ) swap >>vel drop ;
: pos-x ( node -- x ) pos>> first ;
: pos-y ( node -- y ) pos>> second ;
: vel-x ( node -- y ) vel>> first ;
: vel-y ( node -- y ) vel>> second ;
: >>pos-x ( node x -- node ) over pos>> set-first ;
: >>pos-y ( node y -- node ) over pos>> set-second ;
: >>vel-x ( node x -- node ) over vel>> set-first ;
: >>vel-y ( node y -- node ) over vel>> set-second ;
: apply-force ( node vec -- ) over force>> v+ >>force drop ;
: reset-force ( node -- node ) 0 0 2array >>force ;
: node-id ( id -- node ) 1- nodes> nth ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! spring
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
TUPLE: spring rest-length k damp node-a node-b ;
C: <spring> spring
: end-points ( spring -- b-pos a-pos )
[ node-b>> pos>> ] [ node-a>> pos>> ] bi ;
: spring-length ( spring -- length ) end-points v- norm ;
: stretch-length ( spring -- length )
[ spring-length ] [ rest-length>> ] bi - ;
: dir ( spring -- vec ) end-points v- normalize ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Hooke
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! F = -kx
!
! k :: spring constant
! x :: distance stretched beyond rest length
!
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: hooke-force-mag ( spring -- mag ) [ k>> ] [ stretch-length ] bi * ;
: hooke-force ( spring -- force ) [ dir ] [ hooke-force-mag ] bi v*n ;
: hooke-forces ( spring -- a b ) hooke-force dup vneg ;
: act-on-nodes-hooke ( spring -- )
[ node-a>> ] [ node-b>> ] [ ] tri hooke-forces swapd
apply-force
apply-force ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! damping
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! F = -bv
!
! b :: Damping constant
! v :: Velocity
!
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! : damping-force-a ( spring -- vec )
! [ spring-node-a node-vel ] [ spring-damp ] bi v*n vneg ;
! : damping-force-b ( spring -- vec )
! [ spring-node-b node-vel ] [ spring-damp ] bi v*n vneg ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: relative-velocity-a ( spring -- vel )
[ node-a>> vel>> ] [ node-b>> vel>> ] bi v- ;
: unit-vec-b->a ( spring -- vec )
[ node-a>> pos>> ] [ node-b>> pos>> ] bi v- ;
: relative-velocity-along-spring-a ( spring -- vel )
[ relative-velocity-a ] [ unit-vec-b->a ] bi vector-projection ;
: damping-force-a ( spring -- vec )
[ relative-velocity-along-spring-a ] [ damp>> ] bi v*n vneg ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: relative-velocity-b ( spring -- vel )
[ node-b>> vel>> ] [ node-a>> vel>> ] bi v- ;
: unit-vec-a->b ( spring -- vec )
[ node-b>> pos>> ] [ node-a>> pos>> ] bi v- ;
: relative-velocity-along-spring-b ( spring -- vel )
[ relative-velocity-b ] [ unit-vec-a->b ] bi vector-projection ;
: damping-force-b ( spring -- vec )
[ relative-velocity-along-spring-b ] [ damp>> ] bi v*n vneg ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: act-on-nodes-damping ( spring -- )
dup
[ node-a>> ] [ damping-force-a ] bi apply-force
[ node-b>> ] [ damping-force-b ] bi apply-force ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: below? ( node -- ? ) pos-y 0 < ;
: above? ( node -- ? ) pos-y world-height >= ;
: beyond-left? ( node -- ? ) pos-x 0 < ;
: beyond-right? ( node -- ? ) pos-x world-width >= ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: bounce-top ( node -- )
world-height 1- >>pos-y
dup [ vel-y ] [ elas>> ] bi * neg >>vel-y
drop ;
: bounce-bottom ( node -- )
0 >>pos-y
dup [ vel-y ] [ elas>> ] bi * neg >>vel-y
drop ;
: bounce-left ( node -- )
0 >>pos-x
dup [ vel-x ] [ elas>> ] bi * neg >>vel-x
drop ;
: bounce-right ( node -- )
world-width 1- >>pos-x
dup [ vel-x ] [ elas>> ] bi * neg >>vel-x
drop ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: handle-bounce ( node -- )
{ { [ dup above? ] [ bounce-top ] }
{ [ dup below? ] [ bounce-bottom ] }
{ [ dup beyond-left? ] [ bounce-left ] }
{ [ dup beyond-right? ] [ bounce-right ] }
{ [ t ] [ drop ] } }
cond ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: act-on-nodes ( spring -- )
dup
act-on-nodes-hooke
act-on-nodes-damping ;
! : act-on-nodes ( spring -- ) act-on-nodes-hooke ;
: loop-over-springs ( -- ) springs> [ act-on-nodes ] each ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: apply-gravity ( node -- ) { 0 -9.8 } apply-force ;
: do-gravity ( -- ) gravity> [ nodes> [ apply-gravity ] each ] when ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! F = ma
: calc-acceleration ( node -- vec ) [ force>> ] [ mass>> ] bi v/n ;
: new-vel ( node -- vel )
[ vel>> ] [ calc-acceleration time-slice> v*n ] bi v+ ;
: new-pos ( node -- pos ) [ pos>> ] [ vel>> time-slice> v*n ] bi v+ ;
: iterate-node ( node -- )
dup new-pos >>pos
dup new-vel >>vel
reset-force
handle-bounce ;
: iterate-nodes ( -- ) nodes> [ iterate-node ] each ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: iterate-system ( -- ) do-gravity loop-over-springs iterate-nodes ;
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Reading xspringies data files
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
: mass ( id x y x-vel y-vel mass elas -- )
node new
swap >>elas
swap >>mass
-rot 2array >>vel
-rot 2array >>pos
0 0 2array >>force
nodes> swap suffix >nodes
drop ;
: spng ( id id-a id-b k damp rest-length -- )
spring new
swap >>rest-length
swap >>damp
swap >>k
swap node-id >>node-b
swap node-id >>node-a
springs> swap suffix >springs
drop ;
]]
FILE: [[springies/authors.txt]] [[Eduardo Cavazos
]]
FILE: [[springies/tags.txt]] [[simulation
physics
demos]]
FILE: [[gstreamer/plugins/pbutils/pbutils.factor]] [[! Copyright (C) 2010 Anton Gorenko.
! See http://factorcode.org/license.txt for BSD license.
USING: gstreamer.pbutils.ffi ;
IN: gstreamer.pbutils
]]
FILE: [[gstreamer/plugins/pbutils/GstPbutils-0.10.gir]] [[<?xml version="1.0"?>
<!-- This file was automatically generated from C sources - DO NOT EDIT!
To affect the contents of this file, edit the original C definitions,
and/or use gtk-doc annotations. -->
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<include name="GLib" version="2.0"/>
<include name="GModule" version="2.0"/>
<include name="GObject" version="2.0"/>
<include name="Gst" version="0.10"/>
<include name="libxml2" version="2.0"/>
<package name="gstreamer-pbutils-0.10"/>
<c:include name="gst/pbutils/codec-utils.h"/>
<c:include name="gst/pbutils/descriptions.h"/>
<c:include name="gst/pbutils/encoding-profile.h"/>
<c:include name="gst/pbutils/encoding-target.h"/>
<c:include name="gst/pbutils/gstdiscoverer.h"/>
<c:include name="gst/pbutils/gstpluginsbaseversion.h"/>
<c:include name="gst/pbutils/install-plugins.h"/>
<c:include name="gst/pbutils/missing-plugins.h"/>
<c:include name="gst/pbutils/pbutils-enumtypes.h"/>
<c:include name="gst/pbutils/pbutils.h"/>
<namespace name="GstPbutils"
version="0.10"
shared-library="libgstpbutils-0.10.so.0,libgstreamer-0.10.so.0"
c:identifier-prefixes="Gst"
c:symbol-prefixes="gst">
<alias name="DiscovererAudioInfoClass"
c:type="GstDiscovererAudioInfoClass">
<type name="Gst.MiniObjectClass" c:type="GstMiniObjectClass"/>
</alias>
<alias name="DiscovererContainerInfoClass"
c:type="GstDiscovererContainerInfoClass">
<type name="Gst.MiniObjectClass" c:type="GstMiniObjectClass"/>
</alias>
<alias name="DiscovererInfoClass" c:type="GstDiscovererInfoClass">
<type name="Gst.MiniObjectClass" c:type="GstMiniObjectClass"/>
</alias>
<alias name="DiscovererStreamInfoClass"
c:type="GstDiscovererStreamInfoClass">
<type name="Gst.MiniObjectClass" c:type="GstMiniObjectClass"/>
</alias>
<alias name="DiscovererVideoInfoClass"
c:type="GstDiscovererVideoInfoClass">
<type name="Gst.MiniObjectClass" c:type="GstMiniObjectClass"/>
</alias>
<alias name="EncodingAudioProfileClass"
c:type="GstEncodingAudioProfileClass">
<type name="EncodingProfileClass" c:type="GstEncodingProfileClass"/>
</alias>
<alias name="EncodingContainerProfileClass"
c:type="GstEncodingContainerProfileClass">
<type name="EncodingProfileClass" c:type="GstEncodingProfileClass"/>
</alias>
<alias name="EncodingProfileClass" c:type="GstEncodingProfileClass">
<type name="Gst.MiniObjectClass" c:type="GstMiniObjectClass"/>
</alias>
<alias name="EncodingTargetClass" c:type="GstEncodingTargetClass">
<type name="Gst.MiniObjectClass" c:type="GstMiniObjectClass"/>
</alias>
<alias name="EncodingVideoProfileClass"
c:type="GstEncodingVideoProfileClass">
<type name="EncodingProfileClass" c:type="GstEncodingProfileClass"/>
</alias>
<class name="Discoverer"
c:symbol-prefix="discoverer"
c:type="GstDiscoverer"
version="0.10.31"
parent="GObject.Object"
glib:type-name="GstDiscoverer"
glib:get-type="gst_discoverer_get_type"
glib:type-struct="DiscovererClass">
<doc xml:whitespace="preserve">The #GstDiscoverer structure.</doc>
<constructor name="new"
c:identifier="gst_discoverer_new"
version="0.10.31"
throws="1">
<doc xml:whitespace="preserve">Creates a new #GstDiscoverer with the provided timeout.
If an error occurred when creating the discoverer, @err will be set
accordingly and %NULL will be returned. If @err is set, the caller must
free it when no longer needed using g_error_free().</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The new #GstDiscoverer.</doc>
<type name="Discoverer" c:type="GstDiscoverer*"/>
</return-value>
<parameters>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">timeout per file, in nanoseconds. Allowed are values between one second (#GST_SECOND) and one hour (3600 * #GST_SECOND)</doc>
<type name="Gst.ClockTime" c:type="GstClockTime"/>
</parameter>
</parameters>
</constructor>
<method name="discover_uri"
c:identifier="gst_discoverer_discover_uri"
version="0.10.31"
throws="1">
<doc xml:whitespace="preserve">Synchronously discovers the given @uri.
A copy of @uri will be made internally, so the caller can safely g_free()
afterwards.
error occurred.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the result of the scanning. Can be %NULL if an</doc>
<type name="DiscovererInfo" c:type="GstDiscovererInfo*"/>
</return-value>
<parameters>
<parameter name="uri" transfer-ownership="none">
<doc xml:whitespace="preserve">The URI to run on.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="discover_uri_async"
c:identifier="gst_discoverer_discover_uri_async"
version="0.10.31">
<doc xml:whitespace="preserve">Appends the given @uri to the list of URIs to discoverer. The actual
discovery of the @uri will only take place if gst_discoverer_start() has
been called.
A copy of @uri will be made internally, so the caller can safely g_free()
afterwards.
uris, else %FALSE</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the @uri was succesfully appended to the list of pending</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="uri" transfer-ownership="none">
<doc xml:whitespace="preserve">the URI to add.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="start"
c:identifier="gst_discoverer_start"
version="0.10.31">
<doc xml:whitespace="preserve">Allow asynchronous discovering of URIs to take place.
A #GMainLoop must be available for #GstDiscoverer to properly work in
asynchronous mode.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
</method>
<method name="stop" c:identifier="gst_discoverer_stop" version="0.10.31">
<doc xml:whitespace="preserve">Stop the discovery of any pending URIs and clears the list of
pending URIS (if any).</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
</method>
<property name="timeout"
writable="1"
construct="1"
transfer-ownership="none">
<type name="guint64"/>
</property>
<field name="parent">
<type name="GObject.Object" c:type="GObject"/>
</field>
<field name="priv">
<type name="DiscovererPrivate" c:type="GstDiscovererPrivate*"/>
</field>
<field name="_reserved">
<array zero-terminated="0" c:type="gpointer" fixed-size="4">
<type name="gpointer" c:type="gpointer"/>
</array>
</field>
<glib:signal name="discovered">
<doc xml:whitespace="preserve">Will be emitted when all information on a URI could be discovered.</doc>
<return-value transfer-ownership="none">
<type name="none"/>
</return-value>
<parameters>
<parameter name="object" transfer-ownership="none">
<doc xml:whitespace="preserve">the results #GstDiscovererInfo</doc>
<type name="DiscovererInfo"/>
</parameter>
<parameter name="p0" transfer-ownership="none">
<doc xml:whitespace="preserve">#GError, which will be non-NULL if an error occurred during discovery</doc>
<type name="GLib.Error"/>
</parameter>
</parameters>
</glib:signal>
<glib:signal name="finished">
<doc xml:whitespace="preserve">Will be emitted when all pending URIs have been processed.</doc>
<return-value transfer-ownership="none">
<type name="none"/>
</return-value>
</glib:signal>
<glib:signal name="starting">
<doc xml:whitespace="preserve">Will be emitted when the discover starts analyzing the pending URIs</doc>
<return-value transfer-ownership="none">
<type name="none"/>
</return-value>
</glib:signal>
</class>
<class name="DiscovererAudioInfo"
c:symbol-prefix="discoverer_audio_info"
c:type="GstDiscovererAudioInfo"
version="0.10.31"
parent="DiscovererStreamInfo"
glib:type-name="GstDiscovererAudioInfo"
glib:get-type="gst_discoverer_audio_info_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">#GstDiscovererStreamInfo specific to audio streams.</doc>
<method name="get_bitrate"
c:identifier="gst_discoverer_audio_info_get_bitrate"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the average or nominal bitrate of the stream in bits/second.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_channels"
c:identifier="gst_discoverer_audio_info_get_channels"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the number of channels in the stream.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_depth"
c:identifier="gst_discoverer_audio_info_get_depth"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the number of bits used per sample in each channel.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_max_bitrate"
c:identifier="gst_discoverer_audio_info_get_max_bitrate"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the maximum bitrate of the stream in bits/second.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_sample_rate"
c:identifier="gst_discoverer_audio_info_get_sample_rate"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the sample rate of the stream in Hertz.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
</class>
<record name="DiscovererClass"
c:type="GstDiscovererClass"
glib:is-gtype-struct-for="Discoverer">
<field name="parentclass">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
<field name="finished">
<callback name="finished">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="discoverer" transfer-ownership="none">
<type name="Discoverer" c:type="GstDiscoverer*"/>
</parameter>
</parameters>
</callback>
</field>
<field name="starting">
<callback name="starting">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="discoverer" transfer-ownership="none">
<type name="Discoverer" c:type="GstDiscoverer*"/>
</parameter>
</parameters>
</callback>
</field>
<field name="discovered">
<callback name="discovered">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="discoverer" transfer-ownership="none">
<type name="Discoverer" c:type="GstDiscoverer*"/>
</parameter>
<parameter name="info" transfer-ownership="none">
<type name="DiscovererInfo" c:type="GstDiscovererInfo*"/>
</parameter>
<parameter name="err" transfer-ownership="none">
<type name="GLib.Error" c:type="GError*"/>
</parameter>
</parameters>
</callback>
</field>
<field name="_reserved">
<array zero-terminated="0" c:type="gpointer" fixed-size="4">
<type name="gpointer" c:type="gpointer"/>
</array>
</field>
</record>
<class name="DiscovererContainerInfo"
c:symbol-prefix="discoverer_container_info"
c:type="GstDiscovererContainerInfo"
version="0.10.31"
parent="DiscovererStreamInfo"
glib:type-name="GstDiscovererContainerInfo"
glib:get-type="gst_discoverer_container_info_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">#GstDiscovererStreamInfo specific to container streams.</doc>
<method name="get_streams"
c:identifier="gst_discoverer_container_info_get_streams"
version="0.10.31"
introspectable="0">
<doc xml:whitespace="preserve">#GstDiscovererStreamInfo this container stream offers.
Free with gst_discoverer_stream_info_list_free() after usage.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the list of</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.DiscovererStreamInfo"/>
</type>
</return-value>
</method>
</class>
<class name="DiscovererInfo"
c:symbol-prefix="discoverer_info"
c:type="GstDiscovererInfo"
version="0.10.31"
parent="Gst.MiniObject"
glib:type-name="GstDiscovererInfo"
glib:get-type="gst_discoverer_info_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">Structure containing the information of a URI analyzed by #GstDiscoverer.</doc>
<method name="copy"
c:identifier="gst_discoverer_info_copy"
introspectable="0">
<return-value>
<type name="DiscovererInfo" c:type="GstDiscovererInfo*"/>
</return-value>
</method>
<method name="get_audio_streams"
c:identifier="gst_discoverer_info_get_audio_streams"
version="0.10.31"
introspectable="0">
<doc xml:whitespace="preserve">Finds all the #GstDiscovererAudioInfo contained in @info
matching #GstDiscovererStreamInfo. The caller should free it with
gst_discoverer_stream_info_list_free().</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">A #GList of</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.DiscovererStreamInfo"/>
</type>
</return-value>
</method>
<method name="get_container_streams"
c:identifier="gst_discoverer_info_get_container_streams"
version="0.10.31"
introspectable="0">
<doc xml:whitespace="preserve">Finds all the #GstDiscovererContainerInfo contained in @info
matching #GstDiscovererStreamInfo. The caller should free it with
gst_discoverer_stream_info_list_free().</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">A #GList of</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.DiscovererStreamInfo"/>
</type>
</return-value>
</method>
<method name="get_duration"
c:identifier="gst_discoverer_info_get_duration"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the duration of the URI in #GstClockTime (nanoseconds).</doc>
<type name="Gst.ClockTime" c:type="GstClockTime"/>
</return-value>
</method>
<method name="get_misc"
c:identifier="gst_discoverer_info_get_misc"
version="0.10.31">
<doc xml:whitespace="preserve">(for example: information about missing plugins). If you wish to use the
#GstStructure after the life-time of @info, you will need to copy it.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">Miscellaneous information stored as a #GstStructure</doc>
<type name="Gst.Structure" c:type="GstStructure*"/>
</return-value>
</method>
<method name="get_result"
c:identifier="gst_discoverer_info_get_result"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the result of the discovery as a #GstDiscovererResult.</doc>
<type name="DiscovererResult" c:type="GstDiscovererResult"/>
</return-value>
</method>
<method name="get_seekable"
c:identifier="gst_discoverer_info_get_seekable"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the wheter the URI is seekable.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</method>
<method name="get_stream_info"
c:identifier="gst_discoverer_info_get_stream_info"
version="0.10.31">
<doc xml:whitespace="preserve">#GstDiscovererStreamInfo.
This structure can be traversed to see the original hierarchy. Unref with
gst_discoverer_stream_info_unref() after usage.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the structure (or topology) of the URI as a</doc>
<type name="DiscovererStreamInfo" c:type="GstDiscovererStreamInfo*"/>
</return-value>
</method>
<method name="get_stream_list"
c:identifier="gst_discoverer_info_get_stream_list"
version="0.10.31"
introspectable="0">
<doc xml:whitespace="preserve">all streams contained in the #info. Free after usage
with gst_discoverer_stream_info_list_free().</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the list of</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.DiscovererStreamInfo"/>
</type>
</return-value>
</method>
<method name="get_streams"
c:identifier="gst_discoverer_info_get_streams"
version="0.10.31"
introspectable="0">
<doc xml:whitespace="preserve">Finds the #GstDiscovererStreamInfo contained in @info that match the
given @streamtype.
matching #GstDiscovererStreamInfo. The caller should free it with
gst_discoverer_stream_info_list_free().</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">A #GList of</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.DiscovererStreamInfo"/>
</type>
</return-value>
<parameters>
<parameter name="streamtype" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GType derived from #GstDiscovererStreamInfo</doc>
<type name="GType" c:type="GType"/>
</parameter>
</parameters>
</method>
<method name="get_tags"
c:identifier="gst_discoverer_info_get_tags"
version="0.10.31">
<doc xml:whitespace="preserve">the tags after the life-time of @info, you will need to copy them.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">all tags contained in the %URI. If you wish to use</doc>
<type name="Gst.TagList" c:type="GstTagList*"/>
</return-value>
</method>
<method name="get_uri"
c:identifier="gst_discoverer_info_get_uri"
version="0.10.31">
<doc xml:whitespace="preserve">Copy it if you wish to use it after the life-time of @info.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the URI to which this information corresponds to.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_video_streams"
c:identifier="gst_discoverer_info_get_video_streams"
version="0.10.31"
introspectable="0">
<doc xml:whitespace="preserve">Finds all the #GstDiscovererVideoInfo contained in @info
matching #GstDiscovererStreamInfo. The caller should free it with
gst_discoverer_stream_info_list_free().</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">A #GList of</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.DiscovererStreamInfo"/>
</type>
</return-value>
</method>
</class>
<record name="DiscovererPrivate"
c:type="GstDiscovererPrivate"
disguised="1">
</record>
<enumeration name="DiscovererResult"
version="0.10.31"
glib:type-name="GstDiscovererResult"
glib:get-type="gst_discoverer_result_get_type"
c:type="GstDiscovererResult">
<doc xml:whitespace="preserve">Result values for the discovery process.</doc>
<member name="ok"
value="0"
c:identifier="GST_DISCOVERER_OK"
glib:nick="ok"/>
<member name="uri_invalid"
value="1"
c:identifier="GST_DISCOVERER_URI_INVALID"
glib:nick="uri-invalid"/>
<member name="error"
value="2"
c:identifier="GST_DISCOVERER_ERROR"
glib:nick="error"/>
<member name="timeout"
value="3"
c:identifier="GST_DISCOVERER_TIMEOUT"
glib:nick="timeout"/>
<member name="busy"
value="4"
c:identifier="GST_DISCOVERER_BUSY"
glib:nick="busy"/>
<member name="missing_plugins"
value="5"
c:identifier="GST_DISCOVERER_MISSING_PLUGINS"
glib:nick="missing-plugins"/>
</enumeration>
<class name="DiscovererStreamInfo"
c:symbol-prefix="discoverer_stream_info"
c:type="GstDiscovererStreamInfo"
version="0.10.31"
parent="Gst.MiniObject"
glib:type-name="GstDiscovererStreamInfo"
glib:get-type="gst_discoverer_stream_info_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">Base structure for information concerning a media stream. Depending on the
stream type, one can find more media-specific information in
#GstDiscovererAudioInfo, #GstDiscovererVideoInfo, and
#GstDiscovererContainerInfo.
The #GstDiscovererStreamInfo represents the topology of the stream. Siblings
can be iterated over with gst_discoverer_stream_info_get_next() and
gst_discoverer_stream_info_get_previous(). Children (sub-streams) of a
stream can be accessed using the #GstDiscovererContainerInfo API.
As a simple example, if you run #GstDiscoverer on an AVI file with one audio
and one video stream, you will get a #GstDiscovererContainerInfo
corresponding to the AVI container, which in turn will have a
#GstDiscovererAudioInfo sub-stream and a #GstDiscovererVideoInfo sub-stream
for the audio and video streams respectively.</doc>
<function name="list_free"
c:identifier="gst_discoverer_stream_info_list_free">
<doc xml:whitespace="preserve">Decrements the reference count of all contained #GstDiscovererStreamInfo
and fress the #GList.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="infos" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GList of #GstDiscovererStreamInfo</doc>
<type name="GLib.List" c:type="GList*">
<type name="gpointer" c:type="gpointer"/>
</type>
</parameter>
</parameters>
</function>
<method name="get_caps"
c:identifier="gst_discoverer_stream_info_get_caps"
version="0.10.31">
<doc xml:whitespace="preserve">#gst_caps_unref after usage.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the #GstCaps of the stream. Unref with</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</return-value>
</method>
<method name="get_misc"
c:identifier="gst_discoverer_stream_info_get_misc"
version="0.10.31">
<doc xml:whitespace="preserve">example codec version, profile, etc..). If you wish to use the #GstStructure
after the life-time of @info you will need to copy it.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">additional information regarding the stream (for</doc>
<type name="Gst.Structure" c:type="GstStructure*"/>
</return-value>
</method>
<method name="get_next"
c:identifier="gst_discoverer_stream_info_get_next"
version="0.10.31">
<doc xml:whitespace="preserve">for final streams.
Unref with #gst_discoverer_stream_info_unref after usage.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the next #GstDiscovererStreamInfo in a chain. %NULL</doc>
<type name="DiscovererStreamInfo" c:type="GstDiscovererStreamInfo*"/>
</return-value>
</method>
<method name="get_previous"
c:identifier="gst_discoverer_stream_info_get_previous"
version="0.10.31">
<doc xml:whitespace="preserve">%NULL for starting points. Unref with #gst_discoverer_stream_info_unref
after usage.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the previous #GstDiscovererStreamInfo in a chain.</doc>
<type name="DiscovererStreamInfo" c:type="GstDiscovererStreamInfo*"/>
</return-value>
</method>
<method name="get_stream_type_nick"
c:identifier="gst_discoverer_stream_info_get_stream_type_nick"
version="0.10.31">
<doc xml:whitespace="preserve">"container",...).</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">a human readable name for the stream type of the given @info (ex : "audio",</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_tags"
c:identifier="gst_discoverer_stream_info_get_tags"
version="0.10.31">
<doc xml:whitespace="preserve">use the tags after the life-time of @info you will need to copy them.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the tags contained in this stream. If you wish to</doc>
<type name="Gst.TagList" c:type="GstTagList*"/>
</return-value>
</method>
</class>
<class name="DiscovererVideoInfo"
c:symbol-prefix="discoverer_video_info"
c:type="GstDiscovererVideoInfo"
version="0.10.31"
parent="DiscovererStreamInfo"
glib:type-name="GstDiscovererVideoInfo"
glib:get-type="gst_discoverer_video_info_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">#GstDiscovererStreamInfo specific to video streams (this includes images).</doc>
<method name="get_bitrate"
c:identifier="gst_discoverer_video_info_get_bitrate"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the average or nominal bitrate of the video stream in bits/second.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_depth"
c:identifier="gst_discoverer_video_info_get_depth"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the depth in bits of the video stream.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_framerate_denom"
c:identifier="gst_discoverer_video_info_get_framerate_denom"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the framerate of the video stream (denominator).</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_framerate_num"
c:identifier="gst_discoverer_video_info_get_framerate_num"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the framerate of the video stream (numerator).</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_height"
c:identifier="gst_discoverer_video_info_get_height"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the height of the video stream in pixels.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_max_bitrate"
c:identifier="gst_discoverer_video_info_get_max_bitrate"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the maximum bitrate of the video stream in bits/second.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_par_denom"
c:identifier="gst_discoverer_video_info_get_par_denom"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the Pixel Aspect Ratio (PAR) of the video stream (denominator).</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_par_num"
c:identifier="gst_discoverer_video_info_get_par_num"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the Pixel Aspect Ratio (PAR) of the video stream (numerator).</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_width"
c:identifier="gst_discoverer_video_info_get_width"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the width of the video stream in pixels.</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="is_image"
c:identifier="gst_discoverer_video_info_is_image"
version="0.10.31">
<doc xml:whitespace="preserve">one frame).</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#TRUE if the video stream corresponds to an image (i.e. only contains</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</method>
<method name="is_interlaced"
c:identifier="gst_discoverer_video_info_is_interlaced"
version="0.10.31">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the stream is interlaced, else %FALSE.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</method>
</class>
<constant name="ENCODING_CATEGORY_CAPTURE" value="capture">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="ENCODING_CATEGORY_DEVICE" value="device">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="ENCODING_CATEGORY_ONLINE_SERVICE" value="online-service">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="ENCODING_CATEGORY_STORAGE_EDITING" value="storage-editing">
<type name="utf8" c:type="gchar*"/>
</constant>
<class name="EncodingAudioProfile"
c:symbol-prefix="encoding_audio_profile"
c:type="GstEncodingAudioProfile"
version="0.10.32"
parent="EncodingProfile"
glib:type-name="GstEncodingAudioProfile"
glib:get-type="gst_encoding_audio_profile_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">Variant of #GstEncodingProfile for audio streams.</doc>
<constructor name="new"
c:identifier="gst_encoding_audio_profile_new"
version="0.10.32">
<doc xml:whitespace="preserve">Creates a new #GstEncodingAudioProfile
All provided allocatable arguments will be internally copied, so can be
safely freed/unreferenced after calling this method.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the newly created #GstEncodingAudioProfile.</doc>
<type name="EncodingAudioProfile" c:type="GstEncodingAudioProfile*"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="preset" transfer-ownership="none">
<doc xml:whitespace="preserve">the preset(s) to use on the encoder, can be #NULL</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="restriction" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps used to restrict the input to the encoder, can be NULL. See gst_encoding_profile_get_restriction() for more details.</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="presence" transfer-ownership="none">
<doc xml:whitespace="preserve">the number of time this stream must be used. 0 means any number of times (including never)</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</constructor>
</class>
<class name="EncodingContainerProfile"
c:symbol-prefix="encoding_container_profile"
c:type="GstEncodingContainerProfile"
version="0.10.32"
parent="EncodingProfile"
glib:type-name="GstEncodingContainerProfile"
glib:get-type="gst_encoding_container_profile_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">Encoding profiles for containers. Keeps track of a list of #GstEncodingProfile</doc>
<constructor name="new"
c:identifier="gst_encoding_container_profile_new"
version="0.10.32">
<doc xml:whitespace="preserve">Creates a new #GstEncodingContainerProfile.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The newly created #GstEncodingContainerProfile.</doc>
<type name="EncodingContainerProfile"
c:type="GstEncodingContainerProfile*"/>
</return-value>
<parameters>
<parameter name="name" transfer-ownership="none">
<doc xml:whitespace="preserve">The name of the container profile, can be %NULL</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="description" transfer-ownership="none">
<doc xml:whitespace="preserve">The description of the container profile, can be %NULL</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">The format to use for this profile</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="preset" transfer-ownership="none">
<doc xml:whitespace="preserve">The preset to use for this profile</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</constructor>
<method name="add_profile"
c:identifier="gst_encoding_container_profile_add_profile"
version="0.10.32">
<doc xml:whitespace="preserve">Add a #GstEncodingProfile to the list of profiles handled by @container.
No copy of @profile will be made, if you wish to use it elsewhere after this
method you should increment its reference count.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the @stream was properly added, else %FALSE.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="profile" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstEncodingProfile to add.</doc>
<type name="EncodingProfile" c:type="GstEncodingProfile*"/>
</parameter>
</parameters>
</method>
<method name="contains_profile"
c:identifier="gst_encoding_container_profile_contains_profile"
version="0.10.32">
<doc xml:whitespace="preserve">Checks if @container contains a #GstEncodingProfile identical to
to @profile, else %FALSE.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if @container contains a #GstEncodingProfile identical</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="profile" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstEncodingProfile</doc>
<type name="EncodingProfile" c:type="GstEncodingProfile*"/>
</parameter>
</parameters>
</method>
<method name="get_profiles"
c:identifier="gst_encoding_container_profile_get_profiles">
<return-value transfer-ownership="none">
<type name="GLib.List" c:type="GList*">
<type name="gpointer" c:type="gpointer"/>
</type>
</return-value>
</method>
</class>
<class name="EncodingProfile"
c:symbol-prefix="encoding_profile"
c:type="GstEncodingProfile"
version="0.10.32"
parent="Gst.MiniObject"
glib:type-name="GstEncodingProfile"
glib:get-type="gst_encoding_profile_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">The opaque base class object for all encoding profiles. This contains generic
information like name, description, format and preset.</doc>
<function name="find"
c:identifier="gst_encoding_profile_find"
version="0.10.32">
<doc xml:whitespace="preserve">Find the #GstEncodingProfile with the specified name and category.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The matching #GstEncodingProfile or %NULL.</doc>
<type name="EncodingProfile" c:type="GstEncodingProfile*"/>
</return-value>
<parameters>
<parameter name="targetname" transfer-ownership="none">
<doc xml:whitespace="preserve">The name of the target</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="profilename" transfer-ownership="none">
<doc xml:whitespace="preserve">The name of the profile</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="category" transfer-ownership="none" allow-none="1">
<doc xml:whitespace="preserve">The target category. Can be %NULL</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<method name="get_description"
c:identifier="gst_encoding_profile_get_description"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the description of the profile, can be %NULL.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_format"
c:identifier="gst_encoding_profile_get_format"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps corresponding to the media format used in the profile.</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</return-value>
</method>
<method name="get_input_caps"
c:identifier="gst_encoding_profile_get_input_caps"
version="0.10.32">
<doc xml:whitespace="preserve">Computes the full output caps that this @profile will be able to consume.
when you are done with the caps.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The full caps the given @profile can consume. Call gst_caps_unref()</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</return-value>
</method>
<method name="get_name"
c:identifier="gst_encoding_profile_get_name"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the name of the profile, can be %NULL.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_presence"
c:identifier="gst_encoding_profile_get_presence"
version="0.10.32">
<doc xml:whitespace="preserve">container profile. If 0, it is not a mandatory stream.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The number of times the profile is used in its parent</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_preset"
c:identifier="gst_encoding_profile_get_preset"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the name of the #GstPreset to be used in the profile.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_restriction"
c:identifier="gst_encoding_profile_get_restriction"
version="0.10.32">
<doc xml:whitespace="preserve">that will be used in the profile. The fields present in restriction caps are
properties of the raw stream (that is before encoding), such as height and
width for video and depth and sampling rate for audio. Does not apply to
#GstEncodingContainerProfile (since there is no corresponding raw stream).
Can be %NULL.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The restriction #GstCaps to apply before the encoder</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</return-value>
</method>
<method name="get_type_nick"
c:identifier="gst_encoding_profile_get_type_nick"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the human-readable name of the type of @profile.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="is_equal"
c:identifier="gst_encoding_profile_is_equal"
version="0.10.32">
<doc xml:whitespace="preserve">Checks whether the two #GstEncodingProfile are equal</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if @a and @b are equal, else %FALSE.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="b" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstEncodingProfile</doc>
<type name="EncodingProfile" c:type="GstEncodingProfile*"/>
</parameter>
</parameters>
</method>
<method name="set_description"
c:identifier="gst_encoding_profile_set_description"
version="0.10.32">
<doc xml:whitespace="preserve">Set @description as the given description for the @profile. A copy of @description will be made
internally.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="description" transfer-ownership="none">
<doc xml:whitespace="preserve">the description to set on the profile</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="set_format"
c:identifier="gst_encoding_profile_set_format"
version="0.10.32">
<doc xml:whitespace="preserve">Sets the media format used in the profile.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">the media format to use in the profile.</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</method>
<method name="set_name"
c:identifier="gst_encoding_profile_set_name"
version="0.10.32">
<doc xml:whitespace="preserve">Set @name as the given name for the @profile. A copy of @name will be made
internally.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="name" transfer-ownership="none">
<doc xml:whitespace="preserve">the name to set on the profile</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="set_presence"
c:identifier="gst_encoding_profile_set_presence"
version="0.10.32">
<doc xml:whitespace="preserve">Set the number of time the profile is used in its parent
container profile. If 0, it is not a mandatory stream</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="presence" transfer-ownership="none">
<doc xml:whitespace="preserve">the number of time the profile can be used</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</method>
<method name="set_preset"
c:identifier="gst_encoding_profile_set_preset"
version="0.10.32">
<doc xml:whitespace="preserve">Sets the preset to use for the profile.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="preset" transfer-ownership="none">
<doc xml:whitespace="preserve">the element preset to use</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="set_restriction"
c:identifier="gst_encoding_profile_set_restriction"
version="0.10.32">
<doc xml:whitespace="preserve">Set the restriction #GstCaps to apply before the encoder
that will be used in the profile. See gst_encoding_profile_set_restriction()
for more about restrictions. Does not apply to #GstEncodingContainerProfile.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="restriction" transfer-ownership="none">
<doc xml:whitespace="preserve">the restriction to apply</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</method>
</class>
<class name="EncodingTarget"
c:symbol-prefix="encoding_target"
c:type="GstEncodingTarget"
version="0.10.32"
parent="Gst.MiniObject"
glib:type-name="GstEncodingTarget"
glib:get-type="gst_encoding_target_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">Collection of #GstEncodingProfile for a specific target or use-case.
When being stored/loaded, targets come from a specific category, like
#GST_ENCODING_CATEGORY_DEVICE.</doc>
<constructor name="new"
c:identifier="gst_encoding_target_new"
version="0.10.32"
introspectable="0">
<doc xml:whitespace="preserve">Creates a new #GstEncodingTarget.
The name and category can only consist of lowercase ASCII letters for the
first character, followed by either lowercase ASCII letters, digits or
hyphens ('-').
The @category &lt;emphasis&gt;should&lt;/emphasis&gt; be one of the existing
well-defined categories, like #GST_ENCODING_CATEGORY_DEVICE, but it
&lt;emphasis&gt;can&lt;/emphasis&gt; be a application or user specific category if
needed.
there was an error.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The newly created #GstEncodingTarget or %NULL if</doc>
<type name="EncodingTarget" c:type="GstEncodingTarget*"/>
</return-value>
<parameters>
<parameter name="name" transfer-ownership="none">
<doc xml:whitespace="preserve">The name of the target.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="category" transfer-ownership="none">
<doc xml:whitespace="preserve">The name of the category to which this @target belongs. For example: #GST_ENCODING_CATEGORY_DEVICE.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="description" transfer-ownership="none">
<doc xml:whitespace="preserve">A description of #GstEncodingTarget in the current locale.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="profiles" transfer-ownership="none">
<doc xml:whitespace="preserve">A #GList of #GstEncodingProfile.</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.EncodingProfile"/>
</type>
</parameter>
</parameters>
</constructor>
<function name="load"
c:identifier="gst_encoding_target_load"
version="0.10.32"
throws="1">
<doc xml:whitespace="preserve">Searches for the #GstEncodingTarget with the given name, loads it
and returns it.
If the category name is specified only targets from that category will be
searched for.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The #GstEncodingTarget if available, else %NULL.</doc>
<type name="EncodingTarget" c:type="GstEncodingTarget*"/>
</return-value>
<parameters>
<parameter name="name" transfer-ownership="none">
<doc xml:whitespace="preserve">the name of the #GstEncodingTarget to load.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="category" transfer-ownership="none" allow-none="1">
<doc xml:whitespace="preserve">the name of the target category, like #GST_ENCODING_CATEGORY_DEVICE. Can be %NULL</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="load_from_file"
c:identifier="gst_encoding_target_load_from_file"
version="0.10.32"
throws="1">
<doc xml:whitespace="preserve">Opens the provided file and returns the contained #GstEncodingTarget.
%NULL</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The #GstEncodingTarget contained in the file, else</doc>
<type name="EncodingTarget" c:type="GstEncodingTarget*"/>
</return-value>
<parameters>
<parameter name="filepath" transfer-ownership="none">
<doc xml:whitespace="preserve">The file location to load the #GstEncodingTarget from</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<method name="add_profile"
c:identifier="gst_encoding_target_add_profile"
version="0.10.32">
<doc xml:whitespace="preserve">Adds the given @profile to the @target. Each added profile must have
a unique name within the profile.
The @target will steal a reference to the @profile. If you wish to use
the profile after calling this method, you should increase its reference
count.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the profile was added, else %FALSE.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="profile" transfer-ownership="full">
<doc xml:whitespace="preserve">the #GstEncodingProfile to add</doc>
<type name="EncodingProfile" c:type="GstEncodingProfile*"/>
</parameter>
</parameters>
</method>
<method name="get_category"
c:identifier="gst_encoding_target_get_category"
version="0.10.32">
<doc xml:whitespace="preserve">#GST_ENCODING_CATEGORY_DEVICE.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The category of the @target. For example:</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_description"
c:identifier="gst_encoding_target_get_description"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The description of the @target.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_name"
c:identifier="gst_encoding_target_get_name"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The name of the @target.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_profile"
c:identifier="gst_encoding_target_get_profile"
version="0.10.32">
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The matching #GstEncodingProfile, or %NULL.</doc>
<type name="EncodingProfile" c:type="GstEncodingProfile*"/>
</return-value>
<parameters>
<parameter name="name" transfer-ownership="none">
<doc xml:whitespace="preserve">the name of the profile to retrieve</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="get_profiles"
c:identifier="gst_encoding_target_get_profiles"
version="0.10.32"
introspectable="0">
<doc xml:whitespace="preserve">#GstEncodingProfile(s) this @target handles.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">A list of</doc>
<type name="GLib.List" c:type="GList*">
<type name="Gst.EncodingProfile"/>
</type>
</return-value>
</method>
<method name="save"
c:identifier="gst_encoding_target_save"
version="0.10.32"
throws="1">
<doc xml:whitespace="preserve">Saves the @target to a default user-local directory.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the target was correctly saved, else %FALSE.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</method>
<method name="save_to_file"
c:identifier="gst_encoding_target_save_to_file"
version="0.10.32"
throws="1">
<doc xml:whitespace="preserve">Saves the @target to the provided file location.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the target was correctly saved, else %FALSE.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="filepath" transfer-ownership="none">
<doc xml:whitespace="preserve">the location to store the @target at.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
</class>
<class name="EncodingVideoProfile"
c:symbol-prefix="encoding_video_profile"
c:type="GstEncodingVideoProfile"
version="0.10.32"
parent="EncodingProfile"
glib:type-name="GstEncodingVideoProfile"
glib:get-type="gst_encoding_video_profile_get_type"
glib:fundamental="1">
<doc xml:whitespace="preserve">Variant of #GstEncodingProfile for video streams, allows specifying the @pass.</doc>
<constructor name="new"
c:identifier="gst_encoding_video_profile_new"
version="0.10.32">
<doc xml:whitespace="preserve">Creates a new #GstEncodingVideoProfile
All provided allocatable arguments will be internally copied, so can be
safely freed/unreferenced after calling this method.
If you wish to control the pass number (in case of multi-pass scenarios),
please refer to the gst_encoding_video_profile_set_pass() documentation.
If you wish to use/force a constant framerate please refer to the
gst_encoding_video_profile_set_variableframerate() documentation.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">the newly created #GstEncodingVideoProfile.</doc>
<type name="EncodingVideoProfile" c:type="GstEncodingVideoProfile*"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="preset" transfer-ownership="none">
<doc xml:whitespace="preserve">the preset(s) to use on the encoder, can be #NULL</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="restriction" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps used to restrict the input to the encoder, can be NULL. See gst_encoding_profile_get_restriction() for more details.</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="presence" transfer-ownership="none">
<doc xml:whitespace="preserve">the number of time this stream must be used. 0 means any number of times (including never)</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</constructor>
<method name="get_pass"
c:identifier="gst_encoding_video_profile_get_pass"
version="0.10.32">
<doc xml:whitespace="preserve">1 for multi-pass. 0 if this is not a multi-pass profile</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The pass number if this is part of a multi-pass profile. Starts at</doc>
<type name="guint" c:type="guint"/>
</return-value>
</method>
<method name="get_variableframerate"
c:identifier="gst_encoding_video_profile_get_variableframerate"
version="0.10.32">
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">Whether non-constant video framerate is allowed for encoding.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</method>
<method name="set_pass"
c:identifier="gst_encoding_video_profile_set_pass"
version="0.10.32">
<doc xml:whitespace="preserve">Sets the pass number of this video profile. The first pass profile should have
this value set to 1. If this video profile isn't part of a multi-pass profile,
you may set it to 0 (the default value).</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="pass" transfer-ownership="none">
<doc xml:whitespace="preserve">the pass number for this profile</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</method>
<method name="set_variableframerate"
c:identifier="gst_encoding_video_profile_set_variableframerate"
version="0.10.32">
<doc xml:whitespace="preserve">If set to %TRUE, then the incoming streamm will be allowed to have non-constant
framerate. If set to %FALSE (default value), then the incoming stream will
be normalized by dropping/duplicating frames in order to produce a
constance framerate.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="variableframerate" transfer-ownership="none">
<doc xml:whitespace="preserve">a boolean</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
</method>
</class>
<record name="InstallPluginsContext"
c:type="GstInstallPluginsContext"
version="0.10.12"
glib:type-name="GstInstallPluginsContext"
glib:get-type="gst_install_plugins_context_get_type"
c:symbol-prefix="install_plugins_context">
<doc xml:whitespace="preserve">Opaque context structure for the plugin installation. Use the provided
API to set details on it.</doc>
<constructor name="new"
c:identifier="gst_install_plugins_context_new"
version="0.10.12">
<doc xml:whitespace="preserve">Creates a new #GstInstallPluginsContext.
gst_install_plugins_context_free() when no longer needed</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstInstallPluginsContext. Free with</doc>
<type name="InstallPluginsContext"
c:type="GstInstallPluginsContext*"/>
</return-value>
</constructor>
<method name="free"
c:identifier="gst_install_plugins_context_free"
version="0.10.12">
<doc xml:whitespace="preserve">Frees a #GstInstallPluginsContext.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
</method>
<method name="set_xid"
c:identifier="gst_install_plugins_context_set_xid"
version="0.10.12">
<doc xml:whitespace="preserve">This function is for X11-based applications (such as most Gtk/Qt
applications on linux/unix) only. You can use it to tell the external
installer the XID of your main application window. That way the installer
can make its own window transient to your application window during the
installation.
If set, the XID will be passed to the installer via a --transient-for=XID
command line option.
Gtk+/Gnome application should be able to obtain the XID of the top-level
window like this:
&lt;programlisting&gt;
##include &amp;lt;gtk/gtk.h&amp;gt;
##ifdef GDK_WINDOWING_X11
##include &amp;lt;gdk/gdkx.h&amp;gt;
##endif
...
##ifdef GDK_WINDOWING_X11
xid = GDK_WINDOW_XWINDOW (GTK_WIDGET (application_window)-&amp;gt;window);
##endif
...
&lt;/programlisting&gt;</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="xid" transfer-ownership="none">
<doc xml:whitespace="preserve">the XWindow ID (XID) of the top-level application</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</method>
</record>
<callback name="InstallPluginsResultFunc"
c:type="GstInstallPluginsResultFunc"
version="0.10.12">
<doc xml:whitespace="preserve">The prototype of the callback function that will be called once the
external plugin installer program has returned. You only need to provide
a callback function if you are using the asynchronous interface.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="result" transfer-ownership="none">
<doc xml:whitespace="preserve">whether the installation of the requested plugins succeeded or not</doc>
<type name="InstallPluginsReturn" c:type="GstInstallPluginsReturn"/>
</parameter>
<parameter name="user_data" transfer-ownership="none" closure="1">
<doc xml:whitespace="preserve">the user data passed to gst_install_plugins_async()</doc>
<type name="gpointer" c:type="gpointer"/>
</parameter>
</parameters>
</callback>
<enumeration name="InstallPluginsReturn"
version="0.10.12"
glib:type-name="GstInstallPluginsReturn"
glib:get-type="gst_install_plugins_return_get_type"
c:type="GstInstallPluginsReturn">
<doc xml:whitespace="preserve">Result codes returned by gst_install_plugins_async() and
gst_install_plugins_sync(), and also the result code passed to the
#GstInstallPluginsResultFunc specified with gst_install_plugin_async().
These codes indicate success or failure of starting an external installer
program and to what extent the requested plugins could be installed.</doc>
<member name="success"
value="0"
c:identifier="GST_INSTALL_PLUGINS_SUCCESS"
glib:nick="success"/>
<member name="not_found"
value="1"
c:identifier="GST_INSTALL_PLUGINS_NOT_FOUND"
glib:nick="not-found"/>
<member name="error"
value="2"
c:identifier="GST_INSTALL_PLUGINS_ERROR"
glib:nick="error"/>
<member name="partial_success"
value="3"
c:identifier="GST_INSTALL_PLUGINS_PARTIAL_SUCCESS"
glib:nick="partial-success"/>
<member name="user_abort"
value="4"
c:identifier="GST_INSTALL_PLUGINS_USER_ABORT"
glib:nick="user-abort"/>
<member name="crashed"
value="100"
c:identifier="GST_INSTALL_PLUGINS_CRASHED"
glib:nick="crashed"/>
<member name="invalid"
value="101"
c:identifier="GST_INSTALL_PLUGINS_INVALID"
glib:nick="invalid"/>
<member name="started_ok"
value="200"
c:identifier="GST_INSTALL_PLUGINS_STARTED_OK"
glib:nick="started-ok"/>
<member name="internal_failure"
value="201"
c:identifier="GST_INSTALL_PLUGINS_INTERNAL_FAILURE"
glib:nick="internal-failure"/>
<member name="helper_missing"
value="202"
c:identifier="GST_INSTALL_PLUGINS_HELPER_MISSING"
glib:nick="helper-missing"/>
<member name="install_in_progress"
value="203"
c:identifier="GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS"
glib:nick="install-in-progress"/>
</enumeration>
<constant name="PLUGINS_BASE_VERSION_MAJOR" value="0">
<type name="gint" c:type="gint"/>
</constant>
<constant name="PLUGINS_BASE_VERSION_MICRO" value="32">
<type name="gint" c:type="gint"/>
</constant>
<constant name="PLUGINS_BASE_VERSION_MINOR" value="10">
<type name="gint" c:type="gint"/>
</constant>
<constant name="PLUGINS_BASE_VERSION_NANO" value="0">
<type name="gint" c:type="gint"/>
</constant>
<function name="codec_utils_aac_caps_set_level_and_profile"
c:identifier="gst_codec_utils_aac_caps_set_level_and_profile"
version="0.10.31">
<doc xml:whitespace="preserve">Sets the level and profile on @caps if it can be determined from
gst_codec_utils_aac_get_profile() for more details on the parameters.
If mpegversion is 4, the "base-profile" field is also set in @caps.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the level and profile could be set, %FALSE otherwise.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps to which level and profile fields are to be added</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="audio_config" transfer-ownership="none">
<doc xml:whitespace="preserve">a pointer to the AudioSpecificConfig as specified in the Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see below for a more details).</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of @audio_config in bytes</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_aac_get_level"
c:identifier="gst_codec_utils_aac_get_level"
version="0.10.31">
<doc xml:whitespace="preserve">Determines the level of a stream as defined in ISO/IEC 14496-3. For AAC LC
streams, the constraints from the AAC audio profile are applied. For AAC
Main, LTP, SSR and others, the Main profile is used.
The @audio_config parameter follows the following format, starting from the
most significant bit of the first byte:
&lt;itemizedlist&gt;
&lt;listitem&gt;&lt;para&gt;
Bit 0:4 contains the AudioObjectType
&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;
Bit 5:8 contains the sample frequency index (if this is 0xf, then the
next 24 bits define the actual sample frequency, and subsequent
fields are appropriately shifted).
&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;
Bit 9:12 contains the channel configuration
&lt;/para&gt;&lt;/listitem&gt;
&lt;/itemizedlist&gt;
&lt;note&gt;
HE-AAC support has not yet been implemented.
&lt;/note&gt;
determined.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The level as a const string and %NULL if the level could not be</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="audio_config" transfer-ownership="none">
<doc xml:whitespace="preserve">a pointer to the AudioSpecificConfig as specified in the Elementary Stream Descriptor (esds) in ISO/IEC 14496-1.</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of @audio_config in bytes</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_aac_get_profile"
c:identifier="gst_codec_utils_aac_get_profile"
version="0.10.31">
<doc xml:whitespace="preserve">Returns the profile of the given AAC stream as a string. The profile is
determined using the AudioObjectType field which is in the first 5 bits of
&lt;note&gt;
HE-AAC support has not yet been implemented.
&lt;/note&gt;
determined.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The profile as a const string and %NULL if the profile could not be</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="audio_config" transfer-ownership="none">
<doc xml:whitespace="preserve">a pointer to the AudioSpecificConfig as specified in the Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see gst_codec_utils_aac_get_level() for a more details).</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of @audio_config in bytes</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_aac_get_sample_rate_from_index"
c:identifier="gst_codec_utils_aac_get_sample_rate_from_index"
version="0.10.31">
<doc xml:whitespace="preserve">Translates the sample rate index found in AAC headers to the actual sample
rate.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The sample rate if @sr_idx is valid, 0 otherwise.</doc>
<type name="guint" c:type="guint"/>
</return-value>
<parameters>
<parameter name="sr_idx" transfer-ownership="none">
<doc xml:whitespace="preserve">Sample rate index as from the AudioSpecificConfig (MPEG-4 container) or ADTS frame header</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_h264_caps_set_level_and_profile"
c:identifier="gst_codec_utils_h264_caps_set_level_and_profile"
version="0.10.31">
<doc xml:whitespace="preserve">Sets the level and profile in @caps if it can be determined from @sps. See
gst_codec_utils_h264_get_level() and gst_codec_utils_h264_get_profile()
for more details on the parameters.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the level and profile could be set, %FALSE otherwise.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps to which the level and profile are to be added</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="sps" transfer-ownership="none">
<doc xml:whitespace="preserve">Pointer to the sequence parameter set for the stream.</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of the data available in @sps.</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_h264_get_level"
c:identifier="gst_codec_utils_h264_get_level"
version="0.10.31">
<doc xml:whitespace="preserve">Converts the level indication (level_idc) in the stream's
sequence parameter set into a string. The SPS is expected to have the
same format as for gst_codec_utils_h264_get_profile().</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The level as a const string, or %NULL if there is an error.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="sps" transfer-ownership="none">
<doc xml:whitespace="preserve">Pointer to the sequence parameter set for the stream.</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of the data available in @sps.</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_h264_get_profile"
c:identifier="gst_codec_utils_h264_get_profile"
version="0.10.31">
<doc xml:whitespace="preserve">Converts the profile indication (profile_idc) in the stream's
sequence parameter set into a string. The SPS is expected to have the
following format, as defined in the H.264 specification. The SPS is viewed
as a bitstream here, with bit 0 being the most significant bit of the first
byte.
&lt;itemizedlist&gt;
&lt;listitem&gt;&lt;para&gt;Bit 0:7 - Profile indication&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;Bit 8 - constraint_set0_flag&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;Bit 9 - constraint_set1_flag&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;Bit 10 - constraint_set2_flag&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;Bit 11 - constraint_set3_flag&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;Bit 12 - constraint_set3_flag&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;Bit 13:15 - Reserved&lt;/para&gt;&lt;/listitem&gt;
&lt;listitem&gt;&lt;para&gt;Bit 16:24 - Level indication&lt;/para&gt;&lt;/listitem&gt;
&lt;/itemizedlist&gt;</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The profile as a const string, or %NULL if there is an error.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="sps" transfer-ownership="none">
<doc xml:whitespace="preserve">Pointer to the sequence parameter set for the stream.</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of the data available in @sps.</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_mpeg4video_caps_set_level_and_profile"
c:identifier="gst_codec_utils_mpeg4video_caps_set_level_and_profile"
version="0.10.31">
<doc xml:whitespace="preserve">Sets the level and profile in @caps if it can be determined from
gst_codec_utils_mpeg4video_get_profile() for more details on the
parameters.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the level and profile could be set, %FALSE otherwise.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps to which the level and profile are to be added</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="vis_obj_seq" transfer-ownership="none">
<doc xml:whitespace="preserve">Pointer to the visual object sequence for the stream.</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of the data available in @sps.</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_mpeg4video_get_level"
c:identifier="gst_codec_utils_mpeg4video_get_level"
version="0.10.31">
<doc xml:whitespace="preserve">Converts the level indication in the stream's visual object sequence into
a string. @vis_obj_seq is expected to be the data following the visual
object sequence start code. Only the first byte
(profile_and_level_indication) is used.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The level as a const string, or NULL if there is an error.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="vis_obj_seq" transfer-ownership="none">
<doc xml:whitespace="preserve">Pointer to the visual object sequence for the stream.</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of the data available in @sps.</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="codec_utils_mpeg4video_get_profile"
c:identifier="gst_codec_utils_mpeg4video_get_profile"
version="0.10.31">
<doc xml:whitespace="preserve">Converts the profile indication in the stream's visual object sequence into
a string. @vis_obj_seq is expected to be the data following the visual
object sequence start code. Only the first byte
(profile_and_level_indication) is used.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The profile as a const string, or NULL if there is an error.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="vis_obj_seq" transfer-ownership="none">
<doc xml:whitespace="preserve">Pointer to the visual object sequence for the stream.</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="len" transfer-ownership="none">
<doc xml:whitespace="preserve">Length of the data available in @sps.</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="encoding_list_all_targets"
c:identifier="gst_encoding_list_all_targets"
version="0.10.32">
<doc xml:whitespace="preserve">List all available #GstEncodingTarget for the specified category, or all categories
if @categoryname is %NULL.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The list of #GstEncodingTarget</doc>
<type name="GLib.List" c:type="GList*">
<type name="EncodingTarget"/>
</type>
</return-value>
<parameters>
<parameter name="categoryname"
transfer-ownership="none"
allow-none="1">
<doc xml:whitespace="preserve">The category, for ex: #GST_ENCODING_CATEGORY_DEVICE. Can be %NULL.</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="encoding_list_available_categories"
c:identifier="gst_encoding_list_available_categories"
version="0.10.32">
<doc xml:whitespace="preserve">Lists all #GstEncodingTarget categories present on disk.
of #GstEncodingTarget categories.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">A list</doc>
<type name="GLib.List" c:type="GList*">
<type name="utf8"/>
</type>
</return-value>
</function>
<function name="install_plugins_async"
c:identifier="gst_install_plugins_async"
version="0.10.12">
<doc xml:whitespace="preserve">Requests plugin installation without blocking. Once the plugins have been
installed or installation has failed, @func will be called with the result
of the installation and your provided @user_data pointer.
This function requires a running GLib/Gtk main loop. If you are not
running a GLib/Gtk main loop, make sure to regularly call
g_main_context_iteration(NULL,FALSE).
The installer strings that make up @detail are typically obtained by
calling gst_missing_plugin_message_get_installer_detail() on missing-plugin
messages that have been caught on a pipeline's bus or created by the
application via the provided API, such as gst_missing_element_message_new().
It is possible to request the installation of multiple missing plugins in
one go (as might be required if there is a demuxer for a certain format
installed but no suitable video decoder and no suitable audio decoder).</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">result code whether an external installer could be started</doc>
<type name="InstallPluginsReturn" c:type="GstInstallPluginsReturn"/>
</return-value>
<parameters>
<parameter name="details" transfer-ownership="none">
<doc xml:whitespace="preserve">NULL-terminated array of installer string details (see below)</doc>
<type name="utf8" c:type="gchar**"/>
</parameter>
<parameter name="ctx" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstInstallPluginsContext, or NULL</doc>
<type name="InstallPluginsContext"
c:type="GstInstallPluginsContext*"/>
</parameter>
<parameter name="func"
transfer-ownership="none"
scope="async"
closure="3">
<doc xml:whitespace="preserve">the function to call when the installer program returns</doc>
<type name="InstallPluginsResultFunc"
c:type="GstInstallPluginsResultFunc"/>
</parameter>
<parameter name="user_data" transfer-ownership="none">
<doc xml:whitespace="preserve">the user data to pass to @func when called, or NULL</doc>
<type name="gpointer" c:type="gpointer"/>
</parameter>
</parameters>
</function>
<function name="install_plugins_installation_in_progress"
c:identifier="gst_install_plugins_installation_in_progress"
version="0.10.12">
<doc xml:whitespace="preserve">Checks whether plugin installation (initiated by this application only)
is currently in progress.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if plugin installation is in progress, otherwise FALSE</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</function>
<function name="install_plugins_return_get_name"
c:identifier="gst_install_plugins_return_get_name"
version="0.10.12">
<doc xml:whitespace="preserve">Convenience function to return the descriptive string associated
with a status code. This function returns English strings and
should not be used for user messages. It is here only to assist
in debugging.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">a descriptive string for the status code in @ret</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="ret" transfer-ownership="none">
<doc xml:whitespace="preserve">the return status code</doc>
<type name="InstallPluginsReturn" c:type="GstInstallPluginsReturn"/>
</parameter>
</parameters>
</function>
<function name="install_plugins_supported"
c:identifier="gst_install_plugins_supported"
version="0.10.15">
<doc xml:whitespace="preserve">Checks whether plugin installation is likely to be supported by the
current environment. This currently only checks whether the helper script
that is to be provided by the distribution or operating system vendor
exists.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if plugin installation is likely to be supported.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</function>
<function name="install_plugins_sync"
c:identifier="gst_install_plugins_sync"
version="0.10.12">
<doc xml:whitespace="preserve">Requests plugin installation and block until the plugins have been
installed or installation has failed.
This function should almost never be used, it only exists for cases where
a non-GLib main loop is running and the user wants to run it in a separate
thread and marshal the result back asynchronously into the main thread
using the other non-GLib main loop. You should almost always use
gst_install_plugins_async() instead of this function.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the result of the installation.</doc>
<type name="InstallPluginsReturn" c:type="GstInstallPluginsReturn"/>
</return-value>
<parameters>
<parameter name="details" transfer-ownership="none">
<doc xml:whitespace="preserve">NULL-terminated array of installer string details</doc>
<type name="utf8" c:type="gchar**"/>
</parameter>
<parameter name="ctx" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstInstallPluginsContext, or NULL</doc>
<type name="InstallPluginsContext"
c:type="GstInstallPluginsContext*"/>
</parameter>
</parameters>
</function>
<function name="is_missing_plugin_message"
c:identifier="gst_is_missing_plugin_message">
<doc xml:whitespace="preserve">Checks whether @msg is a missing plugins message.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if @msg is a missing-plugins message, otherwise %FALSE.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="msg" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstMessage</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</parameter>
</parameters>
</function>
<function name="missing_decoder_installer_detail_new"
c:identifier="gst_missing_decoder_installer_detail_new"
version="0.10.15">
<doc xml:whitespace="preserve">Returns an opaque string containing all the details about the missing
element to be passed to an external installer called via
gst_install_plugins_async() or gst_install_plugins_sync().
This function is mainly for applications that call external plugin
installation mechanisms using one of the two above-mentioned functions in
the case where the application knows exactly what kind of plugin it is
missing.
with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated detail string, or NULL on error. Free string</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="decode_caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) caps for which a decoder element is needed</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="missing_decoder_message_new"
c:identifier="gst_missing_decoder_message_new">
<doc xml:whitespace="preserve">Creates a missing-plugin message for @element to notify the application
that a decoder element for a particular set of (fixed) caps is missing.
This function is mainly for use in plugins.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstMessage, or NULL on error</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</return-value>
<parameters>
<parameter name="element" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstElement posting the message</doc>
<type name="Gst.Element" c:type="GstElement*"/>
</parameter>
<parameter name="decode_caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) caps for which a decoder element is needed</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="missing_element_installer_detail_new"
c:identifier="gst_missing_element_installer_detail_new"
version="0.10.15">
<doc xml:whitespace="preserve">Returns an opaque string containing all the details about the missing
element to be passed to an external installer called via
gst_install_plugins_async() or gst_install_plugins_sync().
This function is mainly for applications that call external plugin
installation mechanisms using one of the two above-mentioned functions in
the case where the application knows exactly what kind of plugin it is
missing.
with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated detail string, or NULL on error. Free string</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="factory_name" transfer-ownership="none">
<doc xml:whitespace="preserve">the name of the missing element (element factory), e.g. "videoscale" or "cdparanoiasrc"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="missing_element_message_new"
c:identifier="gst_missing_element_message_new">
<doc xml:whitespace="preserve">Creates a missing-plugin message for @element to notify the application
that a certain required element is missing. This function is mainly for
use in plugins.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstMessage, or NULL on error</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</return-value>
<parameters>
<parameter name="element" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstElement posting the message</doc>
<type name="Gst.Element" c:type="GstElement*"/>
</parameter>
<parameter name="factory_name" transfer-ownership="none">
<doc xml:whitespace="preserve">the name of the missing element (element factory), e.g. "videoscale" or "cdparanoiasrc"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="missing_encoder_installer_detail_new"
c:identifier="gst_missing_encoder_installer_detail_new"
version="0.10.15">
<doc xml:whitespace="preserve">Returns an opaque string containing all the details about the missing
element to be passed to an external installer called via
gst_install_plugins_async() or gst_install_plugins_sync().
This function is mainly for applications that call external plugin
installation mechanisms using one of the two above-mentioned functions in
the case where the application knows exactly what kind of plugin it is
missing.
with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated detail string, or NULL on error. Free string</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="encode_caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) caps for which an encoder element is needed</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="missing_encoder_message_new"
c:identifier="gst_missing_encoder_message_new">
<doc xml:whitespace="preserve">Creates a missing-plugin message for @element to notify the application
that an encoder element for a particular set of (fixed) caps is missing.
This function is mainly for use in plugins.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstMessage, or NULL on error</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</return-value>
<parameters>
<parameter name="element" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstElement posting the message</doc>
<type name="Gst.Element" c:type="GstElement*"/>
</parameter>
<parameter name="encode_caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) caps for which an encoder element is needed</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="missing_plugin_message_get_description"
c:identifier="gst_missing_plugin_message_get_description">
<doc xml:whitespace="preserve">Returns a localised string describing the missing feature, for use in
error dialogs and the like. Should never return NULL unless @msg is not
a valid missing-plugin message.
This function is mainly for applications that need a human-readable string
describing a missing plugin, given a previously collected missing-plugin
message
string with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated description string, or NULL on error. Free</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="msg" transfer-ownership="none">
<doc xml:whitespace="preserve">a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</parameter>
</parameters>
</function>
<function name="missing_plugin_message_get_installer_detail"
c:identifier="gst_missing_plugin_message_get_installer_detail">
<doc xml:whitespace="preserve">Returns an opaque string containing all the details about the missing
element to be passed to an external installer called via
gst_install_plugins_async() or gst_install_plugins_sync().
This function is mainly for applications that call external plugin
installation mechanisms using one of the two above-mentioned functions.
with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated detail string, or NULL on error. Free string</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="msg" transfer-ownership="none">
<doc xml:whitespace="preserve">a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</parameter>
</parameters>
</function>
<function name="missing_uri_sink_installer_detail_new"
c:identifier="gst_missing_uri_sink_installer_detail_new"
version="0.10.15">
<doc xml:whitespace="preserve">Returns an opaque string containing all the details about the missing
element to be passed to an external installer called via
gst_install_plugins_async() or gst_install_plugins_sync().
This function is mainly for applications that call external plugin
installation mechanisms using one of the two above-mentioned functions in
the case where the application knows exactly what kind of plugin it is
missing.
with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated detail string, or NULL on error. Free string</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="protocol" transfer-ownership="none">
<doc xml:whitespace="preserve">the URI protocol the missing source needs to implement, e.g. "http" or "mms"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="missing_uri_sink_message_new"
c:identifier="gst_missing_uri_sink_message_new">
<doc xml:whitespace="preserve">Creates a missing-plugin message for @element to notify the application
that a sink element for a particular URI protocol is missing. This
function is mainly for use in plugins.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstMessage, or NULL on error</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</return-value>
<parameters>
<parameter name="element" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstElement posting the message</doc>
<type name="Gst.Element" c:type="GstElement*"/>
</parameter>
<parameter name="protocol" transfer-ownership="none">
<doc xml:whitespace="preserve">the URI protocol the missing sink needs to implement, e.g. "http" or "smb"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="missing_uri_source_installer_detail_new"
c:identifier="gst_missing_uri_source_installer_detail_new"
version="0.10.15">
<doc xml:whitespace="preserve">Returns an opaque string containing all the details about the missing
element to be passed to an external installer called via
gst_install_plugins_async() or gst_install_plugins_sync().
This function is mainly for applications that call external plugin
installation mechanisms using one of the two above-mentioned functions in
the case where the application knows exactly what kind of plugin it is
missing.
with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated detail string, or NULL on error. Free string</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="protocol" transfer-ownership="none">
<doc xml:whitespace="preserve">the URI protocol the missing source needs to implement, e.g. "http" or "mms"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="missing_uri_source_message_new"
c:identifier="gst_missing_uri_source_message_new">
<doc xml:whitespace="preserve">Creates a missing-plugin message for @element to notify the application
that a source element for a particular URI protocol is missing. This
function is mainly for use in plugins.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstMessage, or NULL on error</doc>
<type name="Gst.Message" c:type="GstMessage*"/>
</return-value>
<parameters>
<parameter name="element" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstElement posting the message</doc>
<type name="Gst.Element" c:type="GstElement*"/>
</parameter>
<parameter name="protocol" transfer-ownership="none">
<doc xml:whitespace="preserve">the URI protocol the missing source needs to implement, e.g. "http" or "mms"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_add_codec_description_to_tag_list"
c:identifier="gst_pb_utils_add_codec_description_to_tag_list">
<doc xml:whitespace="preserve">Adds a codec tag describing the format specified by @caps to @taglist.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if a codec tag was added, FALSE otherwise.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="taglist" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstTagList</doc>
<type name="Gst.TagList" c:type="GstTagList*"/>
</parameter>
<parameter name="codec_tag" transfer-ownership="none">
<doc xml:whitespace="preserve">a GStreamer codec tag such as #GST_TAG_AUDIO_CODEC, #GST_TAG_VIDEO_CODEC or #GST_TAG_CODEC</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) #GstCaps for which a codec tag should be added.</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_get_codec_description"
c:identifier="gst_pb_utils_get_codec_description">
<doc xml:whitespace="preserve">Returns a localised (as far as this is possible) string describing the
media format specified in @caps, for use in error dialogs or other messages
to be seen by the user. Should never return NULL unless @caps is invalid.
Also see the convenience function
gst_pb_utils_add_codec_description_to_tag_list().
string with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated description string, or NULL on error. Free</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) #GstCaps for which an format description is needed</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_get_decoder_description"
c:identifier="gst_pb_utils_get_decoder_description">
<doc xml:whitespace="preserve">Returns a localised string describing an decoder for the format specified
in @caps, for use in error dialogs or other messages to be seen by the user.
Should never return NULL unless @factory_name or @caps are invalid.
This function is mainly for internal use, applications would typically
use gst_missing_plugin_message_get_description() to get a description of
a missing feature from a missing-plugin message.
string with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated description string, or NULL on error. Free</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) #GstCaps for which an decoder description is needed</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_get_element_description"
c:identifier="gst_pb_utils_get_element_description">
<doc xml:whitespace="preserve">Returns a localised string describing the given element, for use in
error dialogs or other messages to be seen by the user. Should never
return NULL unless @factory_name is invalid.
This function is mainly for internal use, applications would typically
use gst_missing_plugin_message_get_description() to get a description of
a missing feature from a missing-plugin message.
string with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated description string, or NULL on error. Free</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="factory_name" transfer-ownership="none">
<doc xml:whitespace="preserve">the name of the element, e.g. "gnomevfssrc"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_get_encoder_description"
c:identifier="gst_pb_utils_get_encoder_description">
<doc xml:whitespace="preserve">Returns a localised string describing an encoder for the format specified
in @caps, for use in error dialogs or other messages to be seen by the user.
Should never return NULL unless @factory_name or @caps are invalid.
This function is mainly for internal use, applications would typically
use gst_missing_plugin_message_get_description() to get a description of
a missing feature from a missing-plugin message.
string with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated description string, or NULL on error. Free</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the (fixed) #GstCaps for which an encoder description is needed</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_get_sink_description"
c:identifier="gst_pb_utils_get_sink_description">
<doc xml:whitespace="preserve">Returns a localised string describing a sink element handling the protocol
specified in @protocol, for use in error dialogs or other messages to be
seen by the user. Should never return NULL unless @protocol is invalid.
This function is mainly for internal use, applications would typically
use gst_missing_plugin_message_get_description() to get a description of
a missing feature from a missing-plugin message.
string with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated description string, or NULL on error. Free</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="protocol" transfer-ownership="none">
<doc xml:whitespace="preserve">the protocol the sink element needs to handle, e.g. "http"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_get_source_description"
c:identifier="gst_pb_utils_get_source_description">
<doc xml:whitespace="preserve">Returns a localised string describing a source element handling the protocol
specified in @protocol, for use in error dialogs or other messages to be
seen by the user. Should never return NULL unless @protocol is invalid.
This function is mainly for internal use, applications would typically
use gst_missing_plugin_message_get_description() to get a description of
a missing feature from a missing-plugin message.
string with g_free() when not needed any longer.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly-allocated description string, or NULL on error. Free</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="protocol" transfer-ownership="none">
<doc xml:whitespace="preserve">the protocol the source element needs to handle, e.g. "http"</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
<function name="pb_utils_init"
c:identifier="gst_pb_utils_init"
version="0.10.12">
<doc xml:whitespace="preserve">Initialises the base utils support library. This function is not
thread-safe. Applications should call it after calling gst_init(),
plugins should call it from their plugin_init function.
This function may be called multiple times. It will do nothing if the
library has already been initialised.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
</function>
<function name="plugins_base_version"
c:identifier="gst_plugins_base_version"
version="0.10.31">
<doc xml:whitespace="preserve">Gets the version number of the GStreamer Plugins Base libraries.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="major"
direction="out"
caller-allocates="0"
transfer-ownership="full">
<doc xml:whitespace="preserve">pointer to a guint to store the major version number, or %NULL</doc>
<type name="guint" c:type="guint*"/>
</parameter>
<parameter name="minor"
direction="out"
caller-allocates="0"
transfer-ownership="full">
<doc xml:whitespace="preserve">pointer to a guint to store the minor version number, or %NULL</doc>
<type name="guint" c:type="guint*"/>
</parameter>
<parameter name="micro"
direction="out"
caller-allocates="0"
transfer-ownership="full">
<doc xml:whitespace="preserve">pointer to a guint to store the micro version number, or %NULL</doc>
<type name="guint" c:type="guint*"/>
</parameter>
<parameter name="nano"
direction="out"
caller-allocates="0"
transfer-ownership="full">
<doc xml:whitespace="preserve">pointer to a guint to store the nano version number, or %NULL</doc>
<type name="guint" c:type="guint*"/>
</parameter>
</parameters>
</function>
<function name="plugins_base_version_string"
c:identifier="gst_plugins_base_version_string"
version="0.10.31">
<doc xml:whitespace="preserve">This function returns a string that is useful for describing this version
strings, logging, about dialogs ...</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a newly allocated string describing this version of gst-plugins-base</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</function>
</namespace>
</repository>
]]
FILE: [[gstreamer/plugins/pbutils/ffi/ffi.factor]] [[! Copyright (C) 2010 Anton Gorenko.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.libraries combinators kernel system
gobject-introspection glib.ffi gstreamer.ffi ;
IN: gstreamer.pbutils.ffi
<<
"gstreamer.pbutils" {
{ [ os winnt? ] [ drop ] }
{ [ os macosx? ] [ drop ] }
{ [ os unix? ] [ "libgstpbutils-0.10.so" cdecl add-library ] }
} cond
>>
GIR: vocab:gstreamer/pbutils/GstPbutils-0.10.gir
]]
FILE: [[gstreamer/plugins/video/GstVideo-0.10.gir]] [[<?xml version="1.0"?>
<!-- This file was automatically generated from C sources - DO NOT EDIT!
To affect the contents of this file, edit the original C definitions,
and/or use gtk-doc annotations. -->
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<include name="GLib" version="2.0"/>
<include name="GModule" version="2.0"/>
<include name="GObject" version="2.0"/>
<include name="Gst" version="0.10"/>
<include name="GstBase" version="0.10"/>
<include name="libxml2" version="2.0"/>
<package name="gstreamer-video-0.10"/>
<c:include name="gst/video/gstvideofilter.h"/>
<c:include name="gst/video/gstvideosink.h"/>
<c:include name="gst/video/video-enumtypes.h"/>
<c:include name="gst/video/video.h"/>
<namespace name="GstVideo"
version="0.10"
shared-library="libgstvideo-0.10.so.0"
c:identifier-prefixes="Gst"
c:symbol-prefixes="gst">
<constant name="VIDEO_BYTE1_MASK_24" value="0x00FF0000">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_BYTE1_MASK_24_INT" value="16711680">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_BYTE1_MASK_32" value="0xFF000000">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_BYTE1_MASK_32_INT" value="-16777216">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_BYTE2_MASK_24" value="0x0000FF00">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_BYTE2_MASK_24_INT" value="65280">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_BYTE2_MASK_32" value="0x00FF0000">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_BYTE2_MASK_32_INT" value="16711680">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_BYTE3_MASK_24" value="0x000000FF">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_BYTE3_MASK_24_INT" value="255">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_BYTE3_MASK_32" value="0x0000FF00">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_BYTE3_MASK_32_INT" value="65280">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_BYTE4_MASK_32" value="0x000000FF">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_BYTE4_MASK_32_INT" value="255">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_CAPS_GRAY8"
value="video/x-raw-gray, bpp = (int) 8, depth = (int) 8, width = ">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_CAPS_RGB8_PALETTED"
value="video/x-raw-rgb, bpp = (int)8, depth = (int)8, width = ">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_COMP1_MASK_15" value="0x7c00">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_COMP1_MASK_15_INT" value="31744">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_COMP1_MASK_16" value="0xf800">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_COMP1_MASK_16_INT" value="63488">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_COMP2_MASK_15" value="0x03e0">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_COMP2_MASK_15_INT" value="992">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_COMP2_MASK_16" value="0x07e0">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_COMP2_MASK_16_INT" value="2016">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_COMP3_MASK_15" value="0x001f">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_COMP3_MASK_15_INT" value="31">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_COMP3_MASK_16" value="0x001f">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_COMP3_MASK_16_INT" value="31">
<type name="gint" c:type="gint"/>
</constant>
<constant name="VIDEO_FPS_RANGE" value="(fraction) [ 0, max ]">
<type name="utf8" c:type="gchar*"/>
</constant>
<constant name="VIDEO_SIZE_RANGE" value="(int) [ 1, max ]">
<type name="utf8" c:type="gchar*"/>
</constant>
<callback name="VideoConvertFrameCallback"
c:type="GstVideoConvertFrameCallback">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="buf" transfer-ownership="none">
<type name="Gst.Buffer" c:type="GstBuffer*"/>
</parameter>
<parameter name="error" transfer-ownership="none">
<type name="GLib.Error" c:type="GError*"/>
</parameter>
<parameter name="user_data" transfer-ownership="none" closure="2">
<type name="gpointer" c:type="gpointer"/>
</parameter>
</parameters>
</callback>
<class name="VideoFilter"
c:symbol-prefix="video_filter"
c:type="GstVideoFilter"
parent="GstBase.BaseTransform"
abstract="1"
glib:type-name="GstVideoFilter"
glib:get-type="gst_video_filter_get_type"
glib:type-struct="VideoFilterClass">
<field name="element">
<type name="GstBase.BaseTransform" c:type="GstBaseTransform"/>
</field>
<field name="inited">
<type name="gboolean" c:type="gboolean"/>
</field>
</class>
<record name="VideoFilterClass"
c:type="GstVideoFilterClass"
glib:is-gtype-struct-for="VideoFilter">
<field name="parent_class">
<type name="GstBase.BaseTransformClass"
c:type="GstBaseTransformClass"/>
</field>
</record>
<enumeration name="VideoFormat"
glib:type-name="GstVideoFormat"
glib:get-type="gst_video_format_get_type"
c:type="GstVideoFormat">
<doc xml:whitespace="preserve">Enum value describing the most common video formats.</doc>
<member name="unknown"
value="0"
c:identifier="GST_VIDEO_FORMAT_UNKNOWN"
glib:nick="unknown"/>
<member name="i420"
value="1"
c:identifier="GST_VIDEO_FORMAT_I420"
glib:nick="i420"/>
<member name="yv12"
value="2"
c:identifier="GST_VIDEO_FORMAT_YV12"
glib:nick="yv12"/>
<member name="yuy2"
value="3"
c:identifier="GST_VIDEO_FORMAT_YUY2"
glib:nick="yuy2"/>
<member name="uyvy"
value="4"
c:identifier="GST_VIDEO_FORMAT_UYVY"
glib:nick="uyvy"/>
<member name="ayuv"
value="5"
c:identifier="GST_VIDEO_FORMAT_AYUV"
glib:nick="ayuv"/>
<member name="rgbx"
value="6"
c:identifier="GST_VIDEO_FORMAT_RGBx"
glib:nick="rgbx"/>
<member name="bgrx"
value="7"
c:identifier="GST_VIDEO_FORMAT_BGRx"
glib:nick="bgrx"/>
<member name="xrgb"
value="8"
c:identifier="GST_VIDEO_FORMAT_xRGB"
glib:nick="xrgb"/>
<member name="xbgr"
value="9"
c:identifier="GST_VIDEO_FORMAT_xBGR"
glib:nick="xbgr"/>
<member name="rgba"
value="10"
c:identifier="GST_VIDEO_FORMAT_RGBA"
glib:nick="rgba"/>
<member name="bgra"
value="11"
c:identifier="GST_VIDEO_FORMAT_BGRA"
glib:nick="bgra"/>
<member name="argb"
value="12"
c:identifier="GST_VIDEO_FORMAT_ARGB"
glib:nick="argb"/>
<member name="abgr"
value="13"
c:identifier="GST_VIDEO_FORMAT_ABGR"
glib:nick="abgr"/>
<member name="rgb"
value="14"
c:identifier="GST_VIDEO_FORMAT_RGB"
glib:nick="rgb"/>
<member name="bgr"
value="15"
c:identifier="GST_VIDEO_FORMAT_BGR"
glib:nick="bgr"/>
<member name="y41b"
value="16"
c:identifier="GST_VIDEO_FORMAT_Y41B"
glib:nick="y41b"/>
<member name="y42b"
value="17"
c:identifier="GST_VIDEO_FORMAT_Y42B"
glib:nick="y42b"/>
<member name="yvyu"
value="18"
c:identifier="GST_VIDEO_FORMAT_YVYU"
glib:nick="yvyu"/>
<member name="y444"
value="19"
c:identifier="GST_VIDEO_FORMAT_Y444"
glib:nick="y444"/>
<member name="v210"
value="20"
c:identifier="GST_VIDEO_FORMAT_v210"
glib:nick="v210"/>
<member name="v216"
value="21"
c:identifier="GST_VIDEO_FORMAT_v216"
glib:nick="v216"/>
<member name="nv12"
value="22"
c:identifier="GST_VIDEO_FORMAT_NV12"
glib:nick="nv12"/>
<member name="nv21"
value="23"
c:identifier="GST_VIDEO_FORMAT_NV21"
glib:nick="nv21"/>
<member name="gray8"
value="24"
c:identifier="GST_VIDEO_FORMAT_GRAY8"
glib:nick="gray8"/>
<member name="gray16_be"
value="25"
c:identifier="GST_VIDEO_FORMAT_GRAY16_BE"
glib:nick="gray16-be"/>
<member name="gray16_le"
value="26"
c:identifier="GST_VIDEO_FORMAT_GRAY16_LE"
glib:nick="gray16-le"/>
<member name="v308"
value="27"
c:identifier="GST_VIDEO_FORMAT_v308"
glib:nick="v308"/>
<member name="y800"
value="28"
c:identifier="GST_VIDEO_FORMAT_Y800"
glib:nick="y800"/>
<member name="y16"
value="29"
c:identifier="GST_VIDEO_FORMAT_Y16"
glib:nick="y16"/>
<member name="rgb16"
value="30"
c:identifier="GST_VIDEO_FORMAT_RGB16"
glib:nick="rgb16"/>
<member name="bgr16"
value="31"
c:identifier="GST_VIDEO_FORMAT_BGR16"
glib:nick="bgr16"/>
<member name="rgb15"
value="32"
c:identifier="GST_VIDEO_FORMAT_RGB15"
glib:nick="rgb15"/>
<member name="bgr15"
value="33"
c:identifier="GST_VIDEO_FORMAT_BGR15"
glib:nick="bgr15"/>
<member name="uyvp"
value="34"
c:identifier="GST_VIDEO_FORMAT_UYVP"
glib:nick="uyvp"/>
<member name="a420"
value="35"
c:identifier="GST_VIDEO_FORMAT_A420"
glib:nick="a420"/>
<member name="rgb8_paletted"
value="36"
c:identifier="GST_VIDEO_FORMAT_RGB8_PALETTED"
glib:nick="rgb8-paletted"/>
<member name="yuv9"
value="37"
c:identifier="GST_VIDEO_FORMAT_YUV9"
glib:nick="yuv9"/>
<member name="yvu9"
value="38"
c:identifier="GST_VIDEO_FORMAT_YVU9"
glib:nick="yvu9"/>
<member name="iyu1"
value="39"
c:identifier="GST_VIDEO_FORMAT_IYU1"
glib:nick="iyu1"/>
</enumeration>
<record name="VideoRectangle" c:type="GstVideoRectangle">
<doc xml:whitespace="preserve">Helper structure representing a rectangular area.</doc>
<field name="x" writable="1">
<type name="gint" c:type="gint"/>
</field>
<field name="y" writable="1">
<type name="gint" c:type="gint"/>
</field>
<field name="w" writable="1">
<type name="gint" c:type="gint"/>
</field>
<field name="h" writable="1">
<type name="gint" c:type="gint"/>
</field>
</record>
<class name="VideoSink"
c:symbol-prefix="video_sink"
c:type="GstVideoSink"
parent="GstBase.BaseSink"
glib:type-name="GstVideoSink"
glib:get-type="gst_video_sink_get_type"
glib:type-struct="VideoSinkClass">
<doc xml:whitespace="preserve">The video sink instance structure. Derived video sinks should set the</doc>
<function name="center_rect" c:identifier="gst_video_sink_center_rect">
<doc xml:whitespace="preserve">Takes @src rectangle and position it at the center of @dst rectangle with or
without @scaling. It handles clipping if the @src rectangle is bigger than
the @dst one and @scaling is set to FALSE.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="src" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstVideoRectangle describing the source area</doc>
<type name="VideoRectangle" c:type="GstVideoRectangle"/>
</parameter>
<parameter name="dst" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstVideoRectangle describing the destination area</doc>
<type name="VideoRectangle" c:type="GstVideoRectangle"/>
</parameter>
<parameter name="result" transfer-ownership="none">
<doc xml:whitespace="preserve">a pointer to a #GstVideoRectangle which will receive the result area</doc>
<type name="VideoRectangle" c:type="GstVideoRectangle*"/>
</parameter>
<parameter name="scaling" transfer-ownership="none">
<doc xml:whitespace="preserve">a #gboolean indicating if scaling should be applied or not</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
</function>
<virtual-method name="show_frame">
<return-value transfer-ownership="none">
<type name="Gst.FlowReturn" c:type="GstFlowReturn"/>
</return-value>
<parameters>
<parameter name="buf" transfer-ownership="none">
<type name="Gst.Buffer" c:type="GstBuffer*"/>
</parameter>
</parameters>
</virtual-method>
<property name="show-preroll-frame"
writable="1"
construct="1"
transfer-ownership="none">
<type name="gboolean"/>
</property>
<field name="element">
<type name="GstBase.BaseSink" c:type="GstBaseSink"/>
</field>
<field name="width">
<type name="gint" c:type="gint"/>
</field>
<field name="height">
<type name="gint" c:type="gint"/>
</field>
<field name="priv">
<type name="VideoSinkPrivate" c:type="GstVideoSinkPrivate*"/>
</field>
<field name="_gst_reserved">
<array zero-terminated="0" c:type="gpointer" fixed-size="3">
<type name="gpointer" c:type="gpointer"/>
</array>
</field>
</class>
<record name="VideoSinkClass"
c:type="GstVideoSinkClass"
glib:is-gtype-struct-for="VideoSink">
<doc xml:whitespace="preserve">The video sink class structure. Derived classes should override the</doc>
<field name="parent_class">
<type name="GstBase.BaseSinkClass" c:type="GstBaseSinkClass"/>
</field>
<field name="show_frame">
<callback name="show_frame">
<return-value transfer-ownership="none">
<type name="Gst.FlowReturn" c:type="GstFlowReturn"/>
</return-value>
<parameters>
<parameter name="video_sink" transfer-ownership="none">
<type name="VideoSink" c:type="GstVideoSink*"/>
</parameter>
<parameter name="buf" transfer-ownership="none">
<type name="Gst.Buffer" c:type="GstBuffer*"/>
</parameter>
</parameters>
</callback>
</field>
<field name="_gst_reserved">
<array zero-terminated="0" c:type="gpointer" fixed-size="3">
<type name="gpointer" c:type="gpointer"/>
</array>
</field>
</record>
<record name="VideoSinkPrivate" c:type="GstVideoSinkPrivate" disguised="1">
</record>
<function name="video_calculate_display_ratio"
c:identifier="gst_video_calculate_display_ratio"
version="0.10.7">
<doc xml:whitespace="preserve">Given the Pixel Aspect Ratio and size of an input video frame, and the
pixel aspect ratio of the intended display device, calculates the actual
display ratio the video will be rendered with.
dar_n and dar_d parameters.
The return value is FALSE in the case of integer overflow or other error.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">A boolean indicating success and a calculated Display Ratio in the</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="dar_n" transfer-ownership="none">
<doc xml:whitespace="preserve">Numerator of the calculated display_ratio</doc>
<type name="guint" c:type="guint*"/>
</parameter>
<parameter name="dar_d" transfer-ownership="none">
<doc xml:whitespace="preserve">Denominator of the calculated display_ratio</doc>
<type name="guint" c:type="guint*"/>
</parameter>
<parameter name="video_width" transfer-ownership="none">
<doc xml:whitespace="preserve">Width of the video frame in pixels</doc>
<type name="guint" c:type="guint"/>
</parameter>
<parameter name="video_height" transfer-ownership="none">
<doc xml:whitespace="preserve">Height of the video frame in pixels</doc>
<type name="guint" c:type="guint"/>
</parameter>
<parameter name="video_par_n" transfer-ownership="none">
<doc xml:whitespace="preserve">Numerator of the pixel aspect ratio of the input video.</doc>
<type name="guint" c:type="guint"/>
</parameter>
<parameter name="video_par_d" transfer-ownership="none">
<doc xml:whitespace="preserve">Denominator of the pixel aspect ratio of the input video.</doc>
<type name="guint" c:type="guint"/>
</parameter>
<parameter name="display_par_n" transfer-ownership="none">
<doc xml:whitespace="preserve">Numerator of the pixel aspect ratio of the display device</doc>
<type name="guint" c:type="guint"/>
</parameter>
<parameter name="display_par_d" transfer-ownership="none">
<doc xml:whitespace="preserve">Denominator of the pixel aspect ratio of the display device</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="video_convert_frame"
c:identifier="gst_video_convert_frame"
version="0.10.31"
introspectable="0"
throws="1">
<doc xml:whitespace="preserve">Converts a raw video buffer into the specified output caps.
The output caps can be any raw video formats or any image formats (jpeg, png, ...).
The width, height and pixel-aspect-ratio can also be specified in the output caps.
will point to the #GError).</doc>
<return-value>
<doc xml:whitespace="preserve">The converted #GstBuffer, or %NULL if an error happened (in which case @err</doc>
<type name="Gst.Buffer" c:type="GstBuffer*"/>
</return-value>
<parameters>
<parameter name="buf" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstBuffer</doc>
<type name="Gst.Buffer" c:type="GstBuffer*"/>
</parameter>
<parameter name="to_caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps to convert to</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">the maximum amount of time allowed for the processing.</doc>
<type name="Gst.ClockTime" c:type="GstClockTime"/>
</parameter>
</parameters>
</function>
<function name="video_convert_frame_async"
c:identifier="gst_video_convert_frame_async"
version="0.10.31">
<doc xml:whitespace="preserve">Converts a raw video buffer into the specified output caps.
The output caps can be any raw video formats or any image formats (jpeg, png, ...).
The width, height and pixel-aspect-ratio can also be specified in the output caps.
finish after @timeout. @callback will always be called from the thread default
%GMainContext, see g_main_context_get_thread_default(). If GLib before 2.22 is used,
this will always be the global default main context.
anymore.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="buf" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstBuffer</doc>
<type name="Gst.Buffer" c:type="GstBuffer*"/>
</parameter>
<parameter name="to_caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps to convert to</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">the maximum amount of time allowed for the processing.</doc>
<type name="Gst.ClockTime" c:type="GstClockTime"/>
</parameter>
<parameter name="callback"
transfer-ownership="none"
scope="notified"
closure="4"
destroy="5">
<doc xml:whitespace="preserve">%GstVideoConvertFrameCallback that will be called after conversion.</doc>
<type name="VideoConvertFrameCallback"
c:type="GstVideoConvertFrameCallback"/>
</parameter>
<parameter name="user_data" transfer-ownership="none">
<type name="gpointer" c:type="gpointer"/>
</parameter>
<parameter name="destroy_notify"
transfer-ownership="none"
scope="async">
<doc xml:whitespace="preserve">%GDestroyNotify to be called after @user_data is not needed anymore</doc>
<type name="GLib.DestroyNotify" c:type="GDestroyNotify"/>
</parameter>
</parameters>
</function>
<function name="video_event_new_still_frame"
c:identifier="gst_video_event_new_still_frame"
version="0.10.26"
introspectable="0">
<doc xml:whitespace="preserve">Creates a new Still Frame event. If @in_still is %TRUE, then the event
represents the start of a still frame sequence. If it is %FALSE, then
the event ends a still frame sequence.
To parse an event created by gst_video_event_new_still_frame() use
gst_video_event_parse_still_frame().</doc>
<return-value>
<doc xml:whitespace="preserve">The new GstEvent</doc>
<type name="Gst.Event" c:type="GstEvent*"/>
</return-value>
<parameters>
<parameter name="in_still" transfer-ownership="none">
<doc xml:whitespace="preserve">boolean value for the still-frame state of the event.</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
</function>
<function name="video_event_parse_still_frame"
c:identifier="gst_video_event_parse_still_frame"
version="0.10.26">
<doc xml:whitespace="preserve">Parse a #GstEvent, identify if it is a Still Frame event, and
return the still-frame state from the event if it is.
If the event represents the start of a still frame, the in_still
variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
in_still variable order to just check whether the event is a valid still-frame
event.
Create a still frame event using gst_video_event_new_still_frame()</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE if the event is a valid still-frame event. %FALSE if not</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="event" transfer-ownership="none">
<doc xml:whitespace="preserve">A #GstEvent to parse</doc>
<type name="Gst.Event" c:type="GstEvent*"/>
</parameter>
<parameter name="in_still" transfer-ownership="none">
<doc xml:whitespace="preserve">A boolean to receive the still-frame status from the event, or NULL</doc>
<type name="gboolean" c:type="gboolean*"/>
</parameter>
</parameters>
</function>
<function name="video_format_convert"
c:identifier="gst_video_format_convert"
version="0.10.16">
<doc xml:whitespace="preserve">Converts among various #GstFormat types. This function handles
GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
raw video, GST_FORMAT_DEFAULT corresponds to video frames. This
function can be to handle pad queries of the type GST_QUERY_CONVERT.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if the conversion was successful.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">the width of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">the height of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="fps_n" transfer-ownership="none">
<doc xml:whitespace="preserve">frame rate numerator</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="fps_d" transfer-ownership="none">
<doc xml:whitespace="preserve">frame rate denominator</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="src_format" transfer-ownership="none">
<doc xml:whitespace="preserve">#GstFormat of the @src_value</doc>
<type name="Gst.Format" c:type="GstFormat"/>
</parameter>
<parameter name="src_value" transfer-ownership="none">
<doc xml:whitespace="preserve">value to convert</doc>
<type name="gint64" c:type="gint64"/>
</parameter>
<parameter name="dest_format" transfer-ownership="none">
<doc xml:whitespace="preserve">#GstFormat of the @dest_value</doc>
<type name="Gst.Format" c:type="GstFormat"/>
</parameter>
<parameter name="dest_value" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to destination value</doc>
<type name="gint64" c:type="gint64*"/>
</parameter>
</parameters>
</function>
<function name="video_format_from_fourcc"
c:identifier="gst_video_format_from_fourcc"
version="0.10.16">
<doc xml:whitespace="preserve">Converts a FOURCC value into the corresponding #GstVideoFormat.
If the FOURCC cannot be represented by #GstVideoFormat,
#GST_VIDEO_FORMAT_UNKNOWN is returned.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstVideoFormat describing the FOURCC value</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</return-value>
<parameters>
<parameter name="fourcc" transfer-ownership="none">
<doc xml:whitespace="preserve">a FOURCC value representing raw YUV video</doc>
<type name="guint32" c:type="guint32"/>
</parameter>
</parameters>
</function>
<function name="video_format_get_component_height"
c:identifier="gst_video_format_get_component_height"
version="0.10.16">
<doc xml:whitespace="preserve">Calculates the height of the component. See
of the component index.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">height of component @component</doc>
<type name="gint" c:type="int"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="component" transfer-ownership="none">
<doc xml:whitespace="preserve">the component index</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">the height of video</doc>
<type name="gint" c:type="int"/>
</parameter>
</parameters>
</function>
<function name="video_format_get_component_offset"
c:identifier="gst_video_format_get_component_offset"
version="0.10.16">
<doc xml:whitespace="preserve">Calculates the offset (in bytes) of the first pixel of the component
with index @component. For packed formats, this will typically be a
small integer (0, 1, 2, 3). For planar formats, this will be a
(relatively) large offset to the beginning of the second or third
component planes. See @gst_video_format_get_row_stride for a description
of the component index.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">offset of component @component</doc>
<type name="gint" c:type="int"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="component" transfer-ownership="none">
<doc xml:whitespace="preserve">the component index</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">the width of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">the height of video</doc>
<type name="gint" c:type="int"/>
</parameter>
</parameters>
</function>
<function name="video_format_get_component_width"
c:identifier="gst_video_format_get_component_width"
version="0.10.16">
<doc xml:whitespace="preserve">Calculates the width of the component. See
of the component index.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">width of component @component</doc>
<type name="gint" c:type="int"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="component" transfer-ownership="none">
<doc xml:whitespace="preserve">the component index</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">the width of video</doc>
<type name="gint" c:type="int"/>
</parameter>
</parameters>
</function>
<function name="video_format_get_pixel_stride"
c:identifier="gst_video_format_get_pixel_stride"
version="0.10.16">
<doc xml:whitespace="preserve">Calculates the pixel stride (number of bytes from one pixel to the
pixel to its immediate left) for the video component with an index
of @component. See @gst_video_format_get_row_stride for a description
of the component index.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">pixel stride of component @component</doc>
<type name="gint" c:type="int"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="component" transfer-ownership="none">
<doc xml:whitespace="preserve">the component index</doc>
<type name="gint" c:type="int"/>
</parameter>
</parameters>
</function>
<function name="video_format_get_row_stride"
c:identifier="gst_video_format_get_row_stride"
version="0.10.16">
<doc xml:whitespace="preserve">Calculates the row stride (number of bytes from one row of pixels to
the next) for the video component with an index of @component. For
YUV video, Y, U, and V have component indices of 0, 1, and 2,
respectively. For RGB video, R, G, and B have component indicies of
0, 1, and 2, respectively. Alpha channels, if present, have a component
index of 3. The @width parameter always represents the width of the
video, not the component.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">row stride of component @component</doc>
<type name="gint" c:type="int"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="component" transfer-ownership="none">
<doc xml:whitespace="preserve">the component index</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">the width of video</doc>
<type name="gint" c:type="int"/>
</parameter>
</parameters>
</function>
<function name="video_format_get_size"
c:identifier="gst_video_format_get_size"
version="0.10.16">
<doc xml:whitespace="preserve">Calculates the total number of bytes in the raw video format. This
number should be used when allocating a buffer for raw video.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">size (in bytes) of raw video format</doc>
<type name="gint" c:type="int"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">the width of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">the height of video</doc>
<type name="gint" c:type="int"/>
</parameter>
</parameters>
</function>
<function name="video_format_has_alpha"
c:identifier="gst_video_format_has_alpha"
version="0.10.16">
<doc xml:whitespace="preserve">Returns TRUE or FALSE depending on if the video format provides an
alpha channel.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @format has an alpha channel</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
</parameters>
</function>
<function name="video_format_is_gray"
c:identifier="gst_video_format_is_gray"
version="0.10.29">
<doc xml:whitespace="preserve">Determine whether the video format is a grayscale format.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @format represents grayscale video</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
</parameters>
</function>
<function name="video_format_is_rgb"
c:identifier="gst_video_format_is_rgb"
version="0.10.16">
<doc xml:whitespace="preserve">Determine whether the video format is an RGB format.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @format represents RGB video</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
</parameters>
</function>
<function name="video_format_is_yuv"
c:identifier="gst_video_format_is_yuv"
version="0.10.16">
<doc xml:whitespace="preserve">Determine whether the video format is a YUV format.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @format represents YUV video</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
</parameters>
</function>
<function name="video_format_new_caps"
c:identifier="gst_video_format_new_caps"
version="0.10.16">
<doc xml:whitespace="preserve">Creates a new #GstCaps object based on the parameters provided.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstCaps object, or NULL if there was an error</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstVideoFormat describing the raw video format</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">width of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">height of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="framerate_n" transfer-ownership="none">
<doc xml:whitespace="preserve">numerator of frame rate</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="framerate_d" transfer-ownership="none">
<doc xml:whitespace="preserve">denominator of frame rate</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="par_n" transfer-ownership="none">
<doc xml:whitespace="preserve">numerator of pixel aspect ratio</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="par_d" transfer-ownership="none">
<doc xml:whitespace="preserve">denominator of pixel aspect ratio</doc>
<type name="gint" c:type="int"/>
</parameter>
</parameters>
</function>
<function name="video_format_new_caps_interlaced"
c:identifier="gst_video_format_new_caps_interlaced"
version="0.10.23">
<doc xml:whitespace="preserve">Creates a new #GstCaps object based on the parameters provided.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">a new #GstCaps object, or NULL if there was an error</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstVideoFormat describing the raw video format</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">width of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">height of video</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="framerate_n" transfer-ownership="none">
<doc xml:whitespace="preserve">numerator of frame rate</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="framerate_d" transfer-ownership="none">
<doc xml:whitespace="preserve">denominator of frame rate</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="par_n" transfer-ownership="none">
<doc xml:whitespace="preserve">numerator of pixel aspect ratio</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="par_d" transfer-ownership="none">
<doc xml:whitespace="preserve">denominator of pixel aspect ratio</doc>
<type name="gint" c:type="int"/>
</parameter>
<parameter name="interlaced" transfer-ownership="none">
<doc xml:whitespace="preserve">#TRUE if the format is interlaced</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
</function>
<function name="video_format_parse_caps"
c:identifier="gst_video_format_parse_caps"
version="0.10.16">
<doc xml:whitespace="preserve">Determines the #GstVideoFormat of @caps and places it in the location
pointed to by @format. Extracts the size of the video and places it
in the location pointed to by @width and @height. If @caps does not
represent one of the raw video formats listed in #GstVideoFormat, the
function will fail and return FALSE.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @caps was parsed correctly.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstCaps to parse</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">the #GstVideoFormat of the video represented by @caps (output)</doc>
<type name="VideoFormat" c:type="GstVideoFormat*"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">the width of the video represented by @caps, may be NULL (output)</doc>
<type name="gint" c:type="int*"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">the height of the video represented by @caps, may be NULL (output)</doc>
<type name="gint" c:type="int*"/>
</parameter>
</parameters>
</function>
<function name="video_format_parse_caps_interlaced"
c:identifier="gst_video_format_parse_caps_interlaced"
version="0.10.23">
<doc xml:whitespace="preserve">Extracts whether the caps represents interlaced content or not and places it
in @interlaced.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @caps was parsed correctly.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the fixed #GstCaps to parse</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="interlaced" transfer-ownership="none">
<doc xml:whitespace="preserve">whether @caps represents interlaced video or not, may be NULL (output)</doc>
<type name="gboolean" c:type="gboolean*"/>
</parameter>
</parameters>
</function>
<function name="video_format_to_fourcc"
c:identifier="gst_video_format_to_fourcc"
version="0.10.16">
<doc xml:whitespace="preserve">Converts a #GstVideoFormat value into the corresponding FOURCC. Only
a few YUV formats have corresponding FOURCC values. If @format has
no corresponding FOURCC value, 0 is returned.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the FOURCC corresponding to @format</doc>
<type name="guint32" c:type="guint32"/>
</return-value>
<parameters>
<parameter name="format" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstVideoFormat video format</doc>
<type name="VideoFormat" c:type="GstVideoFormat"/>
</parameter>
</parameters>
</function>
<function name="video_frame_rate" c:identifier="gst_video_frame_rate">
<doc xml:whitespace="preserve">A convenience function to retrieve a GValue holding the framerate
from the caps on a pad.
The pad needs to have negotiated caps containing a framerate property.
do not contain a framerate.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">NULL if the pad has no configured caps or the configured caps</doc>
<type name="GObject.Value" c:type="GValue*"/>
</return-value>
<parameters>
<parameter name="pad" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to a #GstPad</doc>
<type name="Gst.Pad" c:type="GstPad*"/>
</parameter>
</parameters>
</function>
<function name="video_get_size" c:identifier="gst_video_get_size">
<doc xml:whitespace="preserve">Inspect the caps of the provided pad and retrieve the width and height of
the video frames it is configured for.
The pad needs to have negotiated caps containing width and height properties.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if the width and height could be retrieved.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="pad" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to a #GstPad</doc>
<type name="Gst.Pad" c:type="GstPad*"/>
</parameter>
<parameter name="width" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to integer to hold pixel width of the video frames (output)</doc>
<type name="gint" c:type="gint*"/>
</parameter>
<parameter name="height" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to integer to hold pixel height of the video frames (output)</doc>
<type name="gint" c:type="gint*"/>
</parameter>
</parameters>
</function>
<function name="video_parse_caps_chroma_site"
c:identifier="gst_video_parse_caps_chroma_site"
version="0.10.29">
<doc xml:whitespace="preserve">Extracts the chroma site used by the caps. Possible values are
"mpeg2" for MPEG-2 style chroma siting (co-sited horizontally,
halfway-sited vertically), "jpeg" for JPEG and Theora style
chroma siting (halfway-sited both horizontally and vertically).
Other chroma site values are possible, but uncommon.
When no chroma site is specified in the caps, it should be assumed
to be "mpeg2".
determined.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">a chroma site string, or NULL if no chroma site could be</doc>
<type name="utf8" c:type="char*"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the fixed #GstCaps to parse</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="video_parse_caps_color_matrix"
c:identifier="gst_video_parse_caps_color_matrix"
version="0.10.29">
<doc xml:whitespace="preserve">Extracts the color matrix used by the caps. Possible values are
"sdtv" for the standard definition color matrix (as specified in
Rec. ITU-R BT.470-6) or "hdtv" for the high definition color
matrix (as specified in Rec. ITU-R BT.709)
determined.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">a color matrix string, or NULL if no color matrix could be</doc>
<type name="utf8" c:type="char*"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">the fixed #GstCaps to parse</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="video_parse_caps_framerate"
c:identifier="gst_video_parse_caps_framerate"
version="0.10.16">
<doc xml:whitespace="preserve">Extracts the frame rate from @caps and places the values in the locations
pointed to by @fps_n and @fps_d. Returns TRUE if the values could be
parsed correctly, FALSE if not.
This function can be used with #GstCaps that have any media type; it
is not limited to formats handled by #GstVideoFormat.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @caps was parsed correctly.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to a #GstCaps instance</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="fps_n" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to integer to hold numerator of frame rate (output)</doc>
<type name="gint" c:type="int*"/>
</parameter>
<parameter name="fps_d" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to integer to hold denominator of frame rate (output)</doc>
<type name="gint" c:type="int*"/>
</parameter>
</parameters>
</function>
<function name="video_parse_caps_palette"
c:identifier="gst_video_parse_caps_palette"
version="0.10.32"
introspectable="0">
<doc xml:whitespace="preserve">Returns the palette data from the caps as a #GstBuffer. For
#GST_VIDEO_FORMAT_RGB8_PALETTED this is containing 256 #guint32
values, each containing ARGB colors in native endianness.</doc>
<return-value>
<doc xml:whitespace="preserve">a #GstBuffer containing the palette data. Unref after usage.</doc>
<type name="Gst.Buffer" c:type="GstBuffer*"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">#GstCaps to parse</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
</parameters>
</function>
<function name="video_parse_caps_pixel_aspect_ratio"
c:identifier="gst_video_parse_caps_pixel_aspect_ratio"
version="0.10.16">
<doc xml:whitespace="preserve">Extracts the pixel aspect ratio from @caps and places the values in
the locations pointed to by @par_n and @par_d. Returns TRUE if the
values could be parsed correctly, FALSE if not.
This function can be used with #GstCaps that have any media type; it
is not limited to formats handled by #GstVideoFormat.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">TRUE if @caps was parsed correctly.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="caps" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to a #GstCaps instance</doc>
<type name="Gst.Caps" c:type="GstCaps*"/>
</parameter>
<parameter name="par_n" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to numerator of pixel aspect ratio (output)</doc>
<type name="gint" c:type="int*"/>
</parameter>
<parameter name="par_d" transfer-ownership="none">
<doc xml:whitespace="preserve">pointer to denominator of pixel aspect ratio (output)</doc>
<type name="gint" c:type="int*"/>
</parameter>
</parameters>
</function>
</namespace>
</repository>
]]
FILE: [[gstreamer/plugins/video/video.factor]] [[! Copyright (C) 2010 Anton Gorenko.
! See http://factorcode.org/license.txt for BSD license.
USING: gstreamer.video.ffi ;
IN: gstreamer.video
]]
FILE: [[gstreamer/plugins/video/ffi/ffi.factor]] [[! Copyright (C) 2010 Anton Gorenko.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.libraries combinators kernel
system
gobject-introspection glib.ffi gobject.ffi gstreamer.ffi ;
IN: gstreamer.video.ffi
<<
"gstreamer.video" {
{ [ os winnt? ] [ drop ] }
{ [ os macosx? ] [ drop ] }
{ [ os unix? ] [ "libgstvideo-0.10.so" cdecl add-library ] }
} cond
>>
IMPLEMENT-STRUCTS: GstVideoRectangle ;
GIR: vocab:gstreamer/video/GstVideo-0.10.gir
]]
FILE: [[gstreamer/plugins/rtsp/rtsp.factor]] [[! Copyright (C) 2010 Anton Gorenko.
! See http://factorcode.org/license.txt for BSD license.
USING: gstreamer.rtsp.ffi ;
IN: gstreamer.rtsp
]]
FILE: [[gstreamer/plugins/rtsp/ffi/ffi.factor]] [[! Copyright (C) 2010 Anton Gorenko.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.syntax alien.libraries combinators kernel
system
gobject-introspection glib.ffi gstreamer.ffi gstreamer.sdp.ffi ;
IN: gstreamer.rtsp.ffi
<<
"gstreamer.rtsp" {
{ [ os winnt? ] [ drop ] }
{ [ os macosx? ] [ drop ] }
{ [ os unix? ] [ "libgstrtsp-0.10.so" cdecl add-library ] }
} cond
>>
! git error (there is _GstRTSPTransport only in .gir)
C-TYPE: GstRTSPTransport
GIR: vocab:gstreamer/rtsp/GstRtsp-0.10.gir
]]
FILE: [[gstreamer/plugins/rtsp/GstRtsp-0.10.gir]] [[<?xml version="1.0"?>
<!-- This file was automatically generated from C sources - DO NOT EDIT!
To affect the contents of this file, edit the original C definitions,
and/or use gtk-doc annotations. -->
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<include name="GLib" version="2.0"/>
<include name="GModule" version="2.0"/>
<include name="GObject" version="2.0"/>
<include name="Gst" version="0.10"/>
<include name="GstSdp" version="0.10"/>
<include name="libxml2" version="2.0"/>
<package name="gstreamer-rtsp-0.10"/>
<c:include name="gst/audio/gstrtsp-enumtypes.h"/>
<c:include name="gst/audio/gstrtspbase64.h"/>
<c:include name="gst/audio/gstrtspconnection.h"/>
<c:include name="gst/audio/gstrtspdefs.h"/>
<c:include name="gst/audio/gstrtspextension.h"/>
<c:include name="gst/audio/gstrtspmessage.h"/>
<c:include name="gst/audio/gstrtsprange.h"/>
<c:include name="gst/audio/gstrtsptransport.h"/>
<c:include name="gst/audio/gstrtspurl.h"/>
<namespace name="GstRtsp"
version="0.10"
shared-library="libgstrtsp-0.10.so.0"
c:identifier-prefixes="Gst"
c:symbol-prefixes="gst">
<enumeration name="RTSPAuthMethod"
glib:type-name="GstRTSPAuthMethod"
glib:get-type="gst_rtsp_auth_method_get_type"
c:type="GstRTSPAuthMethod">
<doc xml:whitespace="preserve">Authentication methods, ordered by strength</doc>
<member name="none"
value="0"
c:identifier="GST_RTSP_AUTH_NONE"
glib:nick="none"/>
<member name="basic"
value="1"
c:identifier="GST_RTSP_AUTH_BASIC"
glib:nick="basic"/>
<member name="digest"
value="2"
c:identifier="GST_RTSP_AUTH_DIGEST"
glib:nick="digest"/>
</enumeration>
<record name="RTSPConnection" c:type="GstRTSPConnection" disguised="1">
<doc xml:whitespace="preserve">Opaque RTSP connection object.</doc>
<method name="clear_auth_params"
c:identifier="gst_rtsp_connection_clear_auth_params"
version="0.10.20">
<doc xml:whitespace="preserve">Clear the list of authentication directives stored in @conn.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
</method>
<method name="close" c:identifier="gst_rtsp_connection_close">
<doc xml:whitespace="preserve">Close the connected @conn. After this call, the connection is in the same
state as when it was first created.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
</method>
<method name="connect" c:identifier="gst_rtsp_connection_connect">
<doc xml:whitespace="preserve">Attempt to connect to the url of @conn made with
gst_rtsp_connection_create(). If @timeout is #NULL this function can block
forever. If @timeout contains a valid timeout, this function will return
#GST_RTSP_ETIMEOUT after the timeout expired.
This function can be cancelled with gst_rtsp_connection_flush().</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK when a connection could be made.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GTimeVal timeout</doc>
<type name="GLib.TimeVal" c:type="GTimeVal*"/>
</parameter>
</parameters>
</method>
<method name="do_tunnel"
c:identifier="gst_rtsp_connection_do_tunnel"
version="0.10.23">
<doc xml:whitespace="preserve">If @conn received the first tunnel connection and @conn2 received
the second tunnel connection, link the two connections together so that
After this call, @conn2 cannot be used anymore and must be freed with
gst_rtsp_connection_free().
If @conn2 is %NULL then only the base64 decoding context will be setup for</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">return GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="conn2" transfer-ownership="none">
<doc xml:whitespace="preserve">a #GstRTSPConnection or %NULL</doc>
<type name="RTSPConnection" c:type="GstRTSPConnection*"/>
</parameter>
</parameters>
</method>
<method name="flush" c:identifier="gst_rtsp_connection_flush">
<doc xml:whitespace="preserve">Start or stop the flushing action on @conn. When flushing, all current
and future actions on @conn will return #GST_RTSP_EINTR until the connection
is set to non-flushing mode again.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="flush" transfer-ownership="none">
<doc xml:whitespace="preserve">start or stop the flush</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
</method>
<method name="free" c:identifier="gst_rtsp_connection_free">
<doc xml:whitespace="preserve">Close and free @conn.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
</method>
<method name="get_ip"
c:identifier="gst_rtsp_connection_get_ip"
version="0.10.20">
<doc xml:whitespace="preserve">Retrieve the IP address of the other end of @conn.
connection is closed.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">The IP address as a string. this value remains valid until the</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_readfd"
c:identifier="gst_rtsp_connection_get_readfd"
version="0.10.23">
<doc xml:whitespace="preserve">Get the file descriptor for reading.
descriptor remains valid until the connection is closed.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the file descriptor used for reading or -1 on error. The file</doc>
<type name="gint" c:type="gint"/>
</return-value>
</method>
<method name="get_tunnelid"
c:identifier="gst_rtsp_connection_get_tunnelid"
version="0.10.23">
<doc xml:whitespace="preserve">Get the tunnel session id the connection.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">returns a non-empty string if @conn is being tunneled over HTTP.</doc>
<type name="utf8" c:type="gchar*"/>
</return-value>
</method>
<method name="get_url"
c:identifier="gst_rtsp_connection_get_url"
version="0.10.23">
<doc xml:whitespace="preserve">Retrieve the URL of the other end of @conn.
connection is freed.</doc>
<return-value transfer-ownership="full">
<doc xml:whitespace="preserve">The URL. This value remains valid until the</doc>
<type name="RTSPUrl" c:type="GstRTSPUrl*"/>
</return-value>
</method>
<method name="get_writefd"
c:identifier="gst_rtsp_connection_get_writefd"
version="0.10.23">
<doc xml:whitespace="preserve">Get the file descriptor for writing.
descriptor remains valid until the connection is closed.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">the file descriptor used for writing or -1 on error. The file</doc>
<type name="gint" c:type="gint"/>
</return-value>
</method>
<method name="is_tunneled"
c:identifier="gst_rtsp_connection_is_tunneled"
version="0.10.23">
<doc xml:whitespace="preserve">Get the tunneling state of the connection.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">if @conn is using HTTP tunneling.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
</method>
<method name="next_timeout"
c:identifier="gst_rtsp_connection_next_timeout">
<doc xml:whitespace="preserve">Calculate the next timeout for @conn, storing the result in @timeout.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">a timeout</doc>
<type name="GLib.TimeVal" c:type="GTimeVal*"/>
</parameter>
</parameters>
</method>
<method name="poll"
c:identifier="gst_rtsp_connection_poll"
version="0.10.15">
<doc xml:whitespace="preserve">Wait up to the specified @timeout for the connection to become available for
at least one of the operations specified in @events. When the function returns
with #GST_RTSP_OK, @revents will contain a bitmask of available operations on
This function can be cancelled with gst_rtsp_connection_flush().</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="events" transfer-ownership="none">
<doc xml:whitespace="preserve">a bitmask of #GstRTSPEvent flags to check</doc>
<type name="RTSPEvent" c:type="GstRTSPEvent"/>
</parameter>
<parameter name="revents" transfer-ownership="none">
<doc xml:whitespace="preserve">location for result flags</doc>
<type name="RTSPEvent" c:type="GstRTSPEvent*"/>
</parameter>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">a timeout</doc>
<type name="GLib.TimeVal" c:type="GTimeVal*"/>
</parameter>
</parameters>
</method>
<method name="read" c:identifier="gst_rtsp_connection_read">
<doc xml:whitespace="preserve">Attempt to read @size bytes into @data from the connected @conn, blocking up to
the specified @timeout. @timeout can be #NULL, in which case this function
might block forever.
This function can be cancelled with gst_rtsp_connection_flush().</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="data" transfer-ownership="none">
<doc xml:whitespace="preserve">the data to read</doc>
<type name="guint8" c:type="guint8*"/>
</parameter>
<parameter name="size" transfer-ownership="none">
<doc xml:whitespace="preserve">the size of @data</doc>
<type name="guint" c:type="guint"/>
</parameter>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">a timeout value or #NULL</doc>
<type name="GLib.TimeVal" c:type="GTimeVal*"/>
</parameter>
</parameters>
</method>
<method name="receive" c:identifier="gst_rtsp_connection_receive">
<doc xml:whitespace="preserve">Attempt to read into @message from the connected @conn, blocking up to
the specified @timeout. @timeout can be #NULL, in which case this function
might block forever.
This function can be cancelled with gst_rtsp_connection_flush().</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="message" transfer-ownership="none">
<doc xml:whitespace="preserve">the message to read</doc>
<type name="RTSPMessage" c:type="GstRTSPMessage*"/>
</parameter>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">a timeout value or #NULL</doc>
<type name="GLib.TimeVal" c:type="GTimeVal*"/>
</parameter>
</parameters>
</method>
<method name="reset_timeout"
c:identifier="gst_rtsp_connection_reset_timeout">
<doc xml:whitespace="preserve">Reset the timeout of @conn.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
</method>
<method name="send" c:identifier="gst_rtsp_connection_send">
<doc xml:whitespace="preserve">Attempt to send @message to the connected @conn, blocking up to
the specified @timeout. @timeout can be #NULL, in which case this function
might block forever.
This function can be cancelled with gst_rtsp_connection_flush().</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="message" transfer-ownership="none">
<doc xml:whitespace="preserve">the message to send</doc>
<type name="RTSPMessage" c:type="GstRTSPMessage*"/>
</parameter>
<parameter name="timeout" transfer-ownership="none">
<doc xml:whitespace="preserve">a timeout value or #NULL</doc>
<type name="GLib.TimeVal" c:type="GTimeVal*"/>
</parameter>
</parameters>
</method>
<method name="set_auth" c:identifier="gst_rtsp_connection_set_auth">
<doc xml:whitespace="preserve">Configure @conn for authentication mode @method with @user and @pass as the
user and password respectively.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="method" transfer-ownership="none">
<doc xml:whitespace="preserve">authentication method</doc>
<type name="RTSPAuthMethod" c:type="GstRTSPAuthMethod"/>
</parameter>
<parameter name="user" transfer-ownership="none">
<doc xml:whitespace="preserve">the user</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="pass" transfer-ownership="none">
<doc xml:whitespace="preserve">the password</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="set_auth_param"
c:identifier="gst_rtsp_connection_set_auth_param"
version="0.10.20">
<doc xml:whitespace="preserve">Setup @conn with authentication directives. This is not necesary for
methods #GST_RTSP_AUTH_NONE and #GST_RTSP_AUTH_BASIC. For
#GST_RTSP_AUTH_DIGEST, directives should be taken from the digest challenge
in the WWW-Authenticate response header and can include realm, domain,
nonce, opaque, stale, algorithm, qop as per RFC2617.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="param" transfer-ownership="none">
<doc xml:whitespace="preserve">authentication directive</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="value" transfer-ownership="none">
<doc xml:whitespace="preserve">value</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="set_http_mode"
c:identifier="gst_rtsp_connection_set_http_mode"
version="0.10.25">
<doc xml:whitespace="preserve">By setting the HTTP mode to %TRUE the message parsing will support HTTP
messages in addition to the RTSP messages. It will also disable the
automatic handling of setting up an HTTP tunnel.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="enable" transfer-ownership="none">
<doc xml:whitespace="preserve">%TRUE to enable manual HTTP mode</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
</method>
<method name="set_ip"
c:identifier="gst_rtsp_connection_set_ip"
version="0.10.23">
<doc xml:whitespace="preserve">Set the IP address of the server.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="ip" transfer-ownership="none">
<doc xml:whitespace="preserve">an ip address</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</method>
<method name="set_proxy"
c:identifier="gst_rtsp_connection_set_proxy"
version="0.10.23">
<doc xml:whitespace="preserve">Set the proxy host and port.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="host" transfer-ownership="none">
<doc xml:whitespace="preserve">the proxy host</doc>
<type name="utf8" c:type="gchar*"/>
</parameter>
<parameter name="port" transfer-ownership="none">
<doc xml:whitespace="preserve">the proxy port</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</method>
<method name="set_qos_dscp"
c:identifier="gst_rtsp_connection_set_qos_dscp"
version="0.10.20">
<doc xml:whitespace="preserve">Configure @conn to use the specified DSCP value.</doc>
<return-value transfer-ownership="none">
<doc xml:whitespace="preserve">#GST_RTSP_OK on success.</doc>
<type name="RTSPResult" c:type="GstRTSPResult"/>
</return-value>
<parameters>
<parameter name="qos_dscp" transfer-ownership="none">
<doc xml:whitespace="preserve">DSCP value</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</method>
<method name="set_tunneled"
c:identifier="gst_rtsp_connection_set_tunneled"
version="0.10.23">
<doc xml:whitespace="preserve">Set the HTTP tunneling state of the connection. This must be configured before
the @conn is connected.</doc>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="tunneled" transfer-ownership="none">
<doc xml:whitespace="preserve">the new state</doc>
<type name="gboolean" c:type="gboolean"/>
</parameter>
</parameters>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment