Write a complete runnable Processing code according to the user request near the end of this prompt. The code is run in Pure ink software via a feature called Kinetic Force. All graphics produced by Processing code in Pure ink exists on a Kinetic Force layer which is on top of the root paper layer of the digital painting. All technical rules and the authoritative Pure Ink API reference required for code generation are included below. Do not rely on external web access. The public learning page is for human reference only. Here are some rules about generating Processing code for Pure ink: RULE 1). Pure ink supports Processing's core library, its sound library and video library only. It allows interaction via mouse, keyboard, and camera input. For Java library, it support these: import java.lang.reflect.*; import java.io.*; import java.net.*; import java.util.*; RULE 2). Custom library imports of both Processing and Java from users are not supported. RULE 3). To use Processing sound or video library, you need to put 'import processing.sound.*;' or 'import processing.video.*;' onto the first line of your code If user requests playing video, use video library and Movie class. loop() does not work in Pure ink, and movieEvent() has no effect. To play a movie iteratively, declare a variable called 'idleTimes'. Then in draw(), check movie's availability. If the movie instance is not available, increment 'idleTimes'. If 'idleTimes' is equal to or larger than 3, stop movie and play it again to achieve looped display. Use tint(255, alpha) in setup() with alpha less than 255 if you determine that the artwork on root paper layer should be seen through the video. In this case, you need to run background(255,0) in draw() to refresh the background and this keeps the video semi-transparent. RULE 4). The mechanism of media file loading and saving in Pure ink programming is very similar with Processing. If user need to load media files in his Pure ink code (e.g. to load an image by loadImage()), user should be reminded to create a folder to store his .pure file first and then a 'data' subfolder inside this project folder. This 'data' subfolder is the default location where media loading functions point to. Then user should put the media files (e.g. 'myImage.jpg') into the data subfolder. The execution of 'loadImage("myImage.jpg")' should successfully load 'myImage.jpg'. If the Pure ink code involves media file loading or saving, you need to remind user to create this 'data' subfolder under his project folder by displaying it obviously as comments in the code. Please say it like this "To load/ save the image file of XXXX.XXX, you should save your Pure ink source file (.pure file) in a folder first, then create a subfolder called 'data' in this folder and put the image file XXXX.XXX in it for loading (or 'and then XXXX.XXX will be stored in it' for saving case)." Adjust the wording for different cases. RULE 5). to write a loading or saving path, please use '/' to construct it if it involves subfolder, avoid using '\' or '\\'. For example, write 'loadImage("mySubfolder/frame.png")' RULE 6). To write Processing code for Pure ink, size() is not allowed to use. The size of the visual effect is not determined by size() but determined by the paper size created by users in Pure ink. This information is stored in the variable of 'width' and 'height' and can be used directly in Pure ink code like how they can be used in Processing. DO NOT call size() in Pure ink or the code will be ignored and an waring message will be given. RULE 7). Concerning background(), sometime a background color with lower alpha value is suitable in Pure ink coding. The dynamic effect of Pure ink coding is displayed on the Kinetic Force layer on top of the Pure ink paper where digital painting is drawn on. If background color is totally non-transparent, the Kinetic Force layer may hide the Pure ink paper totally. If you determine that the dynamic effect has potential to integrate with the artwork painted on paper or user has such intention, you can set background with appropriate alpha (e.g. background(255, 128)) and remind users to adjust the alpha by themselves through the use of comments in the code. Then both digital painting and programming effect can be seen together. RULE 8). White background color without alpha specified will be converted to transparent, i.e. background(255) will be rewritten automatically as background(255,0). Any other background color without alpha specified will remain non-transparent. i.e. background(128) will remain as background(128). Any background color with specific alpha will remain unchanged too, i.e. background(255,128) will remain the same, background(255,0,0,128) will remain the same. RULE 9). For renderer, Pure ink only support JAVA2D and not the others. DO NOT use other renderers in Pure ink coding. DO NOT use functions that rely on renderers other than JAVA2D too (e.g. texture(), box(), lights(), camera(), shader(), hardware-accelerated composite blend modes, etc.). RULE 10). Mandatory use of the Pure Ink API The authoritative Pure Ink API reference is included immediately below in this prompt. The API is available and runnable in the current version of Pure Ink. For every request involving ink(水墨,墨), draw, paint(畫), painting(畫), Chinese painting(中國畫,水墨畫), pigment(顏料), brush behavior like dry brush(乾刷,飛白) and wet paint(濕畫法), brush(毛筆,畫筆), Chinese brush(中國毛筆), paper(宣紙,畫紙), canvas, paper behavior, wetness(濕度,水份,水量), diffusion(滲化,滲染,暈染), infiltration, fluidity, ink flow, Chinese ink(中國水墨), dynamic ink(數碼水墨,數字水墨), or interactive ink(互動水墨): 1. Inspect the supplied Pure Ink API reference before planning the code. 2. Use PureBrush and/or PurePaper whenever any documented API operation is applicable. 3. Processing functions may control trajectories, timing, interaction, geometry, and auxiliary graphics, but they must not replace ink, brush, pigment, or paper behavior already supported by the Pure Ink API. 4. Use only classes, constructors, methods, and parameter ranges explicitly documented in the supplied reference. Never invent API members. 5. Processing-only code is permitted only when no documented Pure Ink API class or method is relevant to any part of the requested effect. On the other hand, if user request (located near the end of this prompt) does not involve the above keywords, or includes keywords like "sketch", "draft", "generate", "visualise", "render", "display", "show", "artistic", "graphical", "art" but not include any of the above keywords, then do not consider the request is related to ink art or painting and do not use Pure Ink API, skip the following Pure ink API reference, use Processing graphics only, and directly jump to RULE 11 to save time and token input. For examples, "render a sunny scene", "display 10 stars on sky" should not trigger the use of Pure ink API. "paint a forest", "display a painting on my work" triggers the use of Pure ink API since the above keywords are involved. Check the meaning of user request too. If its meaning is explicitly unrelated with ink art, then do not use the Pure Ink API, skip the following Pure ink API reference, use Processing graphics only, and directly jump to RULE 11 to save time and token input. For the example: "blowing many paper on the air", "create ants walking on my paper", or "to brush the teeth in his mouth" although they involve the keyword "paper" or "brush", the requests are totally unrelated to ink art or painting, it should not trigger the use of Pure ink API. AUTHORITY AND SCOPE This is the authoritative Pure Ink API reference available to Kinetic Force in this version of Pure ink. PureBrush and PurePaper are built-in Pure ink API classes. They do not require import statements. Only the constructors and methods listed in this reference are supported. Never invent additional constructors, methods, fields, getters, setters, or related classes. In particular, do not invent methods such as setSize(), moveTo(), draw(), beginStroke(), endStroke(), diffuse(), setDiffusion(), setPaperWetness(), or classes such as PureShortBrush. Do not call size(). The width and height variables are supplied by Pure ink. ================================================== CLASS: PureBrush ================================================== PureBrush represents the long-hair digital brush in Pure ink. Use Processing calculations, animation, noise, mouse input, keyboard input, geometry, and other supported functions to calculate the brush trajectory. Use PureBrush.write(x, y) to make the actual ink marks whenever the requested effect involves ink, pigment, or brush behavior. PureBrush.write(x, y) delivers pigment onto the paper of the Kinetic Force layer rather than other paper layers of Pure ink. Pigment automatically diffuses on the paper of the Kinetic Force layer. CONSTRUCTORS -------------------- Single-pigment brush: PureBrush( float size, float brushLoad, float wetness, color pigmentColor) Dual-pigment brush: PureBrush( float size, float brushLoad, float tipWetness, color tipColor, float tuftWetness, color tuftColor) CONSTRUCTOR PARAMETERS size: Type: float Range: 0 to 1 0 means the thinnest brush. 1 means the thickest brush. brushLoad: Type: float Range: 0 to 1 0 means that the brush carries no pigment. 1 means that the brush is fully loaded with pigment. Lower brush load normally produces drier, broken, or discontinuous strokes. Higher brush load produces richer and more continuous strokes. wetness, tipWetness, tuftWetness: Type: float Range: 0 to 1 0 means that the pigment is most concentrated, opaque, and relatively dry. 1 means that the pigment is most diluted and wet. Wetter pigment generally produces stronger diffusion. pigmentColor, tipColor, tuftColor: Type: color These are Processing color values created with color(). The active colorMode() determines their format and range. In the dual-pigment constructor: tipWetness and tipColor belong to the brush tip. tuftWetness and tuftColor belong to the brush tuft. For the relations between brush size, pigment wetness, brush speed, and the stroke thickness for vertical brush, here are some reference data for you to determine the right combinations of brush size, wetness, and speed to paint stroke with appropriate thickness: reference 1 (biggest brush, minimum wetness, move slow): brush size = 1, brushLoad = 1, wetness = 0, the brush move by 1 pixel per frame, stroke thickness is 50 pixels reference 2 (biggest brush, minimum wetness, move fast): same as reference 1 except the brush move by 10 pixel per frame, stroke thickness is 30 pixels reference 3 (biggest brush, maximum wetness, move slow): same as reference 1 except the wetness is 1, stroke is very diffusive and thickness is 140 pixels reference 4 (medium brush, minimum wetness, move slow): brush size = 0.5, brushLoad = 1, wetness = 0, the brush move by 1 pixel per frame, stroke thickness is 20 pixels reference 5 (medium brush, minimum wetness, move fast): same as reference 4 except the brush move by 10 pixel per frame, stroke thickness is 9 pixels reference 6 (medium brush, maximum wetness, move slow): same as reference 4 except the wetness is 1, stroke is very diffusive and thickness is 93 pixels reference 7 (smallest brush, minimum wetness, move slow): brush size = 0, brushLoad = 1, wetness = 0, the brush move by 1 pixel per frame, stroke thickness is 2 pixels and slightly discontinuous reference 8 (smallest brush, minimum wetness, move fast): same as reference 7 except the brush move by 10 pixel per frame, stroke thickness is 1 pixels but highly discontinuous reference 9 (smallest brush, maximum wetness, move slow): same as reference 7 except the wetness is 1, stroke is very diffusive and thickness is 43 pixels For the relations between brush size, pigment wetness, and stroke thickness for inclined brush, read the reference data in setTilt() below. METHODS OF PureBrush -------------------- void write(float x, float y) Press the PureBrush at paper position (x, y) and deliver pigment there. PARAMETER: x Type: float the x position on paper to deliver pigment, the range where pigment can be seen is from 0 to width-1, where width is the internal core variable of Pure ink PARAMETER: x, y Type: float the y position on paper to deliver pigment, the range where pigment can be seen is from 0 to height-1, where height is the internal core variable of Pure ink Call write() repeatedly in draw() to create a continuous moving stroke. The increment of x and y controls the brush speed and affects the amount of pigment delivered to paper and thus the stroke quality. For interactive painting, positions such as mouseX and mouseY can be passed to write(). Processing functions can calculate the position, but PureBrush must produce the ink mark when RULE 10 applies. For inclined brush, the position (x, y) is the location where the root of tuft touches the paper, not the tip of tuft. You must beware of the additional area that the tuft body will touch the paper and deliver pigment there. Refer to the setTilt() part later to understand how inclination affect the stroke thickness. void dispose() Delete the PureBrush instance and release its resources. Do not call write(), lift(), setColor(), setWetness(), setBrushLoad(), setTilt(), or setRotation() on that instance after it has been disposed. When dispose() is called from draw(), normally use a boolean flag so that dispose() is called only once. void lift() Begin lifting the PureBrush away from the paper. This produces a narrowing, sharp tail at the end of the stroke. After calling lift(), allow draw() to continue running for some time so that the lift-off effect can finish. Do not immediately stop the program or dispose of the brush when a visible lift-off tail is required. void setBrushLoad(float brushLoad) Change the amount of pigment carried by the brush. PARAMETER: brushLoad Type: float Range: 0 to 1 Lower values produce less continuous and generally drier strokes. Higher values produce richer and more continuous strokes. void setColor(color pigmentColor) Set a single pigment color. PARAMETER: pigmentColor Type: color These are Processing color values created with color(). void setColor(color tipColor, color tuftColor) Set dual pigment colors. PARAMETERS: tipColor, tuftColor The first color belongs to the brush tip. The second color belongs to the brush tuft. void setWetness(float pigmentWetness) Set the wetness of a single pigment. PARAMETER: pigmentWetness Type: float Range: 0 to 1 void setWetness(float tipPigmentWetness, float tuftPigmentWetness) Set the wetness of the two pigments in a dual-pigment brush. PARAMETERS: tipPigmentWetness, tuftPigmentWetness: Type: float Range: 0 to 1 The first value belongs to the brush tip. The second value belongs to the brush tuft. Always use matching setColor() and setWetness() overloads: Single-pigment mode: setColor(oneColor) setWetness(oneWetness) Dual-pigment mode: setColor(tipColor, tuftColor) setWetness(tipWetness, tuftWetness) Do not combine the one-argument form of one method with the two-argument form of the other method. void setTilt(float angle) Set the angle between the brush and its vertical axis. PARAMETER: angle Type: float Range: 0 to 66 degrees 0 means that the brush is vertical. 5 means that the brush is at its minimum supported inclination 66 means that the brush is at its maximum supported inclination. Always keep the supplied value within 0 to 66. If tilt angle is larger than 0 but less than 5, it will be converted to 5 For the relation between tilt angle, brush size, wetness of pigment, and the thickness of the stroke being produced, here are some reference data for you to determine the right combinations of tilt angle, brush size, and wetness to paint stroke with appropriate thickness: reference 1 (maximum inclination, biggest brush) brush size = 1, wetness = 0.3, tilt = 66, rotation angle = 0, PureBrush moves rightward so that brush tuft is perpendicular to the moving path, the thickness of stroke is in maximum and is 613 pixels reference 2 (maximum inclination, medium brush) same case as reference 1 except brush size = 0.6, the stroke thickness is 396 pixels reference 3 (maximum inclination, small brush) same case as reference 1 except brush size = 0.3, the stroke thickness is 200 pixels reference 4 (maximum inclination, smallest brush) same case as reference 1 except brush size = 0.0, the stroke thickness is 16 pixels reference 5 (how high wetness influences the stroke thickness) same case as reference 1 except wetness is 0.7, then, due to the diffusing effect of pigment, the thickness of stroke boost up to around 700 pixels reference 6 (how maximum wetness influences the stroke thickness) same case as reference 3 except wetness is 1, then, due to the diffusing effect of pigment, the thickness of stroke boost up to around 320 pixels reference 7 (medium inclination, biggest brush) brush size = 1, wetness = 0.3, tilt = 30, rotation angle = 0, PureBrush moves rightward so that brush tuft is perpendicular to the moving path, the thickness of stroke is in maximum and is 430 pixels reference 8 (medium inclination, medium brush) same case as reference 7 except brush size = 0.6, the stroke thickness is 250 pixels reference 9 (medium inclination, small brush) same case as reference 7 except brush size = 0.3, the stroke thickness is 153 pixels reference 10 (medium inclination, smallest brush) same case as reference 7 except brush size = 0.0, the stroke thickness is 16 pixels reference 11 (smallest inclination, biggest brush) brush size = 1, wetness = 0.3, tilt = 5, rotation angle = 0, PureBrush moves rightward so that brush tuft is perpendicular to the moving path, the thickness of stroke is in maximum and is 216 pixels reference 12 (smallest inclination, medium brush) same case as reference 11 except brush size = 0.6, the stroke thickness is 161 pixels reference 13 (smallest inclination, small brush) same case as reference 11 except brush size = 0.3, the stroke thickness is 83 pixels reference 14 (smallest inclination, smallest brush) same case as reference 11 except brush size = 0.0, the stroke thickness is 14 pixels void setRotation(float angle) Set the horizontal azimuth rotation of an inclined brush. PARAMETER: angle Type: float Range: 0 to 360 degrees At 0 degrees, the inclined brush tip points toward the top of the screen. Increasing the value rotates the brush clockwise. Call setTilt() before setRotation() when changing a vertical brush into an inclined brush. If setRotation() is called before setting the tilt, Pure ink may force the brush to a tilt of approximately 30 degrees until setTilt(0) is called. void stopWrite() lifting off the PureBrush away from the paper immediately. Run this in between the two executions of PureBrush.write() if you intend to execute the second PureBrush.write() for a new stroke. Otherwise, PureBrush keeps touching the paper and continues the stroke even the positions indicated in these two executions of write() are separated far from each other. Different from lift(), running stopWrite() is instant and easier. Simply call stopWrite() one time after you finish one stroke and before you start a new one. IMPORTANT PureBrush LIMITATION No setSize() method. Brush size is selected when the PureBrush is constructed. If distinctly different brush sizes are required, create separate PureBrush objects with different constructor sizes and dispose of objects that are no longer required. ================================================== CLASS: PurePaper ================================================== PurePaper provides control over certain pigment behavior on the paper used by the Kinetic Force layer. By default, it represents YunLong paper in freehand-brushwork mode. Pigment delivered to this Kinetic Force paper diffuses automatically even no PurePaper instance is created. CONSTRUCTOR PurePaper() Get the PurePaper instance associated with the current Kinetic Force layer. METHODS OF PurePaper --------------------- void clear(float strength) Continuously clear pigment from the PurePaper at a speed controlled by strength. PARAMETER: strength Type: float Range: 0 to 1 0 means no clearing effect. 1 means the fastest clearing effect. Use an intermediate value to make pigment gradually fade or disappear. Call clear(0) to disable the clearing effect. Using clear() to achieve ink animation. It removes ink effect in the last frame for new ink effect to display in the next frame. Use clear(1) for fast update of frame. PImage clone() This function duplicates the content painted on the root paper layer and return it as a PImage PARAMETER: n/a consider using this function when user requests certain ink-related effects on their digital painting in Pure ink. You can further transfer the returned PImage onto the Kinetic Force layer by transfer(). Beware of the transparence of the background of the Kinetic Force layer. If the returned PImage will be modified such that it is not appropriate to co-exist with the original work on the paper layer, then set the background of the Kinetic Force layer to be non-transparent. void dispose() Delete the PurePaper instance and release its resources. After dispose() is called, do not call clear() on that instance. void quickDry(float dryness) to reduce the wetness of pigment on PurePaper and turn the paper dry. New pigment delivered on dry paper tends to be sharp and clear, rather than diffusive and unclear. PARAMETER: dryness Type: float Range: 0 to 1 0 means that no water is reduced from the PurePaper. 1 means that all water is reduced from the PurePaper, the PurePaper is completely dry. dryness is the percentage of water being reduced for each dot on paper, rather than the overall dry level of the paper. Setting dryness as 0.5 does not necessarily means that the paper is semi-dried. If a dot on paper carries high water value, reducing its water by half may still make this dot diffusive to new pigment on it. Set it to 1 to make the paper totally dry and make new strokes on it sharp and clear. Running quickDry() consumes time. You can run it in setup() or in draw(). If you run it in draw(), do not run it iteratively. Adjust your algorithm so that it is executed one time within a certain period of time. void transfer(PImage img, float x, float y, float wetness) This function transfer an image in PImage type onto a PurePaper with certain diffusing effect controlled by wetness. This gives painting style to an image and let it further integrate with the ink strokes created by PureBrush. transfer() also support transparent and semi-transparent image. Please note that image transfer happens on Kinetic Force layer and does not react with the digital painting on the root paper layer PARAMETER: img Type: PImage the image to be transferred onto PurePaper PARAMETER: x Type: float the x position of the top left corner of img PARAMETER: y Type: float Range: 0 to 1 the y position of the top left corner of img PARAMETER: wetness Type: float Range: 0 to 1 0 means that img is transferred without diffusing effect. 1 means that img is transferred with maximum diffusing effect. a wetness of '0.3' has gentle diffusive effect; '0' has transfer effect with no diffusion; '1' is highly diffusive. Instead of using PureBrush to paint an object stroke by stroke, An alternative is to use Processing functions to draw an object in PGraphics and then transfer this PGraphics onto Kinetic Force layer by transfer() with certain wetness value to create ink art effect. You can only use this approach if the object is not efficient to be painted by PureBrush but very efficient to be achieved by Processing functions. For example, if user request is to paint a rectangle, or to paint a cubist painting, or to paint an architecture. They can be done by the geometric rendering functions in Processing. On the other hand, if user request is to paint organic objects like bird, landscape, rock, figure, animal, etc., you must use PureBrush approach. void transferMode(int mode) This function sets the transfer mode for transfer(). There are either OVERLAP mode or COLORMIXING mode for image transfer. In OVERLAP mode, image is transferred on PurePaper by overlapping and hiding the graphics beneath it. In COLORMIXING mode, image is transferred on PurePaper by mixing its color with the color of graphics beneath it. Run transferMode() before transfer(). If transferMode() is missing, the transfer mode by default is OVERLAP. To change the transfer mode, simply running transferMode() again with the new mode. Both OVERLAP and COLORMIXING are internally defined variables in Pure ink for direct usage. For example, write 'transferMode(COLORMIXING);' PARAMETER: mode Type: int either OVERLAP or COLORMIXING. ================================================== API SELECTION GUIDE ================================================== > For ink marks, Chinese-brush strokes, wet strokes, dry strokes, discontinuous strokes, dynamic ink, interactive ink, ink flow, or pigment trails: Create a PureBrush and call PureBrush.write(). > For lively stroke: Use vertical brush by setting the Tilt angle to 0. Move the vertical brush with various speed. Low speed makes strokes thicker since more pigment is absorbed by the PurePaper while high speed makes strokes thinner since less pigment is absorbed. This makes strokes lively. > For thick stroke or for large area brushing: Use inclined brush by setting the Tile angle to be larger than 5 > For wet, diluted, highly diffusive wet paint: Use a relatively high PureBrush wetness value and high brushLoad, the pigment is very diffusive. This setting is good for creating a wash for the sky, etc. > For gently diffusive wet paint: Use a relatively high PureBrush wetness value but low brushLoad. This setting is good for drawing water reflection, background mountain, etc. To produce gently diffusive stroke with vertical brush, this is reference: brush size=0.3, brushLoad=0.05, pigment wetness=0.9, tilt angle=0, if brush move by every 2 pixels in one frame, it produces gently diffusive stroke > For concentrated, dark, or relatively opaque pigment: Use a relatively low PureBrush wetness value. Set wetness to 0 so that pigment can overlap on top of the old pigment > For strong, sharp, and fine strokes: Use vertical brush, set brushLoad to 1, set PureBrush wetness to 0 This setting is particularly good for calligraphy, or drawing twig, etc. Further set brush size to 0 to paint very fine and detailed objects like hairs, or outlining fingers, etc. > For dry stroke (乾筆): Use vertical brush, set brushLoad around 0.2 to 0.3, PureBrush wetness around 0.3. Dry stroke is good for outlining rough objects like rock, trunk, etc. The continuity of dry stroke is affected by the brush speed. Brush delivers less pigment on paper if brushLoad is low (0.2) and need slow motion (1 pixel per frame) to draw continuing stroke. If brushload is relatively higher (0.3), the brush can afford higher speed to draw continuing stroke. > For dry brush (i.e. discontinuous dry strokes, 乾刷、 飛白): Usually use inclined brush but sometime vertical brush is also considable. Dry brush is good for producing texture on rock surface, trunk surface, etc. BrushLoad takes major role to draw dry brush. For inclined brush, use low brushLoad and low wetness together, move brush faster. For vertical brush, brushLoad need to be relatively higher than the one used for inclined brush but sensitive to the change of brush size. For vertical brush, No pigment can be delivered to paper if both brushLoad and wetness are too low, move the vertical brush slower and never faster than 1 pixels per frame. To produce dry brush with inclined brush, these are references: reference 1: brush size=0.3, brushLoad=0.3, PureBrush wetness=0, tilt angle=30, rotation angle=0, brush move by every 6 pixels per frame, it produces nice dry brush. reference 2: same as reference 1 except brushLoad=0.15 and brush moves by every 3 pixels per frame, it produces dry brush with tiny strokes and fewer then reference 1. reference 3: same as reference 1 except wetness=0.3, the dry brush effect is still seen. But if wetness go up to 0.5, dry brush effect is not obvious. To produce dry brush with vertical brush, brush size affects the amount of pigment deliver on paper and affects the effect. All testing cases below set tilt angle=0 and move the brush by 1 pixels per frame, these are references: reference 4: brush size=0.3, brushLoad=0.3, wetness=0.1, it produces dry brush. reference 5: same as reference 4 except brush size=0.6, the stroke however is NOT so dry and NOT discontinuous since large brush delivery more pigment and water on paper. reference 6 (based on reference 5): brush size=0.6, brushLoad=0.18, wetness=0.1, it produces dry brush. reference 7 : same as reference 6 except brush size=1, the stroke however is NOT so dry and NOT discontinuous since large brush delivery more pigment and water on paper reference 8 (based on refernece 7): brush size=1, brushLoad=0.1, wetness=0.3, it produces dry brush. > To draw fine or dry strokes on wet paint: If fine or dry strokes are added on wet paint and their sharpness is needed to be preserved, you must apply quickDry(dryness) first to make the wet paint dry, otherwise new pigment will diffuse and lose its sharpness. Set dryness to be at least 0.8. If you draw details with fine or dry strokes on wet paint, run quickDry(1). Do not apply quickDry() if you intend to diffuse fine or dry strokes by wet paint. > For one-brush-two-colors effects: Use the six-argument PureBrush constructor or the two-argument versions of setColor() and setWetness(). This effect is very good for ink-style painting. You should always consider using this approach. > For an inclined brush: Call setTilt() first and then setRotation(). > For gradually clearing, fading, or removing pigment: Create a PurePaper and call PurePaper.clear(). If PureBrush writes while PurePaper.clear() is running, the strokes tends to be thinner since new pigment near the stroke edge will be clear imemdiately. For such case, increase PureBrush wetness or brush size to compensate. There is no direct diffuse() method in the documented API. The pigment delivered to the paper of Kinetic Force layer via write() automatically diffuses. Create diffusion through different combinations of pigment wetness and brushLoad. Never invent a diffusion method. Processing functions may calculate paths, movement, timing, interaction, noise, forces, geometry, and auxiliary graphics. They must not replace PureBrush or PurePaper behavior when the documented API is applicable. ================================================== COMPLETE PureBrush SYNTAX EXAMPLE ================================================== The following is a complete structural example. Generated visual artwork should normally be more developed than this example: PureBrush inkBrush; float brushX; boolean lifting; void setup() { inkBrush = new PureBrush(0.22, 1.0, 0.75, color(20, 20, 20)); inkBrush.setTilt(28); inkBrush.setRotation(90); brushX = width * 0.1; lifting = false; } void draw() { if (!lifting) { float brushY = height * 0.5 + sin(brushX * 0.025) * height * 0.08; inkBrush.write(brushX, brushY); brushX = brushX + 1.5; if (brushX >= width * 0.6) { inkBrush.lift(); lifting = true; } } // draw() intentionally continues running so that the // lift-off tail has time to finish. } RULE 11). When the user asks for a visual drawing, animation, or generative artwork, do not produce a minimal demonstration unless the user requests for that. Create a polished result with very fine visual quality with advanced algorithm. Prefer layered composition, rich gradients, sense of depth, procedural noise, shadows, highlights, smooth and realistic motion. Now, I want you to write me a Processing program for Pure ink. The request is: #*(user request is here)*#. Before writing code, decide whether the request can be implemented as runnable Processing code for Pure ink. If the request can be implemented but need extra attention from the user (for example, user need to set up a 'data' subfolder inside the project folder for loading or saving media files, or user need to adjust the alpha value of background color in background() to integrate the coding effect with the digital painting on Pure ink paper, etc.), then please specify these in a format of comments and put them on top of the generated code so that user can read and pay attention to. On the other hand, if the request cannot be implemented as runnable Processing code for Pure ink because Pure ink supports only JAVA2D and limited Processing/Java libraries and does not allow custom library imports, then do not invent unsupported code.