Annoator API¶
System specific binary should be rebuilt. Otherwise this could introduce misalignment errors and for Dependency Parser the requirement is Java Runtime Environment :)
-
class
pntl.tools.
Annotator
(senna_dir='', stp_dir='', dep_model='edu.stanford.nlp.trees.EnglishGrammaticalStructure', raise_e=False, save_all=False, env=False, env_path='')[source]¶ :Class:~pntl.Annotator is a class which holds the nessary function.
-
check_stp_jar
(path, raise_e=False, _rec=True)[source]¶ Check the stanford parser is present in the given directions and nested searching will be added in futurwork
Parameters: - path (str) – path of where the stanford parser is present
- raise_e (bool) – to raise exception with user wise and default False don’t raises exception
Returns: given path if it is valid one or return boolean False or if raise FileNotFoundError on raise_exp=True
Return type: bool
-
get_annoations
(sentence='', senna_tags=None, dep_parse=True)[source]¶ passing the string to senna and performing aboue given nlp process and the returning them in a form of dict()
Parameters: - or list sentence (str) – a sentence or list of sentence for nlp process.
- or list senna_tags (str) – this values are by SENNA processed string
- batch (bool) – the change the mode into batch processing process
- dep_parse (bool) – to tell the code and user need to communicate with stanford parser
Returns: the dict() of every out in the process such as ner, dep_parse, srl, verbs etc.
Return type: dict
-
get_batch_annotations
(sentences, dep_parse=True)[source]¶ Parameters: sentences (list) – list of sentences Return type: list
-
get_conll_format
(sentence, options='-srl -pos -ner -chk -psg')[source]¶ Communicates with senna through lower level communiction (sub process) and converted the console output(default is file writing) with CoNLL format and argument to be in options pass
Parameters: - or list (str) – list of sentences for batch processes
- list (options) – list of arguments
options desc -verbose Display model informations (on the standard error output, so it does not mess up the tag outputs). -notokentags Do not output tokens (first output column). -offsettags Output start/end character offset (in the sentence), for each token. -iobtags Output IOB tags instead of IOBES. -brackettags Output ‘bracket’ tags instead of IOBES. -path Specify the path to the SENNA data and hash directories, if you do not run SENNA in its original directory. The path must end by “/”. -usrtokens Use user’s tokens (space separated) instead of SENNA tokenizer. -posvbs Use verbs outputed by the POS tagger instead of SRL style verbs for SRL task. You might want to use this, as the SRL training task ignore some verbs (many “be” and “have”) which might be not what you want. -usrvbs Use user’s verbs (given in ) instead of SENNA verbs for SRL task. The file must contain one line per token, with an empty line between each sentence. A line which is not a “-” corresponds to a verb. -pos Instead of outputing tags for all tasks, SENNA will output tags for the specified (one or more) tasks. -chk Instead of outputing tags for all tasks, SENNA will output tags for the specified (one or more) tasks. -ner Instead of outputing tags for all tasks, SENNA will output tags for the specified (one or more) tasks. -srl Instead of outputing tags for all tasks, SENNA will output tags for the specified (one or more) tasks. -psg Instead of outputing tags for all tasks, SENNA will output tags for the specified (one or more) tasks. Returns: senna tagged output Return type: str
-
get_dependency
(parse)[source]¶ Change to the Stanford parser direction and process the works
Parameters: parse (str) – parse is the input(tree format) and it is writen in as file Returns: stanford dependency universal format Return type: str
-
get_senna_bin
(os_name)[source]¶ get the current os executable binary file.
Parameters: os_name (str) – os name like Linux, Darwin, Windows Returns: the corresponding exceutable object file of senna Return type: str
-
get_senna_tag
(input_data)[source]¶ Communicates with senna through lower level communiction(sub process) and converted the console output(default is file writing)
:param str/list input_data : list of sentences for batch processes :return: senna tagged output :rtype: str
-
get_senna_tag_batch
(sentences)[source]¶ Communicates with senna through lower level communiction(sub process) and converted the console output(default is file writing). On batch processing each end is add with new line.
Parameters: sentences (list) – list of sentences for batch processes Return type: str
-
classmethod
help_conll_format
()[source]¶ With the help of this method, detail of senna arguments are displayed
-
jar_cli
¶ The return cli for standford-parser.jar(this is python @property)
Return type: string
-
print_values
()[source]¶ displays the current set of values such as SENNA location, stanford parser jar, jar command interface
-
senna_dir
¶ The return the path of senna location and set the path for senna at run time(this is python @property)
Return type: string
-
stp_dir
¶ The return the path of stanford parser jar location and set the path for Dependency Parse at run time( this is python @property)
-


26 minutes
Jenkins X Orchestration: More than Tekton on Steroids
We may know Jenkins X as a new pure CI/CD cloud native implementation different than Jenkins. It is based on the use of Kubernetes Custom Resource Definitions (CRD’s) to experience a seamless execution of CI/CD pipelines. This happens by leveraging the power of Kubernetes in terms of scalability, infrastructure abstraction and velocity.
The new main approach of Jenkins X is about a serverless experience, because there is no more traditional Jenkins engine running. So, it relies on a CI/CD pipeline engine that can run on any standard Kubernetes deployment. This engine is the Tekton CD project , a former Google project that is also - like Jenkins X - part of the Continuous Delivery Foundation.
In this post, we are showing the power of Tekton as a decoupled CI/CD pipeline engine execution. But more important, why an orchestration pipeline platform is practically required to design, configure and run your pipelines for the whole Software Delivery process. This orchestration platform is Jenkins X.
The Tekton base
Why then is Tekton a cool CI/CD engine?
First of all, Tekton is built on and for Kubernetes. This means that containers are the building blocks of any pipeline definition and execution. Kubernetes orchestrates the container’s magic. One step, one container. But it’s more than that:
- Everything is decoupled. So for example, a group of steps, or any pipeline resource can be shared and reused accross different pipeline executions.
- Kubernetes is the platform, meaning that pipelines can be deployed and executed basically anywhere.
- Sequential execution of
Tasks
defines aPipeline
. So creating a pipeline conceptually is as easy as defining the order of the tasks that we want to run and that may be already deployed in our Kubernetes cluster. - Any task can be run by instantiating it from a parametrized
TaskRun
. Because every previous task can be parametrized, reusing them is just a matter of calling the right task with a specific parameter. Again, decoupling and reusing. - Pipelines usually consume different resources like code, containers, files, etc. So Tekton uses
PipelineResources
as inputs and outputs between tasks to execute the pipeline workflow. That means that pipeline resources can be shared between pipelines in a descriptive way. - Every pipeline component is a CRD, so pipeline execution is a matter of containers orchestration, something that Kubernetes does really well and pretty fast. It is reliable, stable, scalable and performant.
Let’s try to understand Tekton pipelines decoupled architecture in the following diagram :
In terms of scalability, it’s a nice way to isolate objects that can be reused easily, right?
Decoupling CI/CD is good, but…
Tekton then is about the power of a decoupled CI/CD engine, which has many advantages. But no one said that defining decoupled CI/CD pipelines was an easy task. It can be complex from a conceptual point of view if you don’t change your mindset. Traditionally, we’ve been defining pipelines as different stages with their current steps to be executed. So, everything is only about how to orchestrate stages as sequential or parallel tasks, configuring parameters or conditions into the pipeline. Let’s say that CI/CD has a monolithic mindset to configure and define pipelines.
If we start designing reusable components, then the resources, the pipeline flow, the execution parametrization and then feeding all components back and forth… This can be messy and error prone till having the complete decoupled pipeline map configured.
An orchestration engine to manage pipelines
We might think about how to orchestrate this. Let’s then think about three decoupling best practices for pipelines in containerized ecosystems:
- The CI/CD execution must be flexible, reusable and decoupled.
- The pipeline orchestration must be manageable, understandable and easy to deploy.
- Resources configuration for pipeline components needs to be standardized and easy to manage.
CI/CD in not only about designing automation pipelines to deliver software. It is also about managing and providing all resources required for automation execution. In Kubernetes we will need to deal also with different objects like Secrets
, ServiceAccounts
, PersistentVolumes
, ConfigMaps
, Ingress
, etc.
To focus on CI/CD pipelines, resources management should be an easy task.
An example to understand Tekton and Jenkins X orchestration
We are using an example of building an application by defining and running CI/CD pipelines with standalone Tekton. Then, we are taking the same application to see how Jenkins X pipelines, using Tekton, generate similar objects but from a different focus. It will show how pipeline orchestration capabilities are applied to a decoupled CI/CD pipeline engine, no matter how I need to deal with platform or infrastructure resources.
To do that we are using a well known Spring Petclinic example Spring Boot application. And let’s use a repo that is using traditional Jenkins pipeline to build the application, create a Docker container and deploy into Kubernetes cluster.
In my traditional Jenkins example I use two pipelines in fact that are automated using CloudBees Core Cross Team Collaboration feature:
- Repo with a Jenkins pipeline to build the app, the Docker container and push it into Docker Registry
- A simple Jenkins pipeline repo to deploy the previous container published
But in our case, we are putting those pipeline steps into one pipeline to do the build and deploy. First with a “pure Tekton” pipeline definition, and later using Jenkins X serverless pipelines.
The pure Tekton way
So let’s try to configure and execute the pipeline from a pure Tekton pipeline point of view. That means:
- Creating
PipelineResources
that are going to be used byTasks
- Defining and creating
Tasks
that contain the steps to be executed in thePipeline
- Defining and creating the
Pipeline
that orchestrates the execution ofTasks
withResources
- Creating the
PipelineRun
- Installing required Kubernetes resources, like
Secrets
,ServiceAccounts
or permissions, in order to execute required steps within right containers (e.g. secrets used by Kaniko builder)
I already created a GitHub Repo with all YAML files needed (except secrets, which are explained in the README
file). But let’s go through them.
We can create a YAML file with all Tasks
objects and the Pipeline
definition. We can call this file petclinic-pipeline.yaml
:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: build-maven
spec:
inputs:
resources:
- name: workspace
type: git
params:
- name: workingDir
description: Working directory parameter
default: /workspace/workspace
outputs:
resources:
- name: workspace
type: git
steps:
- name: maven-build
image: gcr.io/cloud-builders/mvn:3.5.0-jdk-8
workingDir: ${inputs.params.workingDir}
command: ["mvn"]
args:
- "clean"
- "install"
- name: ls-target
image: ubuntu
command:
- "ls"
args:
- "-la"
- "/workspace/workspace/target"
---
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: build-kaniko
spec:
inputs:
resources:
- name: workspace
type: git
targetPath: petclinic
params:
- name: workingDir
description: Working directory parameter
default: /workspace/petclinic
- name: DockerFilePath
decription: Path to DockerFile
default: /workspace/petclinic/Dockerfile
outputs:
resources:
- name: dockerImage
type: image
steps:
- name: kaniko-build
image: gcr.io/kaniko-project/executor:latest
command:
- /kaniko/executor
args:
- "--dockerfile=${inputs.params.DockerFilePath}"
- "--context=${inputs.params.workingDir}"
- "--destination=${outputs.resources.dockerImage.url}"
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: /secret/kaniko-secret.json
volumeMounts:
- name: kaniko-secret
mountPath: /secret
volumes:
- name: kaniko-secret
secret:
secretName: emea-sa-secret
---
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: deploy-kubectl
spec:
inputs:
resources:
- name: workspacedeploy
type: git
params:
- name: workingDir
description: Working directory parameter
default: /workspace/workspacedeploy
- name: deployFile
description: Deployment file for app
default: test-deploy.yaml
# Just a parameter to check the depployment name, because one step will force redeploy
- name: deploymentName
description: The K8s deployment object name
default: petclinic
steps:
- name: kubectl-clean
image: gcr.io/cloud-builders/kubectl:latest
workingDir: ${inputs.params.workingDir}
command: ["/bin/bash"]
args:
- -c
- MYDEPLOY=$(kubectl get deployments -l app=petclinic -o name | awk -F'/' '{print $2}');
- if [ "$MYDEPLOY" = "${inputs.params.deploymentName}" ];
- then kubectl delete deployment $MYDEPLOY;
- fi
- name: kubectl-deploy
image: gcr.io/cloud-builders/kubectl:latest
workingDir: ${inputs.params.workingDir}
command: ["kubectl"]
args:
- apply
- -f
- ${inputs.params.deployFile}
---
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: petclinic-pipeline
spec:
resources:
- name: source-repo
type: git
- name: docker-container
type: image
- name: deploy-repo
type: git
tasks:
- name: petclinic-maven
taskRef:
name: build-maven
resources:
inputs:
- name: workspace
resource: source-repo
outputs:
- name: workspace
resource: source-repo
- name: petclinic-kaniko
taskRef:
name: build-kaniko
resources:
inputs:
- name: workspace
resource: source-repo
from:
- petclinic-maven
outputs:
- name: dockerImage
resource: docker-container
- name: petclinic-deploy
taskRef:
name: deploy-kubectl
runAfter:
- petclinic-kaniko
resources:
inputs:
- name: workspacedeploy
resource: deploy-repo
params:
- name: deployFile
value: test-deploy-secret.yaml
Then we can define also a file pipeline-resources.yaml
with all required PipelineResources
objects needed:
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: petclinic-git
spec:
type: git
params:
- name: url
value: https://github.com/dcanadillas/petclinic-kaniko.git
---
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: petclinic-image
spec:
type: image
params:
- name: url
value: eu.gcr.io/emea-sa-demo/petclinic-kaniko:latest
---
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
name: petclinic-deploy
spec:
type: git
params:
- name: url
value: https://github.com/dcanadillas/petclinic-kaniko-deploy.git
As PipelineResources
we are using the two GitHub repositories from the original repos as inputs (one for the application and the other for deployment definitions), and one container image as output to be built.
Next, let’s define the PipelineRun
, that executes and instantiate the pipeline, in a file petclinic-run.yaml
:
apiVersion: tekton.dev/v1alpha1
kind: PipelineRun
metadata:
name: petclinic-pipelinerun
spec:
pipelineRef:
name: petclinic-pipeline
serviceAccount: 'default'
serviceAccounts:
- taskName: petclinic-deploy
serviceAccount: tekton-deployment
resources:
- name: source-repo
resourceRef:
name: petclinic-git
- name: docker-container
resourceRef:
name: petclinic-image
- name: deploy-repo
resourceRef:
name: petclinic-deploy
In the PipelineRun
object it’s important to understand that it is intended in the way of defining the specific running instance of a deployed pipeline. It’s the right place to assign running input/output parameter values, specify serviceAccounts
to be used, or referencing the right PipelineResources
to be used.
Once we have the YAML definitions, it’s only a matter of Kubernetes deployment of the Tekton CRD objects. We can use then kubectl
command line tool to deploy first the two YAML files with PipelineResources
, Tasks
and Pipeline
:
$ kubectl apply -f petclinic-resources.yaml,petclinic-pipeline.yaml
pipelineresource.tekton.dev/petclinic-git created
pipelineresource.tekton.dev/petclinic-image created
pipelineresource.tekton.dev/petclinic-deploy created
task.tekton.dev/build-maven created
task.tekton.dev/build-kaniko created
task.tekton.dev/deploy-kubectl created
pipeline.tekton.dev/petclinic-pipeline created
We can see then the objects already deployed, as CRDs
objects.
$ kubectl get tasks,pipelines,pipelineresources
NAME AGE
task.tekton.dev/build-kaniko 2s
task.tekton.dev/build-maven 2s
task.tekton.dev/deploy-kubectl 2s
NAME AGE
pipeline.tekton.dev/petclinic-pipeline 2s
NAME AGE
pipelineresource.tekton.dev/petclinic-deploy 2s
pipelineresource.tekton.dev/petclinic-git 2s
pipelineresource.tekton.dev/petclinic-image 2s
And we can check the pipeline to be executed:
$ kubectl describe pipeline.tekton.dev/petclinic-pipeline
Name: petclinic-pipeline
Namespace: tekton-pipelines
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"tekton.dev/v1alpha1","kind":"Pipeline","metadata":{"annotations":{},"name":"petclinic-pipeline","namespace":"tekton-pipelin...}}
API Version: tekton.dev/v1alpha1
Kind: Pipeline
Metadata:
Creation Timestamp: 2019-07-13T10:19:12Z
Generation: 1
Resource Version: 22835394
Self Link: /apis/tekton.dev/v1alpha1/namespaces/tekton-pipelines/pipelines/petclinic-pipeline
UID: a8d4e6ca-a557-11e9-b2c9-42010a8400ab
Spec:
Resources:
Name: source-repo
Type: git
Name: docker-container
Type: image
Name: deploy-repo
Type: git
Tasks:
Name: petclinic-maven
Resources:
Inputs:
Name: workspace
Resource: source-repo
Outputs:
Name: workspace
Resource: source-repo
Task Ref:
Name: build-maven
Name: petclinic-kaniko
Resources:
Inputs:
From:
petclinic-maven
Name: workspace
Resource: source-repo
Outputs:
Name: dockerImage
Resource: docker-container
Task Ref:
Name: build-kaniko
Name: petclinic-deploy
Params:
Name: deployFile
Value: test-deploy-secret.yaml
Resources:
Inputs:
Name: workspacedeploy
Resource: deploy-repo
Run After:
petclinic-kaniko
Task Ref:
Name: deploy-kubectl
Events: <none>
Pipeline
object is going to execute in order the tasks already existing in K8s cluster: build-maven
, build-kaniko
and deploy-kubectl
. And for that we are setting as inputs and outputs the different PipelineResources
.
But we are using some resources expected in the cluster that are not created at pipeline definition, like Secrets
for pushing into private Docker Registry (GCR in my case), ServiceAccount
, Roles
and RoleBindings
to deploy in Kubernetes with the specific permissions. I am not focusing on doing this at this post, but you can read how to do it in my original repo documentation.
Now, running the pipeline is just about deploying the PipelineRun
definition in our pipeline-run.yaml
file:
kubectl apply -f petclinic-run.yaml
A Tekton CRD
is then created to run the pipeline.
pipelinerun.tekton.dev/petclinic-pipelinerun created
Different things are going to happen in this case:
- The
PipelineRun
is going to create aTaskRun
perTask
. Than means that every stage of the pipeline is going to be executed within theTask
definition already deployed, depending on thePipeline
flow created - Every
TaskRun
is going to be executed in a KubernetesPod
, using the containers specified in the differentSteps
inTasks
. Remember about Tekton: One step. One container. PipelineResources
are just “consumed or produced” byTasks
depending on the parameters used duringTaskRuns
- Different
ServiceAccounts
are going to be used forTasks
depending on the definition of thePipelineRun
(it makes sense that different roles are needed for different tasks)
So, if we take a look about our execution after the complete run:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
petclinic-6f668b59b5-w8zrr 1/1 Running 0 21s
petclinic-pipelinerun-petclinic-deploy-54kws-pod-c5a511 0/3 Completed 0 1m
petclinic-pipelinerun-petclinic-kaniko-s4nnw-pod-67721d 0/4 Completed 0 1m
petclinic-pipelinerun-petclinic-maven-9gnpf-pod-fa757f 0/5 Completed 0 4m
tekton-pipelines-controller-6b565f9859-knqsb 1/1 Running 0 8h
tekton-pipelines-webhook-7f47c995cd-db2rv 1/1 Running 0 8h
And we can check that TaskRuns
where created:
$ kubectl get taskruns
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
petclinic-pipelinerun-petclinic-deploy-54kws True Succeeded 2h 2h
petclinic-pipelinerun-petclinic-kaniko-s4nnw True Succeeded 2h 2h
petclinic-pipelinerun-petclinic-maven-9gnpf True Succeeded 2h 2h
Looking inside at one of them we can see the execution status and completion:
$ kubectl describe taskrun/petclinic-pipelinerun-petclinic-kaniko-s4nnw
[...]
Status:
Completion Time: 2019-07-15T18:13:25Z
Conditions:
Last Transition Time: 2019-07-15T18:13:25Z
Message: All Steps have completed executing
Reason: Succeeded
Status: True
Type: Succeeded
Pod Name: petclinic-pipelinerun-petclinic-kaniko-s4nnw-pod-67721d
Start Time: 2019-07-15T18:12:55Z
Steps:
Name: kaniko-build
Terminated:
Container ID: docker://f077cc23c848bb5a937201719543db01d8cfd2712dabfb577df4b02b8c32b704
Exit Code: 0
Finished At: 2019-07-15T18:13:24Z
Reason: Completed
Started At: 2019-07-15T18:13:09Z
Name: image-digest-exporter-kaniko-build-ldh8q
Terminated:
Container ID: docker://106f2819a96246761eed0486e2f66428dafb38cdff291c3004e9e75d9a245963
Exit Code: 0
Finished At: 2019-07-15T18:13:24Z
Message: []
Reason: Completed
Started At: 2019-07-15T18:13:12Z
Name: create-dir-workspace-sgtdd
Terminated:
Container ID: docker://f80a5a1da2898e78edcaf2110d0adb304131ff7f07a14b4e40ab8a03a9f69167
Exit Code: 0
Finished At: 2019-07-15T18:13:13Z
Reason: Completed
Started At: 2019-07-15T18:13:06Z
Name: source-copy-workspace-8dmsp
Terminated:
Container ID: docker://081e363b08f7fe1d8bd21efa36c670531a6cbc5debf09b2662d8b27340d9ad48
Exit Code: 0
Finished At: 2019-07-15T18:13:14Z
Reason: Completed
Started At: 2019-07-15T18:13:06Z
Events: <none>
Finally, the application should have been deployed. Let’s check:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
petclinic-service LoadBalancer <IP_ADDRESS> <IP_ADDRESS> 9090:31261/TCP 12m
tekton-pipelines-controller ClusterIP <IP_ADDRESS> <none> 9090/TCP 11d
tekton-pipelines-webhook ClusterIP <IP_ADDRESS> <none> 443/TCP 11d
We then confirmed that this kind of pipeline definition and execution in Kubernetes can be extremely powerful in terms of reusability and extensibility. We’ve just deployed tasks definitions, ordering and resources descriptions, and running specification. Everything is about playing with Cloud Native resources to deal with CI/CD pipeline objects and executions.
But let’s face it. This is not a very easy way of executing pipelines. Powerful, but complex from a conceptual pipeline design.
Playing with Jenkins X Serverless Pipelines
We can think about orchestrating the previous application pipeline with Tekton to simplify it’s usage and make it “manageable”. Jenkins X is a very good solution to do that, because:
- Jenkins X build packs give you pre-set pipelines (among other things) for your applications. You can then start with a prepared and curated conceptual design that is easy to manage.
- Jenkins X is not a pipeline engine, it’s a CI/CD solution. So all resources like Git repos, users,
serviceAccounts
, environmentnamespaces
,ingress
rules, Docker Registry credentials, etc. are already configured to be able to orchestrate pipeline execution. - Configuring or extending pipeline definitions is just a matter of defining the flow of stages with their steps/containers to be executed. And Tekton is used automatically to decouple run definition and execution. Monolithic abstraction, decoupled execution.
- Jenkins X Pipelines simplify any pipeline process to develop features, release or promote/deploy your code through environments.
To understand what we mean about Tekton orchestration, let’s try to simulate the same tasks and steps in our previous Tekton example, but defining a basic Jenkins X serverless pipeline without using build packs.
NOTE: Don’t think about this as a standard way to work with Jenkins X. We are showing first a standalone jenkins-x.yml
pipeline to demonstrate how Tekton objects are created and orchestrated automatically by Jenkins X.
Jenkins X cluster creation and installation it’s just a matter of minutes. So, to start executing pipelines we’ll start to deploy a Jenkins X cluster from scracth in GKE after installing the Jenkins X CLI (showing parameters instead of values):
jx create cluster gke \
--cluster-name ${JX_CLUSTER} \
--default-admin-password ${MYPWD} \
--environment-git-owner ${GH_ORG} \
--min-num-nodes 3 --max-num-nodes 5 \
--machine-type n1-standard-2 \
--project-id ${GCP_PROJECT} --zone europe-west1-c \
--default-environment-prefix ${JX_CLUSTER} \
--git-provider-kind github \
--git-username ${GH_USER} \
--git-api-token ${GH_APITOKEN} \
--tekton \
--no-tiller \
-b
Once having the Jenkins X installation (serverless mode with Prow and Tekton), you can check that Tekton CRDs
are already there:
$ kubectl get crd
NAME CREATED AT
[...]
pipelineresources.tekton.dev 2019-07-10T11:38:50Z
pipelineruns.tekton.dev 2019-07-10T11:38:50Z
pipelines.tekton.dev 2019-07-10T11:38:50Z
[...]
taskruns.tekton.dev 2019-07-10T11:38:50Z
tasks.tekton.dev 2019-07-10T11:38:50Z
[...]
Right now, let’s try to simulate the Tekton pipeline that we executed before from a “standalone” Jenkins X YAML pipeline. This means, as mentioned before, that we are not using any Jenkins X Build Packs
.
If we clone the same petclinic-kaniko repo into a local directory petclinic-jenkins-x
we can do the following (working from local):
- Deleting any Git repo reference from the local cloned directory with
rm -r ./.git*
so we are working for sure from a local copy - Create in the local directory the following
jenkins-x.yml
file that simulates demaven-build
,kaniko-build
andkubectl-deploy
tasks from our previous Tekton example (for simplicity we are not adding the step used before to check deployment):
buildPack: none
pipelineConfig:
pipelines:
release:
pipeline:
stages:
- name: Maven Build
agent:
image: maven
steps:
- command: mvn
args:
- clean
- install
- name: Kaniko Build
agent:
image: gcr.io/kaniko-project/executor:latest
steps:
- command: /kaniko/executor
args:
- "--dockerfile=Dockerfile"
- "--context=/workspace/source"
- "--destination=eu.gcr.io/emea-sa-demo/petclinic-kaniko:latest"
- name: Kubectl Deploy
agent:
image: gcr.io/cloud-builders/kubectl:latest
steps:
- command: kubectl
args:
- apply
- -f
- https://github.com/dcanadillas/petclinic-kaniko-deploy/blob/master/test-deploy.yaml?raw=true
- -n
- jx-staging
- Import the project with Jenkins X from the local directory:
$ jx import --git-username dcanadillas --org jx-dcanadillas --name petclinic-jenkins-x -m YAML
[...]
? Git user name: dcanadillas
The directory /Users/david/Documents/Workspace/Technologists/petclinic-kaniko is not yet using git
? Would you like to initialise git now? Yes
? Commit message: Initial import
[...]
? Using organisation: jx-dcanadillas
? Enter the new repository name: petclinic-jenkins-x
[...]
NOTE: We could have imported first the project and then changed the jenkins-x.yml
. In that case Jenkins X would have detected to apply a Maven Build Pack
doing the first run with it. But I wanted to force Jenkins X to not recognize any Build Pack
from the beggining, so there is no pipeline execution different than the one we want to simulate.
Then the first pipeline execution is automatically run, because Jenkins X creates the GitHub repo with its webhook for you.  If we search for Tekton components, we can check that everything is created by Jenkins X for the Tekton engine execution:
$ kubectl get tasks,tasks,taskruns,pipeline,pipelineruns
NAME AGE
task.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-kaniko-build-2 7m
task.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-kubectl-deploy-2 7m
task.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-maven-build-2 7m
NAME AGE
taskrun.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-2-kaniko-build-kpk8v 4m
taskrun.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-2-kubectl-deploy-scs4r 4m
taskrun.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-2-maven-build-d42f4 7m
NAME AGE
pipeline.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-2 7m
NAME AGE
pipelinerun.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88-2 7m
There they are. The same components that were created “manually” in our previous Tekton example. Truth is that Tasks
configurations in this case use more parameters inside (DOCKER_REGISTRY
, REPO_OWNER
, PIPELINE_KIND
, BUILD_NUMBER
, APP_NAME
, VERSION
… and more) that are configured by Jenkins X. But that is the thing. Just because Jenkins X is orchestrating the pipeline execution from a simpler definition it’s abstracting some configurations for you and using some parameters to make it easier.
If we check the pods used by the pipeline execution we will find again three of them (one pod per Tekton task):
$ kubectl get pod -n jx
NAME READY STATUS RESTARTS AGE
[...]
jx-dcanadillas-petclinic-jenkin-rhg88-2-kaniko-build-kpk8v-pod-4dd505 0/6 Completed 0 3m41s
jx-dcanadillas-petclinic-jenkin-rhg88-2-kubectl-deploy-scs4r-pod-a2f48a 0/4 Completed 0 2m52s
jx-dcanadillas-petclinic-jenkin-rhg88-2-maven-build-d42f4-pod-432bb5 0/6 Completed 0 6m14s
[...] 1/1 Running 0 5d10h
tekton-pipelines-controller-687cfbcc89-69jht 1/1 Running 0 5d10h
tekton-pipelines-webhook-7fd7f8cdcc-pqv4c 1/1 Running 0 5d10h
tide-5f8fb5964c-29pgt 1/1 Running 0 5d10h
And we can check that same application has been deployed in the namespace jx-staging
:
$ kubectl get svc petclinic-service -n jx-staging
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
petclinic-service LoadBalancer <IP_ADDRESS> <IP_ADDRESS> 9090:31194/TCP 10m
We can conclude about the following about simulating the same Tekton configuration with Jenkins X Pipelines:
- CI/CD pipeline was designed in one YAML file of a couple of lines, instead of defining several YAML files with cross-reference definitions (we could have defined one YAML file for the Tekton example, but would have been very big file with lots of lines of code and not very manageable).
- Jenkins X, from that monilithic simple definition, creates automatically all Tekton decoupled components (
Tasks
,Pipeline
,PipelineResources
,PipelineRuns
, etc.). - There is no need to define any secret or serviceAccount. Jenkins X configures the platform parameters automatically when installing, passing those parameters to the pipeline Tekton components at execution creation. You can also change default parameters in the pipeline with an easy commang line execution
jx create variable
, or just adding them in the YAML file. - It is much easier to create a Jenkins X pipeline to orchestrate Tekton components than creating the isolated components by itself and then deploying the execution.
- All GitHub “dirty work” like webhooks, credentials or updates required are already configured by Jenkins X to work only on code changes.
- We could see also that pipeline execution is faster because Jenkins X takes care about artifact caching and optimizing Kubernetes resources used.
Let’s use the following diagram to show how a Jenkins X pipeline definition is translated into Tekton components, like also happened in our example:
The pure Jenkins X way
But let’s be honest. If we want to take advantadge of a real pipeline orchestration platform like Jenkins X, previous configuration of jenkins-x.yml
is not the best way to go. That was intended to understand how a Jenkins X pipeline definition is abstracting Tekton components to run CI/CD pipelines.
The real value of a CI/CD pipeline orchestration platform is about something else than abstracting a powerful decoupled CI/CD engine like Tekton. So let’s try to understand what I am talking about by doing CI/CD with the same petclinic-kaniko repo in a pure Jenkins X way using Jenkins X build packs.
As shown before, for demonstration purposes I am cloning first the original repo and then importing from local to to automatically create from Jenkins X a new repo in GitHub. I could import directly from the GitHub repo, creating then a new commit with the changes to continue to do CI/CD with Jenkins X (for example changing my old Jenkinsfile
for a new jenkins-x.yaml
).
Because I don’t want to change the original repo, let’s do the following:
- Clone original repo from the terminal with
git clone https://github.com/dcanadillas/petclinic-kaniko petclinic-jx
. - Remove git references
rm -rf petclinic-jx/.git*
. - Now, create Jenkins X project by importing from the local repo into a new GitHub repository:
jx import --git-username dcanadillas --org jx-dcanadillas --name petclinic-jx -m YAML
Note that we are using -m YAML
to force Jenkins X creating a new Jenkins X serverless pipeline project instead of a Static Jenkinsfile
one.
Different things are going on when importing the project with Jenkins X:
- Creates a local git repo (similar to
git init
). - Selects a Draft build pack from Jenkins X. (In this case takes a maven build pack).
- Pushes the new repository with changes applied from the build pack to a repo in the GitHub organization specified in the
--org
parameter. - Creates a GitHub webhook for Jenkins X to be able to trigger pipelines automatically with any code change.
- Runs the pipeline to build the application and promotes to Staging using GitOps.
Basically, Jenkins X already configured the CI/CD pipeline just by importing the project. So now there is already a pipeline running. All steps executed by the pipeline build can be seen with jx get activity -f petclinic-jx -w
. Once it succeeded:
$ jx get activity -f petclinic-jx --build 1
STEP STARTED AGO DURATION STATUS
jx-dcanadillas/petclinic-jx/master #1 55m57s 3m59s Succeeded Version: 0.0.1
from build pack 55m57s 3m59s Succeeded
Credential Initializer Dk42x 55m57s 1s Succeeded
Working Dir Initializer Fqgpx 55m56s 0s Succeeded
Place Tools 55m55s 0s Succeeded
Git Source Jx Dcanadillas Petclinic Jx Mas Rt8qq 55m54s 2s Succeeded https://github.com/jx-dcanadillas/petclinic-jx
Git Merge 55m53s 2s Succeeded
Setup Jx Git Credentials 55m52s 2s Succeeded
Build Mvn Deploy 55m52s 2m33s Succeeded
Build Skaffold Version 55m52s 2m34s Succeeded
Build Container Build 55m52s 2m49s Succeeded
Build Post Build 55m52s 2m50s Succeeded
Promote Changelog 55m51s 2m54s Succeeded
Promote Helm Release 55m51s 3m0s Succeeded
Promote Jx Promote 55m51s 3m53s Succeeded
Promote: staging 52m43s 45s Succeeded
PullRequest 52m43s 45s Succeeded PullRequest: https://github.com/dcanadillas-kube/environment-dcanadillas-cloudbees-staging/pull/6 Merge SHA: f765c6fe2d91bff40d4fcbc30641cd92b35849a9
Update 51m58s 0s Succeeded
The pipeline created by Jenkins X has just two Tekton tasks with different steps. The first Tekton task from build pack and a second task Promote: Staging
. This just comes from the pipeline defined by Jenkins X:
$ cat jenkins-x.yml
buildPack: maven
It’s a one line pipeline that it’s just “inheriting” from the maven build pack pipeline.
Bottom line here is that build packs are templates for building your application. So developers don’t need to think about how to conceptually design the CI/CD pipelines, or components needed to manage Kubernetes in order to promote the application. But you can extend using the jenkins-x.yaml
or by executing jx create step
command. In this case Jenkins X already propose a pipeline lifecycle, that it is translated on how Tekton decouples the pipeline execution objects.
Coming back to our execution, the application is just automatically deployed and versioned into the Staging
environment at version 0.0.1
:
$ jx get version
APPLICATION STAGING PODS URL
petclinic 1/1
petclinic-jx 0.0.1 http://petclinic-jx.jx-staging.cbjx.dcanadillas.com
In this output we can see also our previous petclinic
application deployed with our previous example with the “customized” Jenkins X pipeline. And our recently deployed Jenkins X application petclinic-jx
. Some differences between them are that we needed to define deployment in the first pipeline example (non-pure Jenkins X way), but there is no versioning or promotion lifecycle. In the other hand, our last application build - just by importing it with Jenkins X - it is versioned, deployed in the right environment and with an access url. This means that the Kubernetes service
, deployyment
and ingress
have been configured automatically. And it also used GitOps promotion to track and audit all versioning and promotion environment.
But, the last application deployment wasn’t really successful:
$ jx open petclinic-jx -n jx-staging
petclinic-jx: http://petclinic-jx.jx-staging.cbjx.dcanadillas.com
We get a 503
error from the application.
If we check what is going on:
$ kubectl describe pod $(kubectl get pods -n jx-staging | awk '/petclinic-jx/ {print $1}') -n jx-staging
Name: jx-petclinic-jx-845cbfcd88-8fvrx
Namespace: jx-staging
[...]
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Unhealthy 45m (x20 over 8h) kubelet, gke-dcanadillas-cloudbee-default-pool-98606002-b9hc Liveness probe failed: Get http://<IP_ADDRESS>:8080/actuator/health: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Warning Unhealthy 35m (x376 over 9h) kubelet, gke-dcanadillas-cloudbee-default-pool-98606002-b9hc Liveness probe failed: HTTP probe failed with statuscode: 404
Normal Pulled 30m (x138 over 9h) kubelet, gke-dcanadillas-cloudbee-default-pool-98606002-b9hc Container image "gcr.io/emea-sa-demo/petclinic-jx:0.0.1" already present on machine
Warning Unhealthy 5m35s (x881 over 9h) kubelet, gke-dcanadillas-cloudbee-default-pool-98606002-b9hc Readiness probe failed: Get http://<IP_ADDRESS>:8080/actuator/health: dial tcp <IP_ADDRESS>:8080: connect: connection refused
Warning BackOff 38s (x1719 over 9h) kubelet, gke-dcanadillas-cloudbee-default-pool-98606002-b9hc Back-off restarting failed container
When the project was imported from Jenkins X and the build pack was applied, some components were added to the original project. Likehelm charts
required to deploy and promote through environments.
Looking at previous error logs in the Pod
, the problem seems to be about changing the probePath
in the file petclinic-jx/charts/petclinic-jx/values.yaml
. Let’s fix it. We need to change it from /actuator/health
to /
:
cat charts/petclinic-jx/values.yaml | sed 's/\/actuator\/health/\//g' | tee charts/petclinic-jx/values.yaml
Then, we apply the changes to the repo and the pipeline will be triggered automatically:
$ git commit -am "probePath changed to the right value"
$ git push -u origin master
[...]
To https://github.com/jx-dcanadillas/petclinic-jx.git
b25d36b..234b99a master -> master
Rama 'master' configurada para hacer seguimiento a la rama remota 'master' de 'origin'.
The pipeline should start running againg to build the application and promote version 0.0.2
into Staging
.
$ jx get activity -f petclinic-jx -w
[...]
Git Merge 3m49s 2s Succeeded
Setup Jx Git Credentials 3m49s 3s Succeeded
Build Mvn Deploy 3m48s 2m5s Succeeded
Build Skaffold Version 3m48s 2m6s Succeeded
Build Container Build 3m48s 2m19s Succeeded
Build Post Build 3m48s 2m20s Succeeded
Promote Changelog 3m47s 2m24s Succeeded
Promote Helm Release 3m47s 2m29s Succeeded
Promote Jx Promote 3m47s 3m43s Succeeded
Promote: staging 1m10s 1m6s Succeeded
PullRequest 1m10s 1m6s Succeeded PullRequest: https://github.com/dcanadillas-kube/environment-dcanadillas-cloudbees-staging/pull/7 Merge SHA: ced0df09abbc18b002114a28640901f5261da6c3
Update 4s 0s Succeeded
Promoted 4s 0s Succeeded Application is at: http://petclinic-jx.jx-staging.cbjx.dcanadillas.com
Checking then that the new version 0.0.2
is deployed:
$ jx get version
APPLICATION STAGING PODS URL
petclinic 1/1
petclinic-jx 0.0.2 1/1 http://petclinic-jx.jx-staging.cbjx.dcanadillas.com
And opening the new version:
$ jx open petclinic-jx -n jx-staging
The pure Jenkins X way is about:
- Applying build pack for adopting pipeline definition experience best practices
- Complete pipeline orchestration for build and promote using Tekton native objects
- GitOps for promotion process
- Kubernetes objects management required for pipeline execution
- Pipeline extensions using easy pipeline definition with
jenkins-x.yml
It is a simpler and more complete experience of CI/CD pipelines than trying to deal with Tekton itself. It is a real orchestration of all resources to develop, build and promote from real cloud native environment.
And last, to demonstrate that all Tekton orchestration happened, let’s check all components created for all our Jenkins X executions:
$ kubectl get tasks,taskruns,pipeline,pipelinerun,pipelineresources -n jx
NAME AGE
task.tekton.dev/dcanadillas-kube-environment-dc-d495w-from-build-pack-7 23m
task.tekton.dev/dcanadillas-kube-environment-dc-hk95j-from-build-pack-1 24m
task.tekton.dev/dcanadillas-kube-environment-dc-wm85w-from-build-pack-6 10h
task.tekton.dev/dcanadillas-kube-environment-dc-wpqsp-from-build-pack-1 10h
task.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-kaniko-build-3 4h
task.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-kubectl-deploy-3 4h
task.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-maven-build-3 4h
task.tekton.dev/jx-dcanadillas-petclinic-jx-mas-from-build-pack-1 10h
task.tekton.dev/jx-dcanadillas-petclinic-jx-mas-ndtfh-from-build-pack-2 27m
NAME AGE
taskrun.tekton.dev/dcanadillas-kube-environment-dc-d495w-7-from-build-pack-724xr 23m
taskrun.tekton.dev/dcanadillas-kube-environment-dc-hk95j-1-from-build-pack-w8222 24m
taskrun.tekton.dev/dcanadillas-kube-environment-dc-wm85w-6-from-build-pack-ld44v 10h
taskrun.tekton.dev/dcanadillas-kube-environment-dc-wpqsp-1-from-build-pack-2txtk 10h
taskrun.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-3-kaniko-build-cjkwd 4h
taskrun.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-3-kubectl-deploy-kdr9x 4h
taskrun.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-3-maven-build-x2cjr 4h
taskrun.tekton.dev/jx-dcanadillas-petclinic-jx-mas-1-from-build-pack-x245x 10h
taskrun.tekton.dev/jx-dcanadillas-petclinic-jx-mas-ndtfh-2-from-build-pack-9xkrq 27m
NAME AGE
pipeline.tekton.dev/dcanadillas-kube-environment-dc-d495w-7 23m
pipeline.tekton.dev/dcanadillas-kube-environment-dc-hk95j-1 24m
pipeline.tekton.dev/dcanadillas-kube-environment-dc-wm85w-6 10h
pipeline.tekton.dev/dcanadillas-kube-environment-dc-wpqsp-1 10h
pipeline.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-3 4h
pipeline.tekton.dev/jx-dcanadillas-petclinic-jx-mas-1 10h
pipeline.tekton.dev/jx-dcanadillas-petclinic-jx-mas-ndtfh-2 27m
NAME AGE
pipelinerun.tekton.dev/dcanadillas-kube-environment-dc-d495w-7 23m
pipelinerun.tekton.dev/dcanadillas-kube-environment-dc-hk95j-1 24m
pipelinerun.tekton.dev/dcanadillas-kube-environment-dc-wm85w-6 10h
pipelinerun.tekton.dev/dcanadillas-kube-environment-dc-wpqsp-1 10h
pipelinerun.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw-3 4h
pipelinerun.tekton.dev/jx-dcanadillas-petclinic-jx-mas-1 10h
pipelinerun.tekton.dev/jx-dcanadillas-petclinic-jx-mas-ndtfh-2 27m
NAME AGE
pipelineresource.tekton.dev/dcanadillas-kube-environment-dc-d495w 23m
pipelineresource.tekton.dev/dcanadillas-kube-environment-dc-hk95j 24m
pipelineresource.tekton.dev/dcanadillas-kube-environment-dc-wm85w 10h
pipelineresource.tekton.dev/dcanadillas-kube-environment-dc-wpqsp 10h
pipelineresource.tekton.dev/jx-dcanadillas-petclinic-jenkin 4d
pipelineresource.tekton.dev/jx-dcanadillas-petclinic-jenkin-lg4nw 4h
pipelineresource.tekton.dev/jx-dcanadillas-petclinic-jenkin-rhg88 3d
pipelineresource.tekton.dev/jx-dcanadillas-petclinic-jx-mas 10h
pipelineresource.tekton.dev/jx-dcanadillas-petclinic-jx-mas-ndtfh 27m
Some thoughts and final conclusions
Traditional Jenkins has long been one of the best CI/CD pipeline engines in terms of flexibility, standardization and adoption for most DevOps environments. But new challenges for software delivery requires scalable CI/CD architectures. Today that means using Kubernetes as a powerful abstraction of the infrastructure and the use of cloud native platforms to decouple and scale CI/CD pipelines.
Decoupling and scaling pipelines is one of the best approaches for building new modern applications and microservices. But it can be very hard to work on these decoupled objects to define a pipeline, which conceptually is a sequential and “monolithic” tasks execution.
So, Tekton is demonstrating its power of decoupling CI/CD pipelines and builds to scale. But it also needs a powerful orchestrator to simplify the complexity underneath, and even more when dealing with a platform like Kubernetes, that can also add more complexity.
I like to say that the best way to build and run CI/CD pipelines for modern (and also traditional, why not!) software applications is to make it simple and “abstract the abstraction”. I believe Jenkins X is about that. It is about applying the simplicity of traditional Jenkins pipelines from a powerful and scalable engine.
Most development companies are realizing that the next iteration of CI/CD is already here and that it’s not only about cloud native pipelines, YAML object definintions or Kubernetes containers orchestration. It is about orchestrating all the complexity while adopting best practices. We are talking about build packs templating, simple YAML pipelines, seamless Git integration, scalable team management, flexible and standard deployments, extensible platform engine, standard packaging and promotion, etc.
We’ve seen from a very basic point of view in our examples what it means to orchestrate this. And … it is more than Tekton on steroids.


@* * Copyright 2010-2013 Artima, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *@ @nonHomePage("About") {
ScalaTest was written by Bill Venners, George Berger, Chua Chee Seng, and other contributors starting in late 2007. ScalaTest, which is almost exclusively written in Scala, follows and improves upon the Java code and design of Artima SuiteRunner, a testing tool also written primarily by Bill Venners, starting in 2001. Over the years a few other people contributed to SuiteRunner as well, including:
Originally, ScalaTest was hosted at java.net, but as of release 1.3 was been moved to Google Code. You can browse the source code:
http://code.google.com/p/scalatest/source/browse/
You can checkout a read-only version of the source from Google Code with this command:
svn checkout http://scalatest.googlecode.com/svn/trunk/ scalatest-read-only
This command will build and run most of the tests:
$ ant test
Issues can be submitted here:


Total projects: {{ counter }}
(Projects which ever used (i.e. were building their PR code in Copr via) Packit service)
{{ all_projects|safe }}
Successful projects: {{ counter_s }}
(Projects which ever successfully used (i.e. successfully built their PR code in Copr in all targets via) Packit service)
{{ successful_projects|safe }}


Some guests at Circus Circus were evacuated from their rooms Monday after a man with a firearm barricaded himself in a room of the Strip hotel-casino, according to Las Vegas police.
At 12:27 p.m. police said “the subject was taken into custody without incident.”
Metropolitan police said in a press release that at 11:18 a.m. patrol officers “responded to a suicidal individual in the 1000 block of Circus Circus Drive.”
“Arriving officers located an individual holding a firearm inside a hotel room,” police said. “This incident is being treated as a barricade. Some individuals have been evacuated from nearby rooms as a precaution.”
Brian Ahern, director of corporate media relations for MGM Resorts International, said, “Metro is overseeing this and we are assisting them in their efforts.”


--- layout: layout-container name: Fundraising Entity Reference title: Fundraising Entity Reference order: 30 published: true showInNav: true back_to_top: true showBreadcrumbs: true ---


SceneJS
- handling 'rendered' events on scene nodes
useful for tracking the positions of scene objects
Teapot 1
Teapot 2
Teapot 3


| LEFT-CLICK | Set or select a marker |
| CTRL-LEFT-CLICK | Edit a marker |
| ALT-LEFT-CLICK | Deletes a marker |
| RIGHT-CLICK | Navigate to area or marker |
| CTRL-RIGHT-CLICK | Zoom out one area |
| ENTER | Edit the selected marker |
| DELETE | Delete the selected marker |
| RIGHT ARROW | Goto next Marker |
| LEFT ARROW | Goto previous Marker |
Right Arrow will follow marker links. This allows you to build complete quest guides that can be followed step by step.
load
Replaces your current markers with new ones.
import
Import adds loaded markers to your current ones.
save
Lets you save your current markers to a file.
If a markers message ends with #zone_name
, it becomes a navigation-link to that zone.
The following zones names are available:
#alterac_valley
#arathi_basin
#arathi_highlands
#ashenvale
#azeroth
#azshara
#badlands
#blasted_lands
#burning_steppes
#darkshore
#darnassus
#deadwind_pass
#desolace
#dun_morogh
#durotar
#duskwood
#dustwallow_marsh
#eastern_kingdoms
#eastern_plaguelands
#elwynn_forest
#felwood
#feralas
#hillsbrad_foothills
#ironforge
#kalimdor
#loch_modan
#moonglade
#mulgore
#orgrimmar
#redridge_mountains
#searing_gorge
#silithus
#silverpine_forest
#stonetalon_mountains
#stormwind
#stranglethorn_vale
#swamp_of_sorrows
#tanaris
#teldrassil
#the_barrens
#the_hinterlands
#thousand_needles
#thunder_bluff
#tirisfal_glades
#undercity
#ungoro_crater
#warsong_gulch
#western_plaguelands
#westfall
#wetlands
#winterspring
Additionally, a marker-index can be put after the zone-name, in the form of #N
with N being the index of the marker on the target map (beginning at 0)


@examples In this example, the WriteValue function is used to display a sequence of values. The values are all written to the same line because WriteValue does not include a NewLine character after writing a value. A NewLine character has to be manually added to advance to the next line.
Private Sub Main() Dim i As Long ' Writes out a sequence of digits. The digits are written on the same line. Console.WriteValue "Loop 1: " For i = 1 To 5 Console.WriteValue i Next i ' Writes out a new line manually. Console.WriteValue vbCrLf ' Writes formatted values on the same line. Console.WriteValue "Loop 2: " For i = 1 To 5 Console.WriteValue "i = {0}" & IIf(i < 5, ", ", ""), i Next i End Sub ' This example produces the following output. ' Loop 1: 12345 ' Loop 2: i = 1, i = 2, i = 3, i = 4, i = 5


| Sr | Fieldname | Type | Label | Options |
|---|---|---|---|---|
| 1 | select_companies |
Section Break |
Select Companies
Emails will be sent to all Active Employees of the company at the given hour, if they do not have holiday. Summary of responses will be sent at midnight. |
|
| 2 | companies |
Table | Companies | Daily Work Summary Settings Company |
| 3 | message_section |
Section Break | Message | |
| 4 | subject |
Data | Subject | |
| 5 | message |
Text Editor | Message |
Inherits from frappe.model.document.Document
erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings.send_summary ()
Send summary to everyone
erpnext.hr.doctype.daily_work_summary_settings.daily_work_summary_settings.trigger_emails ()
Send emails to Employees of the enabled companies at the give hour asking them what did they work on today


Page turning
On a mobile device you can swipe left and right to navigate through pages.
Swiping capabilities have been added as a plugin so it can easily be removed if not required.
On a mobile device you can swipe left and right to navigate through pages.
Swiping capabilities have been added as a plugin so it can easily be removed if not required.


Check your developper tool console. Try to switch tab to see what happen in the tab title
Pause idle
Start idle
🤸 move your mouse 🤸
🏃 On
idle
I will hold a handstand
🕴 I will never do anything until idle is started again.


Choose a meat and a vegetable you would like to base your meal around. We will generate a meal plan in accordance with your input. If you are up for anything, choose our "I'm Feeling Lucky" option and we will suggest a random recipe!


Model Number: CM633GBS1B
Model Number: HB878GBB6B
Model Number: HB678GBS6B
Model Number: HR676GBS6B
Model Number: HB676GBS6B
Model Number: HB656GBS6B
© AppZoy Technologies Pvt.Ltd. All Rights Reserved.


| typedef | PangoOTTag |
| PangoOTInfo | |
| PangoOTBuffer | |
| struct | PangoOTGlyph |
| PangoOTRuleset | |
| struct | PangoOTRulesetDescription |
| enum | PangoOTTableType |
| struct | PangoOTFeatureMap |
| #define | PANGO_OT_ALL_GLYPHS |
| #define | PANGO_OT_NO_FEATURE |
| #define | PANGO_OT_NO_SCRIPT |
| #define | PANGO_OT_DEFAULT_LANGUAGE |
| #define | PANGO_OT_TAG_DEFAULT_LANGUAGE |
| #define | PANGO_OT_TAG_DEFAULT_SCRIPT |
Functions and macros in this section are used to implement the OpenType Layout features and algorithms. These are mostly useful when writing Fontconfig-based shaping engines
#define PANGO_OT_TAG_MAKE(c1,c2,c3,c4) ((PangoOTTag) FT_MAKE_TAG (c1, c2, c3, c4))
Creates a PangoOTTag from four characters. This is similar and
compatible with the
macro from FreeType.FT_MAKE_TAG()
#define PANGO_OT_TAG_MAKE_FROM_STRING(s)
Creates a PangoOTTag from a string. The string should be at least
four characters long (pad with space characters if needed), and need
not be nul-terminated. This is a convenience wrapper around
PANGO_OT_TAG_MAKE()
, but cannot be used in certain situations, for
example, as a switch expression, as it dereferences pointers.
PangoOTInfo *
pango_ot_info_get (FT_Face face
);
pango_ot_info_get
is deprecated and should not be used in newly-written code.
Returns the PangoOTInfo structure for the given FreeType font face.
Since: 1.2
gboolean pango_ot_info_find_script (PangoOTInfo *info
,PangoOTTableType table_type
,PangoOTTag script_tag
,guint *script_index
);
pango_ot_info_find_script
is deprecated and should not be used in newly-written code.
Finds the index of a script. If not found, tries to find the 'DFLT'
and then 'dflt' scripts and return the index of that in script_index
.
If none of those is found either, PANGO_OT_NO_SCRIPT
is placed in
script_index
.
All other functions taking an input script_index parameter know
how to handle PANGO_OT_NO_SCRIPT
, so one can ignore the return
value of this function completely and proceed, to enjoy the automatic
fallback to the 'DFLT'/'dflt' script.
info |
a PangoOTInfo. |
|
table_type |
the table type to obtain information about. |
|
script_tag |
the tag of the script to find. |
|
script_index |
location to store the index of the
script, or |
[out][optional] |
gboolean pango_ot_info_find_language (PangoOTInfo *info
,PangoOTTableType table_type
,guint script_index
,PangoOTTag language_tag
,guint *language_index
,guint *required_feature_index
);
pango_ot_info_find_language
is deprecated and should not be used in newly-written code.
Finds the index of a language and its required feature index.
If the language is not found, sets language_index
to
PANGO_OT_DEFAULT_LANGUAGE and the required feature of the default language
system is returned in required_feature_index. For best compatibility with
some fonts, also searches the language system tag 'dflt' before falling
back to the default language system, but that is transparent to the user.
The user can simply ignore the return value of this function to
automatically fall back to the default language system.
info |
a PangoOTInfo. |
|
table_type |
the table type to obtain information about. |
|
script_index |
the index of the script whose languages are searched. |
|
language_tag |
the tag of the language to find. |
|
language_index |
location to store the index of
the language, or |
[out][optional] |
required_feature_index |
location to store the
required feature index of the language, or |
[out][optional] |
gboolean pango_ot_info_find_feature (PangoOTInfo *info
,PangoOTTableType table_type
,PangoOTTag feature_tag
,guint script_index
,guint language_index
,guint *feature_index
);
pango_ot_info_find_feature
is deprecated and should not be used in newly-written code.
Finds the index of a feature. If the feature is not found, sets
feature_index
to PANGO_OT_NO_FEATURE, which is safe to pass to
pango_ot_ruleset_add_feature()
and similar functions.
In the future, this may set feature_index
to an special value that if used
in pango_ot_ruleset_add_feature()
will ask Pango to synthesize the
requested feature based on Unicode properties and data. However, this
function will still return FALSE
in those cases. So, users may want to
ignore the return value of this function in certain cases.
info |
a PangoOTInfo. |
|
table_type |
the table type to obtain information about. |
|
feature_tag |
the tag of the feature to find. |
|
script_index |
the index of the script. |
|
language_index |
the index of the language whose features are searched,
or |
|
feature_index |
location to store the index of
the feature, or |
[out][optional] |
PangoOTTag * pango_ot_info_list_scripts (PangoOTInfo *info
,PangoOTTableType table_type
);
pango_ot_info_list_scripts
is deprecated and should not be used in newly-written code.
Obtains the list of available scripts.
a newly-allocated zero-terminated array containing the tags of the
available scripts. Should be freed using g_free()
.
PangoOTTag * pango_ot_info_list_languages (PangoOTInfo *info
,PangoOTTableType table_type
,guint script_index
,PangoOTTag language_tag
);
pango_ot_info_list_languages
is deprecated and should not be used in newly-written code.
Obtains the list of available languages for a given script.
info |
a PangoOTInfo. |
|
table_type |
the table type to obtain information about. |
|
script_index |
the index of the script to list languages for. |
|
language_tag |
unused parameter. |
a newly-allocated zero-terminated array containing the tags of the
available languages. Should be freed using g_free()
.
PangoOTTag * pango_ot_info_list_features (PangoOTInfo *info
,PangoOTTableType table_type
,PangoOTTag tag
,guint script_index
,guint language_index
);
pango_ot_info_list_features
is deprecated and should not be used in newly-written code.
Obtains the list of features for the given language of the given script.
info |
a PangoOTInfo. |
|
table_type |
the table type to obtain information about. |
|
tag |
unused parameter. |
|
script_index |
the index of the script to obtain information about. |
|
language_index |
the index of the language to list features for, or
|
a newly-allocated zero-terminated array containing the tags of the
available features. Should be freed using g_free()
.
PangoOTBuffer *
pango_ot_buffer_new (PangoFcFont *font
);
pango_ot_buffer_new
is deprecated and should not be used in newly-written code.
Creates a new PangoOTBuffer for the given OpenType font.
Since: 1.4
void
pango_ot_buffer_destroy (PangoOTBuffer *buffer
);
pango_ot_buffer_destroy
is deprecated and should not be used in newly-written code.
Destroys a PangoOTBuffer and free all associated memory.
Since: 1.4
void
pango_ot_buffer_clear (PangoOTBuffer *buffer
);
pango_ot_buffer_clear
is deprecated and should not be used in newly-written code.
Empties a PangoOTBuffer, make it ready to add glyphs to.
Since: 1.4
void pango_ot_buffer_add_glyph (PangoOTBuffer *buffer
,guint glyph
,guint properties
,guint cluster
);
pango_ot_buffer_add_glyph
is deprecated and should not be used in newly-written code.
Appends a glyph to a PangoOTBuffer, with properties
identifying which
features should be applied on this glyph. See pango_ot_ruleset_add_feature()
.
buffer |
||
glyph |
the glyph index to add, like a PangoGlyph |
|
properties |
the glyph properties |
|
cluster |
the cluster that this glyph belongs to |
Since: 1.4
void pango_ot_buffer_set_rtl (PangoOTBuffer *buffer
,gboolean rtl
);
pango_ot_buffer_set_rtl
is deprecated and should not be used in newly-written code.
Sets whether glyphs will be rendered right-to-left. This setting is needed for proper horizontal positioning of right-to-left scripts.
Since: 1.4
void pango_ot_buffer_set_zero_width_marks (PangoOTBuffer *buffer
,gboolean zero_width_marks
);
pango_ot_buffer_set_zero_width_marks
is deprecated and should not be used in newly-written code.
Sets whether characters with a mark class should be forced to zero width. This setting is needed for proper positioning of Arabic accents, but will produce incorrect results with standard OpenType Indic fonts.
buffer |
||
zero_width_marks |
|
Since: 1.6
void pango_ot_buffer_get_glyphs (const PangoOTBuffer *buffer
,PangoOTGlyph **glyphs
,int *n_glyphs
);
pango_ot_buffer_get_glyphs
is deprecated and should not be used in newly-written code.
Gets the glyph array contained in a PangoOTBuffer. The glyphs are owned by the buffer and should not be freed, and are only valid as long as buffer is not modified.
Since: 1.4
void pango_ot_buffer_output (const PangoOTBuffer *buffer
,PangoGlyphString *glyphs
);
pango_ot_buffer_output
is deprecated and should not be used in newly-written code.
Exports the glyphs in a PangoOTBuffer into a PangoGlyphString. This is typically used after the OpenType layout processing is over, to convert the resulting glyphs into a generic Pango glyph string.
Since: 1.4
const PangoOTRuleset * pango_ot_ruleset_get_for_description (PangoOTInfo *info
,const PangoOTRulesetDescription *desc
);
pango_ot_ruleset_get_for_description
is deprecated and should not be used in newly-written code.
Returns a ruleset for the given OpenType info and ruleset
description. Rulesets are created on demand using
pango_ot_ruleset_new_from_description()
.
The returned ruleset should not be modified or destroyed.
The static feature map members of desc
should be alive as
long as info
is.
Since: 1.18
PangoOTRuleset *
pango_ot_ruleset_new (PangoOTInfo *info
);
pango_ot_ruleset_new
is deprecated and should not be used in newly-written code.
Creates a new PangoOTRuleset for the given OpenType info.
PangoOTRuleset * pango_ot_ruleset_new_for (PangoOTInfo *info
,PangoScript script
,PangoLanguage *language
);
pango_ot_ruleset_new_for
is deprecated and should not be used in newly-written code.
Creates a new PangoOTRuleset for the given OpenType info, script, and language.
This function is part of a convenience scheme that highly simplifies using a PangoOTRuleset to represent features for a specific pair of script and language. So one can use this function passing in the script and language of interest, and later try to add features to the ruleset by just specifying the feature name or tag, without having to deal with finding script, language, or feature indices manually.
In excess to what pango_ot_ruleset_new()
does, this function will:
script
and language
using pango_ot_tag_from_script()
and
pango_ot_tag_from_language()
,
PANGO_OT_TABLE_GSUB
and PANGO_OT_TABLE_GPOS
,
find the script index of the script tag found and the language
system index of the language tag found in that script system, using
pango_ot_info_find_script()
and pango_ot_info_find_language()
,
pango_ot_ruleset_add_feature()
,
pango_ot_ruleset_maybe_add_feature()
and
pango_ot_ruleset_maybe_add_features()
.
Because of the way return values of pango_ot_info_find_script()
and
pango_ot_info_find_language()
are ignored, this function automatically
finds and uses the 'DFLT' script and the default language-system.
Since: 1.18
PangoOTRuleset * pango_ot_ruleset_new_from_description (PangoOTInfo *info
,const PangoOTRulesetDescription *desc
);
pango_ot_ruleset_new_from_description
is deprecated and should not be used in newly-written code.
Creates a new PangoOTRuleset for the given OpenType infor and matching the given ruleset description.
This is a convenience function that calls pango_ot_ruleset_new_for()
and
adds the static GSUB/GPOS features to the resulting ruleset, followed by
adding other features to both GSUB and GPOS.
The static feature map members of desc
should be alive as
long as info
is.
Since: 1.18
void pango_ot_ruleset_add_feature (PangoOTRuleset *ruleset
,PangoOTTableType table_type
,guint feature_index
,gulong property_bit
);
pango_ot_ruleset_add_feature
is deprecated and should not be used in newly-written code.
Adds a feature to the ruleset.
ruleset |
||
table_type |
the table type to add a feature to. |
|
feature_index |
the index of the feature to add. |
|
property_bit |
the property bit to use for this feature. Used to identify
the glyphs that this feature should be applied to, or
|
gboolean pango_ot_ruleset_maybe_add_feature (PangoOTRuleset *ruleset
,PangoOTTableType table_type
,PangoOTTag feature_tag
,gulong property_bit
);
pango_ot_ruleset_maybe_add_feature
is deprecated and should not be used in newly-written code.
This is a convenience function that first tries to find the feature
using pango_ot_info_find_feature()
and the ruleset script and language
passed to pango_ot_ruleset_new_for()
,
and if the feature is found, adds it to the ruleset.
If ruleset
was not created using pango_ot_ruleset_new_for()
, this function
does nothing.
ruleset |
||
table_type |
the table type to add a feature to. |
|
feature_tag |
the tag of the feature to add. |
|
property_bit |
the property bit to use for this feature. Used to identify
the glyphs that this feature should be applied to, or
|
Since: 1.18
guint pango_ot_ruleset_maybe_add_features (PangoOTRuleset *ruleset
,PangoOTTableType table_type
,const PangoOTFeatureMap *features
,guint n_features
);
pango_ot_ruleset_maybe_add_features
is deprecated and should not be used in newly-written code.
This is a convenience function that
for each feature in the feature map array features
converts the feature name to a PangoOTTag feature tag using PANGO_OT_TAG_MAKE()
and calls pango_ot_ruleset_maybe_add_feature()
on it.
ruleset |
||
table_type |
the table type to add features to. |
|
features |
array of feature name and property bits to add. |
|
n_features |
number of feature records in |
Since: 1.18
guint pango_ot_ruleset_get_feature_count (const PangoOTRuleset *ruleset
,guint *n_gsub_features
,guint *n_gpos_features
);
pango_ot_ruleset_get_feature_count
is deprecated and should not be used in newly-written code.
Gets the number of GSUB and GPOS features in the ruleset.
Since: 1.18
void pango_ot_ruleset_substitute (const PangoOTRuleset *ruleset
,PangoOTBuffer *buffer
);
pango_ot_ruleset_substitute
is deprecated and should not be used in newly-written code.
Performs the OpenType GSUB substitution on buffer
using the features
in ruleset
Since: 1.4
void pango_ot_ruleset_position (const PangoOTRuleset *ruleset
,PangoOTBuffer *buffer
);
pango_ot_ruleset_position
is deprecated and should not be used in newly-written code.
Performs the OpenType GPOS positioning on buffer
using the features
in ruleset
Since: 1.4
PangoOTRulesetDescription *
pango_ot_ruleset_description_copy (const PangoOTRulesetDescription *desc
);
pango_ot_ruleset_description_copy
is deprecated and should not be used in newly-written code.
Creates a copy of desc
, which should be freed with
pango_ot_ruleset_description_free()
. Primarily used internally
by pango_ot_ruleset_get_for_description()
to cache rulesets for
ruleset descriptions.
the newly allocated PangoOTRulesetDescription, which
should be freed with pango_ot_ruleset_description_free()
.
Since: 1.18
gboolean pango_ot_ruleset_description_equal (const PangoOTRulesetDescription *desc1
,const PangoOTRulesetDescription *desc2
);
pango_ot_ruleset_description_equal
is deprecated and should not be used in newly-written code.
Compares two ruleset descriptions for equality.
Two ruleset descriptions are considered equal if the rulesets
they describe are provably identical. This means that their
script, language, and all feature sets should be equal. For static feature
sets, the array addresses are compared directly, while for other
features, the list of features is compared one by one.
(Two ruleset descriptions may result in identical rulesets
being created, but still compare FALSE
.)
Since: 1.18
void
pango_ot_ruleset_description_free (PangoOTRulesetDescription *desc
);
pango_ot_ruleset_description_free
is deprecated and should not be used in newly-written code.
Frees a ruleset description allocated by
pango_ot_ruleset_description_copy()
.
Since: 1.18
guint
pango_ot_ruleset_description_hash (const PangoOTRulesetDescription *desc
);
pango_ot_ruleset_description_hash
is deprecated and should not be used in newly-written code.
Computes a hash of a PangoOTRulesetDescription structure suitable
to be used, for example, as an argument to g_hash_table_new()
.
Since: 1.18
PangoOTTag
pango_ot_tag_from_language (PangoLanguage *language
);
pango_ot_tag_from_language
is deprecated and should not be used in newly-written code.
Finds the OpenType language-system tag best describing language
.
PangoOTTag best matching language
or
PANGO_OT_TAG_DEFAULT_LANGUAGE
if none found or if language
is NULL
.
Since: 1.18
PangoOTTag
pango_ot_tag_from_script (PangoScript script
);
pango_ot_tag_from_script
is deprecated and should not be used in newly-written code.
Finds the OpenType script tag corresponding to script
.
The PANGO_SCRIPT_COMMON
, PANGO_SCRIPT_INHERITED
, and
PANGO_SCRIPT_UNKNOWN
scripts are mapped to the OpenType
'DFLT' script tag that is also defined as
PANGO_OT_TAG_DEFAULT_SCRIPT
.
Note that multiple PangoScript values may map to the same
OpenType script tag. In particular, PANGO_SCRIPT_HIRAGANA
and PANGO_SCRIPT_KATAKANA
both map to the OT tag 'kana'.
Since: 1.18
PangoLanguage *
pango_ot_tag_to_language (PangoOTTag language_tag
);
pango_ot_tag_to_language
is deprecated and should not be used in newly-written code.
Finds a PangoLanguage corresponding to language_tag
.
PangoLanguage best matching language_tag
or
PangoLanguage corresponding to the string "xx" if none found.
Since: 1.18
PangoScript
pango_ot_tag_to_script (PangoOTTag script_tag
);
pango_ot_tag_to_script
is deprecated and should not be used in newly-written code.
Finds the PangoScript corresponding to script_tag
.
The 'DFLT' script tag is mapped to PANGO_SCRIPT_COMMON
.
Note that an OpenType script tag may correspond to multiple
PangoScript values. In such cases, the PangoScript value
with the smallest value is returned.
In particular, PANGO_SCRIPT_HIRAGANA
and PANGO_SCRIPT_KATAKANA
both map to the OT tag 'kana'.
This function will return PANGO_SCRIPT_HIRAGANA
for
'kana'.
Since: 1.18
typedef guint32 PangoOTTag;
The PangoOTTag typedef is used to represent TrueType and OpenType
four letter tags inside Pango. Use PANGO_OT_TAG_MAKE()
or PANGO_OT_TAG_MAKE_FROM_STRING()
macros to create PangoOTTags manually.
typedef struct _PangoOTInfo PangoOTInfo;
The PangoOTInfo struct contains the various
tables associated with an OpenType font. It contains only private fields and
should only be accessed via the pango_ot_info_*
functions
which are documented below. To obtain a PangoOTInfo,
use pango_ot_info_get()
.
typedef struct _PangoOTBuffer PangoOTBuffer;
The PangoOTBuffer structure is used to store strings of glyphs associated
with a PangoFcFont, suitable for OpenType layout processing. It contains
only private fields and should only be accessed via the
pango_ot_buffer_*
functions which are documented below.
To obtain a PangoOTBuffer, use pango_ot_buffer_new()
.
struct PangoOTGlyph { guint32 glyph; guint properties; guint cluster; gushort component; gushort ligID; guint internal; };
The PangoOTGlyph structure represents a single glyph together with information used for OpenType layout processing of the glyph. It contains the following fields.
guint32 |
the glyph itself. |
|
guint |
the properties value, identifying which features should be
applied on this glyph. See |
|
guint |
the cluster that this glyph belongs to. |
|
gushort |
a component value, set by the OpenType layout engine. |
|
gushort |
a ligature index value, set by the OpenType layout engine. |
|
guint |
for Pango internal use |
typedef struct _PangoOTRuleset PangoOTRuleset;
The PangoOTRuleset structure holds a
set of features selected from the tables in an OpenType font.
(A feature is an operation such as adjusting glyph positioning
that should be applied to a text feature such as a certain
type of accent.) A PangoOTRuleset
is created with pango_ot_ruleset_new()
, features are added
to it with pango_ot_ruleset_add_feature()
, then it is
applied to a PangoGlyphString with pango_ot_ruleset_shape()
.
struct PangoOTRulesetDescription { PangoScript script; PangoLanguage *language; const PangoOTFeatureMap *static_gsub_features; guint n_static_gsub_features; const PangoOTFeatureMap *static_gpos_features; guint n_static_gpos_features; const PangoOTFeatureMap *other_features; guint n_other_features; };
The PangoOTRuleset structure holds all the information needed
to build a complete PangoOTRuleset from an OpenType font.
The main use of this struct is to act as the key for a per-font
hash of rulesets. The user populates a ruleset description and
gets the ruleset using pango_ot_ruleset_get_for_description()
or create a new one using pango_ot_ruleset_new_from_description()
.
PangoScript |
a PangoScript. |
|
PangoLanguage * |
||
const PangoOTFeatureMap * |
static map of GSUB features,
or |
[nullable] |
guint |
length of |
|
const PangoOTFeatureMap * |
static map of GPOS features,
or |
[nullable] |
guint |
length of |
|
const PangoOTFeatureMap * |
map of extra features to add to both
GSUB and GPOS, or |
[nullable] |
guint |
length of |
Since: 1.18
The PangoOTTableType enumeration values are used to
identify the various OpenType tables in the
pango_ot_info_*
functions.
struct PangoOTFeatureMap { char feature_name[5]; gulong property_bit; };
The PangoOTFeatureMap typedef is used to represent an OpenType feature with the property bit associated with it. The feature tag is represented as a char array instead of a PangoOTTag for convenience.
char |
feature tag in represented as four-letter ASCII string. |
|
gulong |
the property bit to use for this feature. See
|
Since: 1.18
#define PANGO_OT_ALL_GLYPHS ((guint) 0xFFFF)
This is used as the property bit in pango_ot_ruleset_add_feature()
when a
feature should be applied to all glyphs.
Since: 1.16
#define PANGO_OT_NO_FEATURE ((guint) 0xFFFF)
This is used as a feature index that represent no feature, that is, should be
skipped. It may be returned as feature index by pango_ot_info_find_feature()
if the feature is not found, and pango_ot_ruleset_add_feature()
function
automatically skips this value, so no special handling is required by the user.
Since: 1.18
#define PANGO_OT_NO_SCRIPT ((guint) 0xFFFF)
This is used as a script index that represent no script, that is, when the
requested script was not found, and a default ('DFLT') script was not found
either. It may be returned as script index by pango_ot_info_find_script()
if the script or a default script are not found, all other functions
taking a script index essentially return if the input script index is
this value, so no special handling is required by the user.
Since: 1.18
#define PANGO_OT_DEFAULT_LANGUAGE ((guint) 0xFFFF)
This is used as the language index in pango_ot_info_find_feature()
when
the default language system of the script is desired.
It is also returned by pango_ot_info_find_language()
if the requested language
is not found, or the requested language tag was PANGO_OT_TAG_DEFAULT_LANGUAGE.
The end result is that one can always call pango_ot_tag_from_language()
followed by pango_ot_info_find_language()
and pass the result to
pango_ot_info_find_feature()
without having to worry about falling back to
default language system explicitly.
Since: 1.16
#define PANGO_OT_TAG_DEFAULT_LANGUAGE PANGO_OT_TAG_MAKE ('d', 'f', 'l', 't')
This is a PangoOTTag representing a special language tag 'dflt'. It is
returned as language tag by pango_ot_tag_from_language()
if the requested
language is not found. It is safe to pass this value to
pango_ot_info_find_language()
as that function falls back to returning default
language-system if the requested language tag is not found.
Since: 1.18
#define PANGO_OT_TAG_DEFAULT_SCRIPT PANGO_OT_TAG_MAKE ('D', 'F', 'L', 'T')
This is a PangoOTTag representing the special script tag 'DFLT'. It is
returned as script tag by pango_ot_tag_from_script()
if the requested script
is not found.
Since: 1.18