diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..5b76b8e --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,51 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.224.2/containers/docker-existing-docker-compose +{ + "name": "intersystems-iris-dev-template devcontainer", + + // Use the same recipe as creates the container we use when working locally. + "dockerComposeFile": [ + "../docker-compose.yml" + ], + + "service": "iris", + + "workspaceFolder": "/home/irisowner/dev", + + // This provides the elements of the connection object which require different values when connecting to the workspace within the container, + // versus those in .vscode/settings.json which apply when operating locally on the workspace files. + // We define and use a `server` so that (a) a user-level `objectscript.conn.server` properly doesn't override us, and (b) so InterSystems + // Server Manager can also be used. + "settings": { + "objectscript.conn" :{ + "server": "devcontainer", + "active": true, + }, + "intersystems.servers": { + "devcontainer": { + "username": "SuperUser", + "password": "SYS", + "webServer": { + "scheme": "http", + "host": "127.0.0.1", + "port": 52773 + }, + }, + }, + "python.defaultInterpreterPath":"/usr/irissys/bin/irispython" + }, + + // Add the IDs of extensions we want installed when the container is created. + // Currently (March 2022) `intersystems.language-server` fails to run within the container (alpine platform). + // Issue is probably https://github.com/intersystems/language-server/issues/185 and/or https://github.com/intersystems/language-server/issues/32 + // Crash gets reported to the user, after which `intersystems-community.vscode-objectscript` falls back to + // using its TextMate grammar for code coloring. + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance", + "intersystems-community.vscode-objectscript", + "intersystems.language-server", + "intersystems-community.servermanager", + "ms-vscode.docker" + ], +} diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..24c989d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +**/.DS_Store +iris-main.log +.git \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4a94c94 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +*.cls linguist-language=ObjectScript +*.mac linguist-language=ObjectScript +*.int linguist-language=ObjectScript +*.inc linguist-language=ObjectScript +*.csp linguist-language=Html + +*.sh text eol=lf +*.cls text eol=lf +*.mac text eol=lf +*.int text eol=lf +Dockerfil* text eol=lf diff --git a/.github/workflows/build-push-gcr.yaml b/.github/workflows/build-push-gcr.yaml new file mode 100644 index 0000000..aa786f9 --- /dev/null +++ b/.github/workflows/build-push-gcr.yaml @@ -0,0 +1,19 @@ +name: Cloud Run Deploy + +on: + push: + branches: + - master + - main + workflow_dispatch: + +jobs: + deploy: + uses: intersystems-community/demo-deployment/.github/workflows/deployment.yml@master + with: + # Replace the name: parameter below to have your application deployed at + # https://project-name.demo.community.intersystems.com/ + name: project-name + secrets: + # Do not forget to add Secret in GitHub Repoository Settings with name SERVICE_ACCOUNT_KEY + SERVICE_ACCOUNT_KEY: ${{ secrets.SERVICE_ACCOUNT_KEY }} \ No newline at end of file diff --git a/.github/workflows/bump-module-version.yml b/.github/workflows/bump-module-version.yml new file mode 100644 index 0000000..28689cf --- /dev/null +++ b/.github/workflows/bump-module-version.yml @@ -0,0 +1,28 @@ +name: versionbump + +on: + push: + branches: + - master + - main + release: + types: + - released +permissions: + contents: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Bump version + run: | + git config --global user.name 'ProjectBot' + git config --global user.email 'bot@users.noreply.github.com' + VERSION=$(sed -n '0,/.*\(.*\)<\/Version>.*/s//\1/p' module.xml) + VERSION=`echo $VERSION | awk -F. '/[0-9]+\./{$NF++;print}' OFS=.` + sed -i "0,/\(.*\)<\/Version>/s//$VERSION<\/Version>/" module.xml + git add module.xml + git commit -m 'auto bump version' + git push diff --git a/.github/workflows/github-registry.yml b/.github/workflows/github-registry.yml new file mode 100644 index 0000000..d2e1234 --- /dev/null +++ b/.github/workflows/github-registry.yml @@ -0,0 +1,25 @@ +name: Build and publish a Docker image to ghcr.io +on: + + # publish on pushes to the main branch (image tagged as "latest") + # image name: will be: ghcr.io/${{ github.repository }}:latest + # e.g.: ghcr.io/intersystems-community/intersystems-iris-dev-template:latest + push: + branches: + - master + +jobs: + docker_publish: + runs-on: "ubuntu-20.04" + + steps: + - uses: actions/checkout@v2 + + # https://github.com/marketplace/actions/push-to-ghcr + - name: Build and publish a Docker image for ${{ github.repository }} + uses: macbre/push-to-ghcr@master + with: + image_name: ${{ github.repository }} + github_token: ${{ secrets.GITHUB_TOKEN }} + # optionally push to the Docker Hub (docker.io) + # docker_io_token: ${{ secrets.DOCKER_IO_ACCESS_TOKEN }} # see https://hub.docker.com/settings/security \ No newline at end of file diff --git a/.github/workflows/objectscript-quality.yml b/.github/workflows/objectscript-quality.yml new file mode 100644 index 0000000..4bda31c --- /dev/null +++ b/.github/workflows/objectscript-quality.yml @@ -0,0 +1,12 @@ +name: objectscriptquality +on: push + +jobs: + linux: + name: Linux build + runs-on: ubuntu-latest + + steps: + - name: Execute ObjectScript Quality Analysis + run: wget https://raw.githubusercontent.com/litesolutions/objectscriptquality-jenkins-integration/master/iris-community-hook.sh && sh ./iris-community-hook.sh + diff --git a/.github/workflows/runtests.yml b/.github/workflows/runtests.yml new file mode 100644 index 0000000..7464209 --- /dev/null +++ b/.github/workflows/runtests.yml @@ -0,0 +1,28 @@ +name: unittest + +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + release: + types: + - released + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build and Test + uses: docker/build-push-action@v2 + with: + context: . + push: false + load: true + tags: ${{ github.repository }}:${{ github.sha }} + build-args: TESTS=1 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..725c144 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +iris-main.log +.env +.git + diff --git a/.iris_init b/.iris_init new file mode 100644 index 0000000..5d29201 --- /dev/null +++ b/.iris_init @@ -0,0 +1,7 @@ +:alias enablebi do EnableDeepSee^%SYS.cspServer("/csp/"_$zcvt($namespace,"L")) ; +:alias ssl x "n $namespace set $namespace=""%SYS"", name=$S(""$1""="""":""DefaultSSL"",1:""$1"") do:'##class(Security.SSLConfigs).Exists(name) ##class(Security.SSLConfigs).Create(name)" ; +:alias createdb do $SYSTEM.SQL.Execute("CREATE DATABASE $1") ; +:alias installipm s r=##class(%Net.HttpRequest).%New(),r.Server="pm.community.intersystems.com",r.SSLConfiguration="ISC.FeatureTracker.SSL.Config" d r.Get("/packages/zpm/latest/installer"),$system.OBJ.LoadStream(r.HttpResponse.Data,"c") ; +:alias add%all x "n $namespace set $namespace=""%SYS"",P(""Globals"")=""%DEFAULTDB"",sc=##class(Config.Namespaces).Create(""%All"",.P)" ; +:alias exportglobal d $System.OBJ.Export("$1.GBL","$2$1.xml") ; +:alias rcc Write !,"Hi "_$namespace,! ; \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..0638285 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,17 @@ +{ + "recommendations": [ + "eamodio.gitlens", + "georgejames.gjlocate", + "github.copilot", + "intersystems-community.servermanager", + "intersystems-community.sqltools-intersystems-driver", + "intersystems-community.testingmanager", + "intersystems-community.vscode-objectscript", + "intersystems.language-server", + "mohsen1.prettify-json", + "ms-azuretools.vscode-docker", + "ms-python.python", + "ms-python.vscode-pylance", + "ms-vscode-remote.remote-containers" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7da4968 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "objectscript", + "request": "launch", + "name": "ObjectScript Debug Class", + "program": "##class(dc.sample.ObjectScript).Test()", + }, + { + "type": "objectscript", + "request": "attach", + "name": "ObjectScript Attach", + "processId": "${command:PickProcess}", + "system": true + } + ] + } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..366f779 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "files.associations": { + + "Dockerfile*": "dockerfile", + "iris.script": "objectscript" + }, + "objectscript.conn" :{ + "active": true, + "ns": "USER", + "username": "_SYSTEM", + "password": "SYS", + "docker-compose": { + "service": "iris", + "internalPort": 52773 + }, + "links": { + "UnitTest Portal": "${serverUrl}/csp/sys/%25UnitTest.Portal.Home.cls?$NAMESPACE=IRISAPP" + } + }, + "intersystems.testingManager.client.relativeTestRoot": "tests" + +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ed8eb37 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +# The most minimumalistic dockerfile possible. +# No embedded python support, no unit-testing, no aliases. +ARG IMAGE=intersystemsdc/iris-community +FROM $IMAGE + +WORKDIR /home/irisowner/dev +COPY .iris_init /home/irisowner/.iris_init + +RUN --mount=type=bind,src=.,dst=. \ + iris start IRIS && \ + iris session IRIS < iris.script && \ + iris stop IRIS quietly diff --git a/README.md b/README.md index 7c8707f..8731a1f 100644 --- a/README.md +++ b/README.md @@ -17,5 +17,32 @@ Result of example above: ![Result](https://github.com/AndreiLN/Ikon/blob/master/test.jpg) + +## DOCKER Support +### Prerequisites +Make sure you have [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [Docker desktop](https://www.docker.com/products/docker-desktop) installed. +### Installation +Clone/git pull the repo into any local directory +``` +$ git clone https://github.com/AndreiLN/Ikon.git +``` +Open the terminal in this directory and run: +``` +$ docker-compose build +``` +Run IRIS container with your project: +``` +$ docker-compose up -d +``` +Test from docker console +``` +$ docker-compose exec iris1 iris session iris +USER> +``` +or using **WebTerminal** +``` +http://localhost:42773/terminal/ +``` ## Documentation and Discussion See the [Article on InterSystems Developer Community](https://community.intersystems.com/post/identicon-generator-cach%C3%A9) + diff --git a/demo/demo.jpg b/demo/demo.jpg new file mode 100644 index 0000000..59db615 Binary files /dev/null and b/demo/demo.jpg differ diff --git a/demo/dockerdemo.jpg b/demo/dockerdemo.jpg new file mode 100644 index 0000000..bbe4fbe Binary files /dev/null and b/demo/dockerdemo.jpg differ diff --git a/dev.md b/dev.md new file mode 100644 index 0000000..c2c8a64 --- /dev/null +++ b/dev.md @@ -0,0 +1,117 @@ +# useful commands +## clean up docker +use it when docker says "There is no space left on device". It will remove built but not used images and other temporary files. +``` +docker system prune -f +``` + +``` +docker rm -f $(docker ps -qa) +``` + +## build container with no cache +``` +docker-compose build --no-cache --progress=plain +``` +## start iris container +``` +docker-compose up -d +``` + +## open iris terminal in docker +``` +docker exec iris iris session iris -U IRISAPP +``` + + +## import objectscirpt code + +do $System.OBJ.LoadDir("/home/irisowner/dev/src","ck",,1) +## map iris key from Mac home directory to IRIS in container +- ~/iris.key:/usr/irissys/mgr/iris.key + +## install git in the docker image +## add git in dockerfile +USER root +RUN apt update && apt-get -y install git + +USER ${ISC_PACKAGE_MGRUSER} + + +## install docker-compose +``` +sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + +sudo chmod +x /usr/local/bin/docker-compose + +``` + +## load and test module +``` + +zpm "load /home/irisowner/dev" + +zpm "test dc-sample" +``` + +## select zpm test registry +``` +repo -n registry -r -url https://test.pm.community.intersystems.com/registry/ -user test -pass PassWord42 +``` + +## get back to public zpm registry +``` +repo -r -n registry -url https://pm.community.intersystems.com/ -user "" -pass "" +``` + +## export a global in runtime into the repo +``` +d $System.OBJ.Export("GlobalD.GBL","/irisrun/repo/src/gbl/GlobalD.xml") +``` + +## create a web app in dockerfile +``` +zn "%SYS" \ + write "Create web application ...",! \ + set webName = "/csp/irisweb" \ + set webProperties("NameSpace") = "IRISAPP" \ + set webProperties("Enabled") = 1 \ + set webProperties("CSPZENEnabled") = 1 \ + set webProperties("AutheEnabled") = 32 \ + set webProperties("iKnowEnabled") = 1 \ + set webProperties("DeepSeeEnabled") = 1 \ + set sc = ##class(Security.Applications).Create(webName, .webProperties) \ + write "Web application "_webName_" has been created!",! +``` + + + +``` +do $SYSTEM.OBJ.ImportDir("/opt/irisbuild/src",, "ck") +``` + + +### run tests described in the module + +IRISAPP>zpm +IRISAPP:zpm>load /irisrun/repo +IRISAPP:zpm>test package-name + +### install ZPM with one line + // Install ZPM + set $namespace="%SYS", name="DefaultSSL" do:'##class(Security.SSLConfigs).Exists(name) ##class(Security.SSLConfigs).Create(name) set url="https://pm.community.intersystems.com/packages/zpm/latest/installer" Do ##class(%Net.URLParser).Parse(url,.comp) set ht = ##class(%Net.HttpRequest).%New(), ht.Server = comp("host"), ht.Port = 443, ht.Https=1, ht.SSLConfiguration=name, st=ht.Get(comp("path")) quit:'st $System.Status.GetErrorText(st) set xml=##class(%File).TempFilename("xml"), tFile = ##class(%Stream.FileBinary).%New(), tFile.Filename = xml do tFile.CopyFromAndSave(ht.HttpResponse.Data) do ht.%Close(), $system.OBJ.Load(xml,"ck") do ##class(%File).Delete(xml) + + + + +docker run --rm --name iris-sql -d -p 9091:1972 -p 9092:52773  -e IRIS_PASSWORD=demo -e IRIS_USERNAME=demo intersystemsdc/iris-community + + +docker run --rm --name iris-ce -d -p 9091:1972 -p 9092:52773 -e IRIS_PASSWORD=demo -e IRIS_USERNAME=demo intersystemsdc/iris-community -a "echo 'zpm \"install webterminal\"' | iriscli" + + + +docker run --rm --name iris-sql -d -p 9092:52773 containers.intersystems.com/intersystems/iris-community:2023.1.0.229.0 + + +docker run --rm --name iris-ce -d -p 9092:52773 containers.intersystems.com/intersystems/iris-community:2023.1.0.229.0 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..070f5d6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.6' +services: + iris: + build: + context: . + dockerfile: Dockerfile + restart: always + command: --check-caps false --ISCAgent false + ports: + - 41773:1972 + - 42773:52773 + volumes: + - ./:/home/irisowner/dev diff --git a/img/docker.jpg b/img/docker.jpg new file mode 100644 index 0000000..e83ea7e Binary files /dev/null and b/img/docker.jpg differ diff --git a/img/test.jpg b/img/test.jpg new file mode 100644 index 0000000..3aa3e35 Binary files /dev/null and b/img/test.jpg differ diff --git a/iris.script b/iris.script new file mode 100644 index 0000000..a50b716 --- /dev/null +++ b/iris.script @@ -0,0 +1,14 @@ + zn "%SYS" + + // Unexpire passwords and set up passwordless mode to simplify dev use. + // ** Comment out these two line for Production use ** + do ##class(Security.Users).UnExpireUserPasswords("*") + zpm "install passwordless" + + zn "USER" + + // Create /_vscode web app to support intersystems-community.testingmanager VS Code extension + zpm "install vscode-per-namespace-settings" + + zpm "load /home/irisowner/dev/ -v":1:1 + halt diff --git a/module.xml b/module.xml index 0c8232f..73872d5 100644 --- a/module.xml +++ b/module.xml @@ -1,14 +1,13 @@ - - - - - Ikon - 1.0.1 - Identicon generator for Intersystems Caché. Good to use in Mojo applications. - module - src - - - - - + + + + + Ikon + 1.0.2 + Identicon generator for Intersystems Caché. Good to use in Mojo applications. + module + src + + + + diff --git a/src/cls/Ikon/Identicon.cls b/src/cls/Ikon/Identicon.cls new file mode 100644 index 0000000..0afd645 --- /dev/null +++ b/src/cls/Ikon/Identicon.cls @@ -0,0 +1,224 @@ +/// Identicon Generator in COS
+/// Author: Andrei Luiz Nenevê - alneneve@gmail.com
+/// Requires: Caché 2016.2 or Newer

+/// Example:
+/// +/// ; Parameters=> Word, Directory, Size, Background amount of red, green, blue +/// Do ##class(Ikon.Identicon).%New("test","C:\Identicons\",250,255,255,155) +/// +Class Ikon.Identicon Extends %RegisteredObject +{ + +Property Name As %String; + +Property Hash As %DynamicArray; + +Property Color As %DynamicArray; + +Property Grid As %DynamicArray; + +Property GridPoint As %DynamicArray; + +Property PixelMap As %DynamicArray; + +Property Directory As %String [ InitialExpression = "C:\Identicons\" ]; + +Property FileFullName As %String; + +Property Size As %Integer [ InitialExpression = 250 ]; + +Property BackgroundColor As %String [ InitialExpression = "255,255,255" ]; + +Method HashInput() As %Status [ Private ] +{ + Set tSC = $$$OK + Try { + Set identicon = ##class(%SYSTEM.Encryption).MD5Hash(..Name) + Set ..Hash = ##class(%DynamicArray).%New() + For i=1:1:$Length(identicon){ + $$$THROWONERROR(tSC, ..Hash.%Push($ASCII($Extract(identicon,i)))) + } + } Catch tException { + Set:$$$ISOK(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method PickColor() As %Status [ Private ] +{ + Set tSC = $$$OK + Try { + Set ..Color = ##class(%DynamicArray).%New() + $$$THROWONERROR(tSC, ..Color.%Push(..Hash.%Get(0))) //Red + $$$THROWONERROR(tSC, ..Color.%Push(..Hash.%Get(1))) //Green + $$$THROWONERROR(tSC, ..Color.%Push(..Hash.%Get(2))) //Blue + } Catch tException { + Set:$$$ISOK(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method BuildGrid() As %Status [ Private ] +{ + Set tSC = $$$OK + Try { + Set ..Grid = ##class(%DynamicArray).%New() + For i=0:3:..Hash.%Size(){ + Quit:(i+3>(..Hash.%Size()-1)) + Set chunk = ##class(%DynamicArray).%New() + Set fst = ..Hash.%Get(i), sec = ..Hash.%Get(i+1) + $$$THROWONERROR(tSC, ..Grid.%Push(fst)) + $$$THROWONERROR(tSC, ..Grid.%Push(sec)) + $$$THROWONERROR(tSC, ..Grid.%Push(..Hash.%Get(i+2))) + $$$THROWONERROR(tSC, ..Grid.%Push(sec)) + $$$THROWONERROR(tSC, ..Grid.%Push(fst)) + } + } Catch tException { + Set:$$$ISOK(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method FilterOddSquares() As %Status [ Private ] +{ + Set tSC = $$$OK + Try { + Set ..GridPoint = ##class(%DynamicArray).%New() + Set iter = ..Grid.%GetIterator() + While iter.%GetNext(.key,.value){ + If value # 2 = 0{ + Set obj = ##class(%DynamicObject).%New() + Set obj.key = key + Set obj.value = value + $$$THROWONERROR(tSC, ..GridPoint.%Push(obj)) + } + } + } Catch tException { + Set:$$$ISOK(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method BuildPixelMap() As %Status [ Private ] +{ + Set tSC = $$$OK + Try { + Set ..PixelMap = ##class(%DynamicArray).%New() + Set iter = ..GridPoint.%GetIterator() + While iter.%GetNext(.key,.value){ + Set horizontal = (value.key # 5) * (..Size/5) + Set vertical = (value.key \ 5) * (..Size/5) + + Set point = ##class(%DynamicObject).%New() + + Set cord = ##class(%DynamicObject).%New() + $$$THROWONERROR(tSC, cord.%Set("x",horizontal)) + $$$THROWONERROR(tSC, cord.%Set("y",vertical)) + $$$THROWONERROR(tSC, point.%Set("topLeft",cord)) + + Set cord = ##class(%DynamicObject).%New() + $$$THROWONERROR(tSC, cord.%Set("x",horizontal+(..Size/5))) + $$$THROWONERROR(tSC, cord.%Set("y",vertical+(..Size/5))) + $$$THROWONERROR(tSC, point.%Set("bottomRight",cord)) + + $$$THROWONERROR(tSC, ..PixelMap.%Push(point)) + } + } Catch tException { + Set:$$$ISOK(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method GenerateFileName() As %Status [ Private ] +{ + Set tSC = $$$OK + Try { + If '##class(%File).DirectoryExists(..Directory) { + Set tSC = ##class(%File).CreateDirectoryChain(..Directory) + } + Set ..FileFullName = ..Directory_..Name_".jpg" + } Catch tException { + Set:$$$ISOK(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method CreateImage() As %Status [ Private ] +{ + Set tSC = $$$OK + Try { + Set tBack = $ListFromString(..BackgroundColor,",") + Set tImage = ##class(Ikon.Processor).New(..Size,..Size,$List(tBack,1),$List(tBack,2),$List(tBack,3)) + Do tImage.SetPen(..Color.%Get(0),..Color.%Get(1),..Color.%Get(2)) + Set iter = ..PixelMap.%GetIterator() + While iter.%GetNext(.key,.value){ + Set posInicialX = value.topLeft.x + Set posInicialY = value.topLeft.y + Set posFinalX = value.bottomRight.x + Set posFinalY = value.bottomRight.y + For y=posInicialY:1:posFinalY{ + For x=posInicialX:1:posFinalX{ + Do tImage.Plot(x,y) + } + } + } + s a=..FileFullName + o a:"WNS":10 e + u a + d tImage.WriteBitmap() + c a + d tImage.%Close() + } Catch tException { + Set:$$$ISOK(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method Generate(pName As %String = "Caché", pDirectory As %String = "", pSize = 250, Red As %Integer = 255, Green As %Integer = 255, Blue As %Integer = 255) As %Status +{ + Set tSC = $$$OK + Try { + Set:pName'="" ..Name = pName + Set:pDirectory'="" ..Directory = pDirectory + Set ..BackgroundColor = Red_","_Green_","_Blue + Set ..Size = pSize + $$$THROWONERROR(tSC, ..HashInput()) + $$$THROWONERROR(tSC, ..PickColor()) + $$$THROWONERROR(tSC, ..BuildGrid()) + $$$THROWONERROR(tSC, ..FilterOddSquares()) + $$$THROWONERROR(tSC, ..BuildPixelMap()) + $$$THROWONERROR(tSC, ..GenerateFileName()) + $$$THROWONERROR(tSC, ..CreateImage()) + Write !,"File '"_..Directory_..Name_"' successfully generated!",! + } Catch tException { + Set:$$$ISERR(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +Method %OnNew(pName As %String = "", pDirectory As %String = "", pSize = 250, Red As %Integer = 255, Green As %Integer = 255, Blue As %Integer = 255) As %Status [ Private, ServerOnly = 1 ] +{ + Set tSC = $$$OK + Try { + Set:pName'="" ..Name = pName + Set:pDirectory'="" ..Directory = pDirectory + Set ..BackgroundColor = Red_","_Green_","_Blue + Set ..Size = pSize + If pName'=""{ + $$$THROWONERROR(tSC, ..HashInput()) + $$$THROWONERROR(tSC, ..PickColor()) + $$$THROWONERROR(tSC, ..BuildGrid()) + $$$THROWONERROR(tSC, ..FilterOddSquares()) + $$$THROWONERROR(tSC, ..BuildPixelMap()) + $$$THROWONERROR(tSC, ..GenerateFileName()) + $$$THROWONERROR(tSC, ..CreateImage()) + Write !,"File '"_..Directory_..Name_"' successfully generated!",! + } + } Catch tException { + Set:$$$ISERR(tSC) tSC = tException.AsStatus() + } + Quit tSC +} + +} + diff --git a/src/cls/Ikon/Processor.cls b/src/cls/Ikon/Processor.cls new file mode 100644 index 0000000..75f9692 --- /dev/null +++ b/src/cls/Ikon/Processor.cls @@ -0,0 +1,83 @@ +/// This class is a refactored version from Captcha generator originally made by Fabio Gonçalves +///
This refactored version to do the generation of identicons was made by Andrei Luiz Nenevê +Class Ikon.Processor Extends %RegisteredObject [ ClassType = "", Not ProcedureBlock ] +{ + +Property Data [ MultiDimensional ]; + +Property Width As %Integer; + +Property Height As %Integer; + +Property PenColor As %String(TRUNCATE = 1); + +ClassMethod New(width As %Integer, height As %Integer, red As %Integer = 255, green As %Integer = 255, blue As %Integer = 255) As Ikon.Processor +{ + Set img = ##class(Ikon.Processor).%New() + Set img.Width = width,img.Height = height + For x = 1:1:width{ + For y = 1:1:height{ + Set img.Data(x,y) = $Char(blue,green,red) + } + } + Do img.SetPen(0,0,0) + Quit img +} + +Method SetPen(red As %Integer, green As %Integer, blue As %Integer) As %Status +{ + Set ..PenColor = $Char(blue,green,red) + Quit $$$OK +} + +Method Plot(x As %Integer, y As %Integer) As %Status +{ + Quit:(x<1||y<1||y>..Height||x>..Width) 1 + Set ..Data(x,y) = ..PenColor + Quit $$$OK +} + +ClassMethod SetBytes(decimal As %Integer, length As %Integer) As %String +{ + Set ret = "" + For i = 1:1:length{ + Set ret = ret_$Char(decimal#256), decimal = decimal/256 + } + Quit ret +} + +Method WriteBitmap() +{ + Set bfType = "BM", + bfSize = 0, + bfReserved1 = ..SetBytes(0,2), + bfReserved2=..SetBytes(0,2), + bfOffsetBits=..SetBytes(54,4), + biSize=..SetBytes(40,4), + biWidth=..SetBytes(..Width,4), + biHeight=..SetBytes(..Height,4), + biPlanes=..SetBytes(1,2), + biBitCount=..SetBytes(24,2), + biCompression=..SetBytes(0,4), + biSizeImage=..SetBytes(0,4), + biXPelsPerMeter=..SetBytes(0,4), + biYPelsPerMeter=..SetBytes(0,4), + biColorsUsed=..SetBytes(0,4), + biColorsImportant=..SetBytes(0,4), + padding=(..Width*3)#4, + padding=$s(padding=0:"",1:$e($c(0,0,0),1,4-padding)), + sizeimage=((..Width*3)+$l(padding))*..Height, + bfSize=..SetBytes(14+40+sizeimage,4), + biSizeImage=..SetBytes(sizeimage,4) + Write bfType_bfSize_bfReserved1_bfReserved2_bfOffsetBits + Write biSize_biWidth_biHeight_biPlanes_biBitCount_biCompression_biSizeImage_biXPelsPerMeter_biYPelsPerMeter_biColorsUsed_biColorsImportant + For y = ..Height:-1:1 { + For x=1:1:..Width { + Write ..Data(x,y) + } + Write padding + } +} + +} +