diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..93c4b27b4
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+github: processing
+custom: https://processingfoundation.org/
diff --git a/.gitignore b/.gitignore
index b006f9e2d..27c953a9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,5 @@ exhibition/
about/
contrib_generate/contribs.txt # File now built on the server side; don't need to track here
contrib_generate/contributions.txt # File now built on the server side; don't need to track here
+*~
+/bin/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..9f20dd7ba
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,15 @@
+## Contributing to Processing
+
+Wow, thank you for helping us out!
+
+## Reporting Issues
+
+**[Here's how to report a bug with Processing.](https://github.com/processing/processing/wiki/Report-Bugs)**
+
+Before logging a new issue, please please please review [that document](https://github.com/processing/processing/wiki/Report-Bugs) closely. Processing is a complex project housed across several repositories. A quick read on your part now will save us all a lot of hassle later.
+
+## Other Contributions
+
+See the [Processing wiki](https://github.com/processing/processing/wiki#contribute) for how to contribute in other ways.
+
+Thank you!
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 000000000..71ae8ba7c
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,10 @@
+### Issue description
+
+
+
+### URL(s) of affected page(s)
+
+
+
+### Proposed fix
+
diff --git a/README.md b/README.md
index c0183179c..60a674da3 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,14 @@
+> ⚠️ This repository is now deprecated and will be archived soon. If you have any issues or want to submit a pull request, please direct them to the [processing-website](https://github.com/processing/processing-website) repo. Make sure to check the [README](https://github.com/processing/processing-website/blob/main/README.md) for information on how to contribute to the documentation.
+
+
+
Processing Documentation
==========
-This is the official source code for the Processing reference, examples, tutorials, and [processing.org](http://processing.org) web site.
+~~This is the official source code for the Processing reference, examples, tutorials, and [processing.org](http://processing.org) web site.~~
-If you have found an error in the Processing reference, examples, tutorials, or website you can file it here under the ["issues" tab](https://github.com/processing/processing-docs/issues).
+~~If you have found an error in the Processing reference, examples, tutorials, or website you can file it here under the ["issues" tab](https://github.com/processing/processing-docs/issues).~~
-The [processing](https://github.com/processing/processing) repository contains the source code for Processing itself. (Please use that link to file issues regarding the Processing software.)
+~~The [processing](https://github.com/processing/processing) repository contains the source code for Processing itself. (Please use that link to file issues regarding the Processing software.)~~
diff --git a/config-f.php b/config-f.php
deleted file mode 100644
index 500644b22..000000000
--- a/config-f.php
+++ /dev/null
@@ -1,47 +0,0 @@
- array('English', 'utf-8', true, $domain) //,
- //'zh' => array('Chinese Traditional', 'big5', false, $domain."zh/"),
- //'zh-cn' => array('Chinese Simplified', 'GB2312', false, $domain."zh-cn/"),
- //'fr' => array('French', 'utf-8', true, $domain."fr/"),
- //'id' => array('Indonesian', 'utf-8', false, $domain."id/"),
- //'it' => array('Italian', 'utf-8', true, $domain."it/"),
- //'jp' => array('Japanese', 'Shift_JIS', false, 'http://stage.itp.tsoa.nyu.edu/~tk403/proce55ing_reference_jp/'),
- //'kn' => array('Korean', 'utf-8', false, 'http://www.nabi.or.kr/processing/'),
- //'es' => array('Spanish', 'utf-8', true, $domain."es/"),
- //'tr' => array('Turkish', 'ISO-8859-9', true, $domain."tr/"),
- //'he' => array('Hebrew', 'Windows-1255', false, ''),
- //'ru' => array('Russian', 'ISO-8859-5', false, ''),
- //'pl' => array('Polish', 'ISO-8859-2', false, '')
- );
-// Langauges with finished references available to the public
-$FINISHED = array('en');
-
-// for reference index formatting
-$break_before = array('Shape', 'Color');
-
-?>
\ No newline at end of file
diff --git a/content/api_en/HALF_PI.xml b/content/api_en/HALF_PI.xml
index 3d83e4c53..723fb55e1 100755
--- a/content/api_en/HALF_PI.xml
+++ b/content/api_en/HALF_PI.xml
@@ -22,7 +22,7 @@ arc(x, y, d-60, d-60, 0, TWO_PI);
- The Hardware I/O library allows to access the computer's hardware periperals, such as digital
+ The Hardware I/O library allows access to the computer's hardware periperals, such as digital
inputs and outputs, serial busses, and the like, in a fashion similar to the Arduino plaform.
This library is only available for embedded Linux boards with the necessary kernel drivers,
such as the Raspberry Pi.
@@ -28,7 +28,7 @@
- The PWM class controls hardware Pulse-width modulation channels, if supported by your platform.
- The RPI class is a helper for use with the Raspberry Pi.
- The new Sound library for Processing 3 provides a simple way to work with audio. It can play, analyze, and synthesize sound. The library comes with a collection of oscillators for basic wave forms, a variety of noise generators, and effects and filters to alter sound files and other generated sounds. The syntax is minimal to make it easy to patch one sound object into another.
-
- The source code is available on the processing-sound GitHub repository. Please report bugs here. This library is only compatible with Processing 3.0+.
-
-
- I/O
-
- AudioDevice
- SoundFile
- Noise
-
- WhiteNoise
- SinOsc
- Env
+ The new Sound library for Processing 3 provides a simple way to work with audio. It can play, analyze, and synthesize sound. It provides a collection of oscillators for basic wave forms, a variety of noise generators, and effects and filters to play and alter sound files and other generated sounds. The syntax is minimal to make it easy to patch one sound object into another. The library also comes with example sketches covering many use cases to help you get started.
+
+ The source code is available on the processing-sound GitHub repository. Please report bugs here. This library is only compatible with Processing 3.0+.
+
+
+ Configuration
+
+ Sound
+ AudioIn
+ SoundFile
+ Noise
+
+ WhiteNoise
+ SinOsc
+ Env The SVG library makes it possible to write SVG files directly from Processing. These vector graphics files can be scaled to any size and output at very high resolutions. The SVG library can flatten 3D data into a 2D vector file, but to export 3D data, use the DXF library. The source code is available on the Processing GitHub repository. Please report bugs here.
+SVG Export (No Screen Display) SVG Export (With Screen Display) Single Frame from an Animation (With Screen Display) SVG Files from 3D Geometry (With Screen Display) When using beginRaw() and endRaw(), it's possible to write to either a 2D or 3D renderer.
+For instance, beginRaw() with the SVG library will write the geometry as flattened triangles
+and lines. Using createGraphics() to Create an SVG File
+Additional notes for the SVG renderer:
+
+
- Additional commands are found within the five menus: File, Edit, Sketch, Debug, Tools, Help.
+ Additional commands are found within the six menus: File, Edit, Sketch, Debug, Tools, Help.
The menus are context sensitive which means only those items relevant to the work currently
being carried out are available.
Sketches written in this mode can be exported to run on Android phones and tablets.
- This mode is documented on the
- Processing for Android page of the Processing Wiki. To add this mode, click on
+ This mode is documented on the
+ Processing for Android page. To add this mode, click on
the mode button in the upper-right corner of the PDE and select "Add Mode..."
- The Export information and
+ The Export information and
Tips page on the Processing Wiki covers the details of exporting Applications from Java mode.
Send and receive data over the Internet through simple clients and servers. Create SVG files. Send data between Processing and external hardware through serial communication (RS-232).
+ Processing for Android: Create Mobile, Sensor-Aware, and VR Applications Using Processing
+ Creating Procedural Artworks with Processing Die eigenständige Programmiersprache Processing basiert auf Java und ähnelt diesem sehr, verbirgt aber gleichzeitig viel von dessen Komplexität. Dadurch ist Processing für den Programmieranfänger ideal geeignet, um sich Konzepte des Programmierens zu erschließen und bewahrt gleichzeitig die Möglichkeit eines späteren Umstiegs. Dennoch ist die Sprache keineswegs nur für triviale Anfängeraufgaben geeignet: speziell im Bereich der graphischen Datenverarbeitung spielt Processing seine Stärken aus. Dieses Buch richtet sich in erster Linie an den Einsteiger, den es an die Bewältigung auch komplexerer Aufgaben heranführt, wobei grundlegende Konzepte der imperativen und der objektorientierten Programmierung vorgestellt werden. Auch notwendige theoretische Hintergründe kommen dabei nicht zu kurz. Ausführlich kommentierter Beispielcode erschließt Konzepte und Sprache. Aber auch der routinierte Programmierer, der sich "nur" eine neue Sprache erschließen will, wird fündig! Aus dem Inhalt: Datentypen — Variablen — Arrays (ein- und mehrdiomensional) — Flusssteuerung — Methoden — Objektorientiertes Programmieren — 2D-Graphik — 3D-Graphik — Dateizugriff — PDF — QuickTimeTM — Arduino®-Mikrocontroller — Alphabetischer Index
+ Matthias Wolf. Die eigenständige Programmiersprache Processing basiert auf Java und ähnelt diesem sehr, verbirgt aber gleichzeitig viel von dessen Komplexität. Dadurch ist Processing für den Programmieranfänger ideal geeignet, um sich Konzepte des Programmierens zu erschließen und bewahrt gleichzeitig die Möglichkeit eines späteren Umstiegs. Dennoch ist die Sprache keineswegs nur für triviale Anfängeraufgaben geeignet: speziell im Bereich der graphischen Datenverarbeitung spielt Processing seine Stärken aus. Dieses Buch richtet sich in erster Linie an den Einsteiger, den es an die Bewältigung auch komplexerer Aufgaben heranführt, wobei grundlegende Konzepte der imperativen und der objektorientierten Programmierung vorgestellt werden. Auch notwendige theoretische Hintergründe kommen dabei nicht zu kurz. Ausführlich kommentierter Beispielcode erschließt Konzepte und Sprache. Aber auch der routinierte Programmierer, der sich "nur" eine neue Sprache erschließen will, wird fündig! Aus dem Inhalt: Datentypen — Variablen — Arrays (ein- und mehrdiomensional) — Flusssteuerung — Methoden — Objektorientiertes Programmieren — 2D-Graphik — 3D-Graphik — Dateizugriff — PDF — QuickTimeTM — Arduino®-Mikrocontroller — Alphabetischer Index
Earlier releases have been removed because we can only support the current versions of the software. To update old code, read the changes page. Changes for each release can be found in revisions.txt. If you have problems with the current release, please file a bug so that we can fix it. Older releases can also be built from the source. Read More about the releases and their numbering. To use Android Mode, Processing 3 or later is required. The changes document covers incremental updates between 4.x releases, and is especially important to read for pre-releases.
- Processing is open source, free software. All donations fund the Processing Foundation, a nonprofit organization devoted to advancing the role of programming within the visual arts through developing Processing.
-
-
-The Processing Foundation maintains a fellowship program that supports the development and expansion of Processing and its affiliated projects. Work done by fellows is supported through funding and mentorship from The Processing Foundation. The projects done so far have all been undertaken in parallel with each of the fellows’ practices as artists.
-
-
-Wilm Thoben (2013-14)
-
-Thoben developed a new core Sound library from fall 2013 through winter 2014. This library is now released with Processing 3.0.
-
-Lauren McCarthy (2013)
-
-McCarthy started the work that has now become p5.js in spring, summer, and fall 2013. p5.js is a JavaScript interpretation of Processing.
-
-Greg Borenstein (2013)
-
-Borenstein expanded and released the OpenCV library in spring and summer 2013.
-
-
- Since its inception in 2001, Processing has sought to bridge the traditionally divided cultures of the arts and the sciences. The mission of the Processing Foundation is to link these two cultures so they can be used within a diverse constituency, by way of developing the Processing software. For those with a tendency to think in numbers, Processing introduces a language of the visual arts through a more familiar computer science vocabulary. Likewise, the software is structured through an image-based framework, making it accessible to visual thinkers. Core computer science concepts like variables, functions, and conditionals are taught side by side with visual basics like image, shape, and color.
-
- The key to our philosophy is the merging between the two: we see software as a medium, or something that connects two things. We view it as a means for making, and see our role as providing a new medium to artists and users across a variety of fields. At a time when our society requires a literacy and sensitivity to media of all kinds, we see ourselves making this possible for a broad spectrum of constituencies.
-
-
- Processing serves a wide range of communities in different contexts, from the university classroom to the tinkerer’s garage, used by everyone from the professional to the hobbyist. Within education at a university level, we have seen Processing leveraged as a classroom tool across disciplines as varied as computer science, English, art, architecture, design, and the digital humanities. In the last few years, it has begun to become a presence in high school and middle school classrooms, being particularly effective when used to teach science, math, and more generally, computer science. For example, the Kahn Academy now uses Processing’s tutorials and language in their beginning computer science instruction. In areas of professional development, Processing has become enfolded into the practices of interface and communication designers, artists and media artists, photographers, architects, and filmmakers. It also has a substantial role in the communities of makers and amateurs, and among hackerspaces and gatherings of hobbyists.
-
-
- The growing use of Processing in the classroom over the last twelve years has pointed toward a direction to rethink the way students are taught to program. Instead of learning a specific vocational skill (such as any one certain programming language or software), the teaching of Processing follows from a philosophy that advocates for a more generalized and strategic way of thinking. Because technology changes at such a rapid pace, the goal of any education in software has to teach the fundamentals of programming. With knowledge of such a foundation, a student is able to learn any other piece of software. Processing was specifically designed to relate to other languages, so a working knowledge of it means that a student can become well-versed in others that are more domain-specific, in relatively little time. Also, it uses a visual framework, so as to be more accessible to people who don’t naturally think like mathematicians or computer scientists. This has opened the door for software to become part of an artist’s toolkit in a way never before seen.
-
- The use of Processing within the visual arts and design fields has grown continuously since the software was first released. Appearing at a critical moment when artists began introducing new media and technology into their practices, Processing has allowed for thousands of creative professionals to leverage it as a medium, changing the landscape of the arts at the beginning of the 21st century. Software is still a nascent medium for artists and designers, and part of The Processing Foundation’s mission is to nurture this trajectory to be both widely used and accepted.
-
- Within technology, Processing has made it possible to understand massive data sets in a visual and more accessible way. It has also helped foster the connection between engineering and visual design that has been pushed to the fore by Apple and others.
-
- The Processing Foundation was founded in 2012 with the two-fold mission to promote software literacy within the visual arts, and visual literacy within technology-related fields. Our primary goal is to empower people of all interests and backgrounds to learn how to program, so as to facilitate a sophisticated way of thinking about and creating media at a time when such knowledge is crucial. We do this by developing and distributing a group of related software projects, which includes Processing (Java), p5.js (Javascript), and Processing.py (Python).
-
-We serve a growing community of artists, designers, educators, programmers, engineers, and anyone in between who has an inclination toward both the arts and technology. Core to our belief is that learning how to program is a process of learning how to think, rather than acquiring a certain skillset, so that this knowledge may be applied to any number of fields, from creating artworks to imagining new technologies. We view Processing as a means to bridge seemingly disparate disciplines, providing platforms for collaboration between communities that might not otherwise have had access to each other. We also envision Processing as a new tool for both artists and technologists to use in their work, as a medium and as a context. We see ourselves situated at the place of convergence between the arts and technology, facilitating the pursuit and literacy of both.
-
-Processing is primarily developed by a dedicated group affiliated with Fathom Information Design (Boston), the UCLA Arts Software Studio (Los Angeles), and ITP at NYU (New York City).
-
- The Processing Foundation supports a fellowship program to initiate and develop research projects for the Processing software.
-
-We are supported by our community and actively seek donations through downloads of Processing.
-
-Contact us at foundation@processing.org
-
-
-
- Individuals making $5 to $100 donations are the largest source of income for the Processing Foundation. We’re grateful to all who have donated and we’re proud to be supported by the community. You can donate when you download the software here.
-
- The University of Denver and the Emergent Digital Practices program sponsored a Processing 3.0 development meeting in November 2014. We thank Chris Coleman and Laleh Mehran for arranging this session and gracefully hosting us.
-
- The Google Summer of Code program has provided and excellent source of energy and new development through supporting students to work with us. This program has now supported Processing for four years, 2010 to 2014. It has provided the base for many important enhancements to the software.
-
- In 2013, O'Reilly Media and Arduino made donations to the Processing Foundation.
-
- Prior to incorporating as a Foundation, Processing received key funding and support from several organizations and companies. These commitments enabled a series of pivotal improvements to the software:
-
-
- Processing is a programming language, development environment, and online community. Founded in 2001, Processing was initially created to serve as a software sketchbook and to teach computer programming fundamentals within a visual context. Processing has since evolved into a development tool for professionals, an educational tool used in classrooms around the country, and a new context and medium for artists. Today, there are tens of thousands of students, artists, designers, researchers, and hobbyists who use Processing for learning, prototyping, and production.
-
- It was designed to be a user’s first programming language, inspired by earlier languages like BASIC and Logo, as well as our experiences as students and teaching visual arts foundation curricula. It is now used in classrooms worldwide, often in art schools and visual arts programs in universities, but also in high schools, computer science programs, and humanities curricula.
-
- In addition to educational purposes, the Processing software is used by thousands of visual designers, artists, and architects to create their works. Projects created with Processing have been featured at the Museum of Modern Art in New York, the Victoria and Albert Museum in London, the Centre Georges Pompidou in Paris, and many other prominent venues. Processing is used to create projected stage designs for dance and music performances; to generate images for music videos and film; to export images for posters, magazines, and books; and to create interactive installations in galleries, in museums, and on the street.
-
- p5.js is a JavaScript library that starts with the original goal of Processing--to make coding accessible for artists, designers, educators, and beginners--and reinterprets this for today's web. Using the original metaphor of a software sketchbook, p5.js has a full set of drawing functionality for the entire browser page. For this, p5.js has addon libraries that streamline interaction with other HTML5 objects, including text, input, video, webcam, and sound.
-
- Having just been released, p5.js is in active development, with an official editing environment and other features coming soon.
-
- Our most recent initiative: To write Processing code. In Python.
-
- We are thrilled to make available this public release of the Python Mode for Processing, and its associated documentation. If you'd like to help us improve the implementation of Python Mode and its documentation, please find us on Github.
-
-
-
- We had a busy and productive 2013 with a wide range of activities:
-
- The Processing Foundation participated in Google Summer of Code for its fourth consecutive year in 2014, completing a total of eleven projects (summarized below) with a group of dedicated, innovative, and inspiring students.
-
- In 2013, our third year participating in Google Summer of Code, the Processing Foundation completed four projects in collaboration and mentorship with a group of talented students.
-
-
-
- The goal of the Processing Foundation is to promote software literacy, particularly within the visual arts, and to promote visual literacy within technology. Our primary charge is to develop and distribute the Processing software, both the core Application Programming Interface (API) and the programming environment, the Processing Development Environment (PDE). The board of directors for the Processing Foundation consists of Ben Fry, Casey Reas, and Dan Shiffman. The first member of the board of advisors is John Maeda.
-
- To succeed, the Foundation needs to raise money to support future versions of the Processing software and related initiatives. The Processing team, a small group of volunteers, has released over 200 versions of the software since 2001, leading to the 2.0 release in the spring of 2013.With almost no funding between the 1.0 and 2.0 releases, the software was written slowly while the developers managed full-time work and many other responsibilities. The 2.0 software release happened in an unsustainable way, at tremendous personal expense to the lead developers. The Foundation must raise funding for the initiative to continue.
-
- With the 2.0 software release, we're now asking for donations from individuals who use the software, and we're actively seeking larger gifts from individuals, companies, and other non-profit organizations. To learn more about why you might want to contribute, please read the 2013 status report below. The Processing Foundation was publicly announced in June 2013 with the release of the Processing 2.0 software. Our official non-profit status was was granted by the IRS on 6 March 2014, with our tax exception status retroactive to our date of formation, 14 June 2012.
-
- We had a busy and productive 2013 with a wide range of activities:
-
- Despite the new fundraising goals, Processing remains almost entirely a volunteer organization pushed forward by a small group of people. In starting our fundraising push, the initial goal was to hire one full-time developer to maintain and build the Processing code base, while the current Processing team continues to volunteer time to the project. We've received a constant stream of donations through the Download page interface, but at the end of nine months the amount is about 10% of what we need to hire a developer. We're currently utilizing the donations to support Processing Fellows, short-term appointments to explore future directions for Processing and to produce essential libraries. For instance, we supported Lauren McCarthy to explore new ideas for integrating Processing with JavaScript and we supported Greg Borenstein to development the new OpenCV library.
-
- Individuals making $5 to $100 donations are the largest source of income for the Processing Foundation. We're grateful to all who have donated and we're proud to be supported by the community.
-
- In 2013, O'Reilly Media and Arduino made donations to the Processing Foundation.
-
- The Google Summer of Code program has provided and excellent source of energy and new development through supporting students to work with us. This program has now supported Processing for three years, 2010 to 2013. It has provided the base for many important enhancements to the software.
-
- Prior to incorporating as a Foundation, Processing received key funding and support from several organizations and companies. These commitments enabled a series of pivotal improvements to the software.
-
- The Interactive Telecommunications Program (ITP) at New York University sponsored a Processing 2.0 development workshop in the summer of 2011.
-
- The Armstrong Institute for Interactive Media Studies at Miami University funded The Oxford Project, a series of Processing development workshops during the 2008-2009 academic year. These four-day meetings in Oxford, Ohio, enabled the November 2008 launch of Processing 1.0 and stimulated future development.
-
- Oblong Industries funded Ben Fry to develop Processing during the summer of 2008. This funding also assisted in the completion of the 1.0 release. The Rockefeller Foundation awarded Ben Fry with a Media Arts Fellowship in 2006. The grant marked the first time that Ben was able to work on Processing as a funded project. This support led to further developments of the OpenGL and PDF rendering engines, as well as significant enhancements to other libraries and their integration.
-
- The Interaction Design Institute Ivrea funded four individuals' work on Processing in the summer of 2003. This resulted in Dan Mosedale's preprocessor using Antlr, Sami Arola's contributions to the graphics engine, and other contributions to the Processing Development Environment and 2D graphics engine. We are grateful to Interaction Ivrea director Gillian Crampton Smith for her encouragement and support.
-
@@ -28,7 +28,7 @@
- Interviews with SUE.C, Larry Cuba, Mark Hansen, Lynn Hershman Leeson, Jürg Lehni, LettError, Golan Levin and Zachary Lieberman, Benjamin Maus, Manfred Mohr, Ash Nehru, Josh On, Bob Sabiston, Jennifer Steinkamp, Jared Tarbell, Steph Thirion, and Robert Winter.
+ Interviews with SUE.C, Larry Cuba, Mark Hansen, Lynn Hershman Leeson, Jürg Lehni, LettError, Golan Levin and Zachary Lieberman, Benjamin Maus, Manfred Mohr, Ash Nehru, Josh On, Bob Sabiston, Jennifer Steinkamp, Jared Tarbell, Steph Thirion, and Robert Winter.
- For the past fourteen years, Processing has promoted software literacy, particularly within the visual arts, and visual literacy within technology. Initially created to serve as a software sketchbook and to teach programming fundamentals within a visual context, Processing has also evolved into a development tool for professionals. The Processing software is free and open source, and runs on the Mac, Windows, and GNU/Linux platforms.
-
-
- Processing continues to be an alternative to proprietary software tools with restrictive and expensive licenses, making it accessible to schools and individual students. Its open source status encourages the community participation and collaboration that is vital to Processing’s growth. Contributors share programs, contribute code, and build libraries, tools, and modes to extend the possibilities of the software. The Processing community has written more than a hundred libraries to facilitate computer vision, data visualization, music composition, networking, 3D file exporting, and programming electronics.
+ For the past sixteen years, Processing has promoted software literacy, particularly within the visual arts, and visual literacy within technology. Initially created to serve as a software sketchbook and to teach programming fundamentals within a visual context, Processing has also evolved into a development tool for professionals. The Processing software is free and open source, and runs on the Mac, Windows, and GNU/Linux platforms.
- Processing is currently developed primarily in Boston (at Fathom Information Design), Los Angeles (at the UCLA Arts Software Studio), and New York City (at NYU’s ITP).
+ Processing continues to be an alternative to proprietary software tools with restrictive and expensive licenses, making it accessible to schools and individual students. Its open source status encourages the community participation and collaboration that is vital to Processing’s growth. Contributors share programs, contribute code, and build libraries, tools, and modes to extend the possibilities of the software. The Processing community has written more than a hundred libraries to facilitate computer vision, data visualization, music composition, networking, 3D file exporting, and programming electronics.
- The innovations in teaching through Processing have been adapted for the Khan Academy computer science tutorials, offered online for free. The tutorials begin with drawing, using most of the Processing functions for drawing. The Processing approach has also been applied to electronics through the Arduino and Wiring projects. Arduino uses a syntax inspired by that used with Processing, and continues to use a modified version of the Processing programming environment to make it easier for students to learn how to program robots and countless other electronics projects.
+ The innovations in teaching through Processing have been adapted for the Khan Academy computer science tutorials, offered online for free. The tutorials begin with drawing, using most of the Processing functions for drawing. The Processing approach has also been applied to electronics through the Arduino and Wiring projects. Arduino uses a syntax inspired by that used with Processing, and continues to use a modified version of the Processing programming environment to make it easier for students to learn how to program robots and countless other electronics projects.
-The primary charge of the Foundation is to develop and distribute the Processing software. This includes the original Processing (Java), p5.js (Javascript), and Processing.py (Python). There is more information about the Foundation at http://foundation.processing.org/.
+The primary charge of the Foundation is to develop and distribute the Processing software. This includes the original Processing (Java), p5.js (Javascript), and Processing.py (Python). There is more information about the Foundation at https://processingfoundation.org/.
- Processing was started by Ben Fry and Casey Reas in the spring of 2001, while both were graduate students at the MIT Media Lab within John Maeda's Aesthetics and Computation research group. Development continued in their free time while Casey pursued his artistic and teaching career and Ben pursued a Ph.D. and founded Fathom Information Design. Many of the ideas in Processing go back to Muriel Cooper's Visual Language Workshop, and it grew directly out of Maeda's Design By Numbers project, developed at the Media Lab and released in 1999. The Wiring and Arduino projects, in turn, grew out of Processing while Casey was teaching at the Interaction Design Institute Ivrea in Italy. Processing also prompted John Resig (jQuery) to build Processing.js, a JavaScript version that then inspired more related work such as the Khan Academy curriculum in computer science. Versions of Processing that use Python, Ruby, ActionScript, and Scala are also in development. Processing and its sister projects have inspired over twenty educational books.
+ Processing was started by Ben Fry and Casey Reas in the spring of 2001, while both were graduate students at the MIT Media Lab within John Maeda's Aesthetics and Computation research group. Development continued in their free time while Casey pursued his art and teaching career and Ben pursued a Ph.D. and founded Fathom Information Design. Many of the ideas in Processing go back to Muriel Cooper's Visual Language Workshop, and it grew directly out of Maeda's Design By Numbers project, developed at the Media Lab and released in 1999. The Wiring and Arduino projects, in turn, grew out of Processing while Casey was teaching at the Interaction Design Institute Ivrea in Italy.
For more information, please write to foundation@processing.org
diff --git a/content/static/people.html b/content/static/people.html
index ed14bc057..d406b648c 100755
--- a/content/static/people.html
+++ b/content/static/people.html
@@ -6,78 +6,57 @@
- Lead Developers
- Senior Developers
+
-
+
Libraries, Tools
- Fellowship Alumni
- Developer Alumni
-
-
We offer a special "Thank You!" to Sami Arola for writing the base of the original P3D
- and Simon Greenwold for incorporting camera and lights. Tom Carden contributed great
+ and Simon Greenwold for incorporating camera and lights. Tom Carden contributed great
energy by co-creating Processing Hacks and maintaining Processing Blogs. Andreas Schlegel
did amazing work for over three years organizing the Contributed Libraries and building
templates and documentation.
diff --git a/content/static/shop/index.html b/content/static/shop/index.html
index 64177106e..bcfd0ba95 100644
--- a/content/static/shop/index.html
+++ b/content/static/shop/index.html
@@ -114,7 +114,7 @@ Some helpful tips when you’re working with Processing & Android: - I know I’ve said this before, but be patient. Canceling a process (ie. the emulator load or a device compile) can cause problems. If you do this inadvertently, you’re best off restarting Processing. - Make sure to check out the Processing Android Wiki, where you’ll find some troubleshooting advice, and some tips on how to get your sketches working properly on your device. - Make sure to check out the Processing Android Wiki, where you’ll find some troubleshooting advice, and some tips on how to get your sketches working properly on your device. This tutorial is for Processing version 2.0+. If you see any errors or have comments, please let us know. This tutorial is adapted from 'Processing & Android: Mobile App Development Made (Very) Easy' by Jer Thorp
Does 0-255 seem arbitrary to you?
+ This tutorial is from the book Learning Processing by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. If you see any errors or have comments, please let us know.
+
+ This tutorial picks up where the Strings and Drawing Text tutorial leaves off and examines how to use String objects as the basis for reading and writing data. We'll start by learning more sophisticated methods for manipulating Strings, searching in them, chopping them up, and joining them together. Afterwards, we'll see how these skills allow us to use input from data sources, such as text files, web pages, xml feeds, and 3rd party APIs and take a step into the world of data visualization.
+
+ In Strings and Drawing Text, we touched on a few of the basic functions available in the Java String class, such as charAt(), toUpperCase(), equals(), and length(). These functions are documented on the Processing reference page for Strings. Nevertheless, in order to perform some more advanced data parsing techniques, we'll need to explore some additional String manipulation functions documented in the Java API.
+
+ Let's take a closer look at the following two String functions: indexOf() and substring(). indexOf() locates a sequence of characters within a String. It takes one argument, a search String, and returns a numeric value that corresponds to first occurrence of the search string inside of the string being searched.
+
+ Strings are just like arrays, in that the first character is index number zero and the last character is the length of the string minus one. If the search string cannot be found, indexOf() returns -1. This is a good choice because -1 is not a legitimate index value and therefore can indicate "not found." After finding a search phrase within a String, we might want to separate out part of the string, saving it in a different variable. A part of a string is known as "substring." The substring() function which takes two arguments, a start index and an end index and returns the substring in between the two indices.
+ Note that the substring begins at the specified start index (the first argument) and extends to the character at end index (the second argument) minus one. I know. I know. Wouldn't it have been easier to just take the substring from the start index all the way to the end index? While this might initially seem true, it's actually quite convenient to stop at end index minus one. For example, if you ever want to make a substring that extends to the end of a string, you can simply go all the way to thestring.length(). In addition, with end index minus one marking the end, the length of the substring is easily calculated as end index minus begin index. In Strings and Drawing Text, we saw how strings can be joined together (referred to as "concatenation") using the "+" operator. Let's review with a example that uses concatenation to get user input from a keyboard. Processing has two additional functions that make joining strings (or the reverse, splitting them up) easy. In sketches that involve parsing data from a file or the web, we will often be presented that data in the form of an array of strings or as one long string. Depending on what we want to accomplish, it's useful to know how to switch between these two modes of storage. This is where these two new functions, split() and join(), will come in handy. Let's take a look at the split() function. split() separates a longer string into an array of strings, based on a split character known as the delimiter. It takes two arguments, the string to be split and the delimiter. (The delimiter can be a single character or a string. Note that in the code below the period is not set as a delimiter and therefore will be included in the last string in the array: "dog." If you want to use more than one delimiter to split up a text, you must use the Processing function splitTokens(). splitTokens() works identically to split() with one exception: any character that appears in the String qualifies as a delimiter. In the code below, the period is set as a delimiter and therefore will not be included in the last spot in the array: "dog" If we are splitting numbers in a String the resulting array can be converted into an integer array with Processing's int() function. Numbers in a string are not numbers and cannot be used in mathematical operations unless we convert them first. The reverse of split() is join(). join() takes an array of Strings and joins them together into one long string. The join() function also takes two arguments, the array to be joined and a separator. The separator can either be a single character or a String of characters. Consider the following array: Using the + operator along with a for loop, we can join an array of strings together as follows: The join() function, however, allows us to bypass this process achieving the same result in only one line of code. Data can come from many different places: web sites, news feeds, databases, etc. To start, we'll demonstrate how to work with the simplest means of data retrieval data: reading from a text file.Text files can be used as a very simple database (we could store settings for a program, a list of high scores, numbers for a graph, etc.) or to simulate a more complex data source. In order to create a text file, you can use any simple text editor. Windows Notepad or Mac OSX TextEdit will do, just make sure you format the file as "plain text." It is also advisable to name the text files with the ".txt" extension, just to avoid any confusion. And just as with image files, these text files should be placed in the sketch's "data" directory in order for them to be recognized by the Processing sketch. Once the text file is in place, Processing's loadStrings() function is used to read the content of the file into an String array. The individual lines of text in the file each become an individual element in the array. Text from a file can be used to generate a simple visualization. Take the following data file. Here, we can load the numbers separated by commas and split them into an array of ints used to set color and height of rectangles. Text can also be written back to a data file with saveStrings(). saveStrings() writes an array of strings to a file, one line per string. There are cases, however, where you don't want to write a text file all at once. Rather, you want to continuously append to a file over time. This can be achieved with the PrintWriter class. Take the following example which writes saves mouseX and mouseY to a text file for each cycle through draw(), quitting when you press a key. You may have noticed that the graphing example above loads a text file with numbers separated by commas. Processing includes a Table class which will load a comma-separated (CSV) or tab-separated (TSV) file and automatically parse the data into columns and rows for you. This is a great deal more convenient than struggling to manually parse large data files with split(). It works as follows. Let's say you have a data file that looks like: Instead of saying: We can now say:
+
+ Now we've missed an important detail. Take a look at the data.csv text file above. Notice how the first line of text is not the data itself, but rather a "header row." This row includes labels that describe the data included in each subsequent row. The good news is that Processing can automatically interpret and store the headers for you, if you pass in the option "header" when loading the table. (In addition to "header" there are other options you can specify. For example if your file is called data.txt but is comma separated data you can pass in the option "csv". If it also has a header row, then you can specifiy both options like so: "header,csv"). A full list of options can be found on the loadTable() documentation page. Now that the table is loaded, we can look at how we grab individual pieces of data or iterate over the entire table. Let's look at the data visualized as a grid. In the above grid we can see that the data is organized in terms of rows and columns. One way to access the data would be to therefore request a value by its numeric row and column location (with zero being the first row or first column). This is similar to accessing a pixel color at a given (x, y) location though in this case the y position (i.e. row) comes first. The following code requests a piece of data at a given (row, column) location. While the numeric index is sometimes useful, it's generally going to be more convenient to access each piece of data by the column name. For example, we could pull out a specific row from the Table. In addition to being read, Table objects can be altered or created on the fly while a sketch is running. Cell values can be adjusted, rows can be removed, and new rows can be added. For example, to set new values in a cell there are functions setInt(), setFloat(), and setString().
+
+ To add a new row to a Table, simply call the method addRow() and set the values of each column. To delete a row to a Table, simply call the method removeRow() and pass in the numeric index of the row you would like removed. The following code for example, removes the first row whenever the size of the table is greater than ten rows. For an example that creates objects from and saves objects to a Table, take a look at LoadSaveTable under Topics --> Advanced Data. For grabbing data from the web, an XML (Extensible Markup Language) feed is an excellent option (if available). Unlike HTML (which is designed to make content vieweable by a human's eyes) XML is designed to make content viewable by a computer and facilitate the sharing of data across different systems. XML organizes information in a tree structure. Let's imagine a list of students. Each student has an id number, name, address, e-mail, and telephone number. Each student's address has a city, state, and zip code. An XML tree for this dataset might look like the following: Note the similarities to object-oriented programming. We could think of the XML tree in the following terms. The XML document represents an array of student objects. Each student object has multiple pieces of information, an id, a name, a phone number, an e-mail address, and a mailing address. The mailing address is also an object that also has multiple pieces of data, such as street, city, state, and zip. Let's look at Yahoo's XML feed for weather data. Here is the raw XML source (Note I have edited it for simplification purposes). And here is the data mapped in the tree structure. You may be wondering what the top level "RSS" is all about. Yahoo's XML weather data is provided in RSS format. RSS stands for "Really Simple Syndication" and is a standardized XML format for syndicating web content (such as news articles, etc.) Now that we have a handle on the tree structure, we should look at the specifics inside that structure. With the exception of the first line (which simply indicates that this page is XML formatted), this XML document contains a nested list of elements, each with a start tag, i.e. <channel> and an end tag, i.e. </channel>. Some of these elements have content between the tags: and some have attributes (formatted by attribute name equals attribute value in quotes): Knowing this format, we could certainly be clever with our use of split(), indexOf(), and substring() to find the pieces we want in the raw XML. The point here, however, is that because XML is a standard format, we don't have to do this. Rather, we can use an XML parser. In Processing, the XML parser is called just that: XML. Here, instead of loadStrings() or loadTable(), we're now calling loadXML() and passing in the address (URL or local file) of our XML document. An XML object represents one element of an XML tree. When a document is first loaded, that XML object is always the root element. Referring back to XML tree diagram, we see that we can find the current temperature via the following path: We could translate the above into code as follows: This is a bit long-winded, however, and so can be compressed down into one (or three as below) lines of code. It should also be noted that we're accessing the child nodes by their name (i.e. "channel", "item", etc.), but they can also be accessed numerically via an index (starting at zero, same as an array). This is convenient when looping over a list of children. In LoadSaveTable, we used a series of comma separated values in a text file to store information related to Bubble objects. An XML document can also be used in the same manner. Consider the following XML document: In the above XML, the root element is "bubbles" which has four children. Each child "bubble" has 3 children, "position", "diameter", and "label." The "position" element has two attributes, "x" and "y." To access the list of all XML nodes "bubble" we can use the getChildren() method, passing in the name "bubble" Once we have the array of XML objects, we can iterate over them, accessing the individual pieces of data for each "bubble". Notice how the syntax for getting XML attributes (in this case, "x" and "y" of the position element is slightly different than pulling content directly from an element (in this case, "diameter" and "label"). XML elements can be added and removed from the XML tree with the addChild() and removeChild() methods. For the full example that creates objects from and saves objects to an XML document, take a look at LoadSaveXML under Topics --> Advanced Data. You are likely familiar with the idea of writing a program that follows a specific sequence of steps -- setup() first then draw() over and over and over again! A Thread is also a series of steps with a beginning, a middle, and an end. A Processing sketch is a single thread, often referred to as the "Animation" thread. Other threads sequences, however, can run independently of the main Processing sketch. In fact, you can launch any number of threads at one time and they will all run concurrently. Processing does this all the time, whenever you write an event callback, such as serialEvent(), or captureEvent(), etc. these functions are triggered by a different thread running behind the scenes, and they alert Processing whenever they have something to report. This is useful whenever you need to perform a task that takes too long and would slow down the main animation's frame rate, such as grabbing data from the network (XML, database, etc.) If a separate thread gets stuck or has an error, the entire program won't grind to a halt, since the error only stops that individual thread. To create independent, asynchronous threads, you can use the thread() function built into Processing. The thread() function receives a String as an argument. The String should match the name of the function you want to run as a thread. This is especially useful in sketches that grab data for the web. Rather than have the animation freeze while the sketch is waiting to retrieve data, the sketch can continue to loop through draw() updating the data when the thread is completed. In these cases, a boolean variable can be useful to track the status of the thread. The function that loads the data can then set loading equal to true at the start and false at the end. In draw(), you can choose to display something to indicate the thread is running (when loading equals true). Two examples that follow this methodology can be found under Topics --> Advanced Data in the Processing examples. While using the thread() function is a very simple way of getting an independent thread, it should be noted that it is somewhat limited. Being able to make a thread object is a great deal more powerful, and this can be done by extending the Java Thread class.
- This tutorial is from the book Learning Processing by Daniel Shiffman, published by Morgan Kaufmann, © 2008 Elsevier Inc. All rights reserved. If you see any errors or have comments, please let us know.
+ This tutorial is from the book Learning Processing, 2nd Edition by Daniel Shiffman, published by Morgan Kaufmann, © 2015 Elsevier Inc. All rights reserved. If you see any errors or have comments, please let us know.
- In Strings and Drawing Text, we touched on a few of the basic functions available in the Java String class, such as charAt(), toUpperCase(), equals(), and length(). These functions are documented on the Processing reference page for Strings. Nevertheless, in order to perform some more advanced data parsing techniques, we'll need to explore some additional String manipulation functions documented in the Java API.
-
- Let's take a closer look at the following two String functions: indexOf() and substring(). indexOf() locates a sequence of characters within a String. It takes one argument, a search String, and returns a numeric value that corresponds to first occurrence of the search string inside of the string being searched.
-
- Strings are just like arrays, in that the first character is index number zero and the last character is the length of the string minus one. If the search string cannot be found, indexOf() returns -1. This is a good choice because -1 is not a legitimate index value and therefore can indicate "not found." After finding a search phrase within a String, we might want to separate out part of the string, saving it in a different variable. A part of a string is known as "substring." The substring() function which takes two arguments, a start index and an end index and returns the substring in between the two indices.
- Note that the substring begins at the specified start index (the first argument) and extends to the character at end index (the second argument) minus one. I know. I know. Wouldn't it have been easier to just take the substring from the start index all the way to the end index? While this might initially seem true, it's actually quite convenient to stop at end index minus one. For example, if you ever want to make a substring that extends to the end of a string, you can simply go all the way to thestring.length(). In addition, with end index minus one marking the end, the length of the substring is easily calculated as end index minus begin index. In Strings and Drawing Text, we saw how strings can be joined together (referred to as "concatenation") using the "+" operator. Let's review with a example that uses concatenation to get user input from a keyboard. Processing has two additional functions that make joining strings (or the reverse, splitting them up) easy. In sketches that involve parsing data from a file or the web, we will often be presented that data in the form of an array of strings or as one long string. Depending on what we want to accomplish, it's useful to know how to switch between these two modes of storage. This is where these two new functions, split() and join(), will come in handy. Let's take a look at the split() function. split() separates a longer string into an array of strings, based on a split character known as the delimiter. It takes two arguments, the string to be split and the delimiter. (The delimiter can be a single character or a string. Note that in the code below the period is not set as a delimiter and therefore will be included in the last string in the array: "dog."
+ In Strings and Drawing Text, we saw how strings can be joined together (referred to as "concatenation") using the "+" operator. Let's review with a example that uses concatenation to get user input from a keyboard.
+
+ Let’s take a look at the split() function. split() separates a longer string into an array of strings, based on a split character known as the delimiter. It takes two arguments, the String object to be split and the delimiter. (The delimiter can be a single character or a string.) In the code below, the period is not set as a delimiter and therefore will be included in the last string in the array: “dog.” Note how printArray() can be used to print the contents of an array and their corresponding indices to the message console. If you want to use more than one delimiter to split up a text, you must use the Processing function splitTokens(). splitTokens() works identically to split() with one exception: any character that appears in the String qualifies as a delimiter. In the code below, the period is set as a delimiter and therefore will not be included in the last spot in the array: "dog" If we are splitting numbers in a String the resulting array can be converted into an integer array with Processing's int() function. Numbers in a string are not numbers and cannot be used in mathematical operations unless we convert them first. The reverse of split() is join(). join() takes an array of Strings and joins them together into one long string. The join() function also takes two arguments, the array to be joined and a separator. The separator can either be a single character or a String of characters. Consider the following array:
+ Consider the following array: Using the + operator along with a for loop, we can join an array of strings together as follows: The join() function, however, allows us to bypass this process achieving the same result in only one line of code. Data can come from many different places: web sites, news feeds, databases, etc. To start, we'll demonstrate how to work with the simplest means of data retrieval data: reading from a text file.Text files can be used as a very simple database (we could store settings for a program, a list of high scores, numbers for a graph, etc.) or to simulate a more complex data source. In order to create a text file, you can use any simple text editor. Windows Notepad or Mac OSX TextEdit will do, just make sure you format the file as "plain text." It is also advisable to name the text files with the ".txt" extension, just to avoid any confusion. And just as with image files, these text files should be placed in the sketch's "data" directory in order for them to be recognized by the Processing sketch. Once the text file is in place, Processing's loadStrings() function is used to read the content of the file into an String array. The individual lines of text in the file each become an individual element in the array.
+ Data can come from many different places: websites, news feeds, spreadsheets, databases, and so on. Let's say you've decided to make a map of the world's flowers. After searching online you might find a PDF version of a flower encyclopedia, or a spreadsheet of flower genera, or a JSON feed of flower data, or a REST API that provides geolocated lat/lon coordinates, or some web page someone put together with beautiful flower photos, and so on and so forth. The question inevitably arises: “I found all this data; which should I use, and how do I get it into Processing?”
+
+ If you are really lucky, you might find a Processing library that hands data to you directly with code. Maybe the answer is to just download this library and write some code like:
+ Let's take another scenario. Say you’re looking to build a visualization of Major League Baseball statistics. You can't find a Processing library to give you the data but you do see everything you’re looking for at mlb.com. If the data is online and your web browser can show it, shouldn't you be able to get the data in Processing? Passing data from one application (like a web application) to another (say, your Processing sketch) is something that comes up again and again in software engineering. A means for doing this is an API or “application programming interface”: a means by which two computer programs can talk to each other. Now that you know this, you might decide to search online for “MLB API”. Unfortunately, mlb.com does not provide its data via an API. In this case you would have to load the raw source of the website itself and manually search for the data you’re looking for. While possible, this solution is much less desirable given the considerable time required to read through the HTML source as well as program algorithms for parsing it.
+
+ Each means of getting data comes with its own set of challenges. The ease of using a Processing library is dependent on the existence of clear documentation and examples. But in just about all cases, if you can find your data in a format designed for a computer (spreadsheets, XML, JSON, etc.), you'll be able to save some time in the day for a nice walk outside.
+
+ One other note worth a mention about working with data. When developing an application that involves a data source, such as a data visualization, it’s sometimes useful to develop with “dummy” or “fake” data. You don't want to be debugging your data retrieval process at the same time as solving problems related to algorithms for drawing. In keeping with my one-step-at-a-time mantra, once the meat of the program is completed with dummy data, you can then focus solely on how to retrieve the actual data from the real source. You can always use random or hard-coded numbers into your code when you’re experimenting with a visual idea and connect the real data later.
+ Let's begin by working with the simplest means of data retrieval: reading from a text file. Text files can be used as a very simple database (you could store settings for a program, a list of high scores, numbers for a graph, etc.) or to simulate a more complex data source.
+
+ In order to create a text file, you can use any simple text editor. Windows Notepad or Mac OS X TextEdit will do; just make sure you format the file as “plain text.” It is also advisable to name the text files with the “.txt” extension, to avoid any confusion. And just as with image files, these text files should be placed in the sketch’s “data” directory in order for them to be recognized by the Processing sketch.
+ Once the text file is in place, Processing’s loadStrings() function is used to read the content of the file into a String array. The individual lines of text in the file each become an individual element in the array.
+ Text from a file can be used to generate a simple visualization. Take the following data file. Here, we can load the numbers separated by commas and split them into an array of ints used to set color and height of rectangles.
+Graphing Comma-Separated Numbers from a Text File
+ Text can also be written back to a data file with saveStrings(). saveStrings() writes an array of strings to a file, one line per string.
+ A table consists of data arranged as a set of rows and columns, also called “tabular data.” If you've ever used a spreadsheet, this is tabular data. Processing's loadTable() function takes comma-separated (csv) or tab-separated (tsv) values and automatically places the contents into a Table object storing the data in columns and rows. This is a great deal more convenient than struggling to manually parse large data files with split(). It works as follows. Let's say you have a data file that looks like:
+
+ Instead of saying:
+ Once I have the TableRow object, I can ask for data from some or all of the columns. There are cases, however, where you don't want to write a text file all at once. Rather, you want to continuously append to a file over time. This can be achieved with the PrintWriter class. Take the following example which writes saves mouseX and mouseY to a text file for each cycle through draw(), quitting when you press a key.
+ In addition to being read, Table objects can be altered or created on the fly while a sketch is running. Cell values can be adjusted, rows can be removed, and new rows can be added. For example, to set new values in a cell there are functions setInt(), setFloat(), and setString(). You may have noticed that the graphing example above loads a text file with numbers separated by commas. Processing includes a Table class which will load a comma-separated (CSV) or tab-separated (TSV) file and automatically parse the data into columns and rows for you. This is a great deal more convenient than struggling to manually parse large data files with split(). It works as follows. Let's say you have a data file that looks like: Instead of saying: We can now say:
+
+
+ Here, the distance between a given point and a circle's center is compared to that circle's radius as depicted:
+
+ In the code below, the function returns a boolean value (true or false) depending on whether the point (mx,my) is inside the circle. Notice how radius is equal to half the diameter.
+ Now we've missed an important detail. Take a look at the data.csv text file above. Notice how the first line of text is not the data itself, but rather a "header row." This row includes labels that describe the data included in each subsequent row. The good news is that Processing can automatically interpret and store the headers for you, if you pass in the option "header" when loading the table. (In addition to "header" there are other options you can specify. For example if your file is called data.txt but is comma separated data you can pass in the option "csv". If it also has a header row, then you can specifiy both options like so: "header,csv"). A full list of options can be found on the loadTable() documentation page.
+ What if your data is not in a standard format like a table, how do you deal with it then? One of the nice features about loadStrings() is that in addition to pulling text from a file, you can also grab a URL. For example:
+ Unlike with the comma-delimited data from a text file that was specially formatted for use in a Processing sketch, it’s not practical to have the resulting raw HTML stored in an array of strings (each element representing one line from the source). Converting the array into one long string can make things a bit simpler. As you saw earlier in the chapter, this can be achieved using join(). Find the end of the substring “apples:” Call it start. Find the first period after “apples:” Call it end. Make a substring of the characters between start and end. Convert the string to a number (if I want to use it as such).
+ In code, this looks like: Now that the table is loaded, we can look at how we grab individual pieces of data or iterate over the entire table. Let's look at the data visualized as a grid. In the above grid we can see that the data is organized in terms of rows and columns. One way to access the data would be to therefore request a value by its numeric row and column location (with zero being the first row or first column). This is similar to accessing a pixel color at a given (x, y) location though in this case the y position (i.e. row) comes first. The following code requests a piece of data at a given (row, column) location.
+ For grabbing data from the web, an XML (Extensible Markup Language) or JSON (JavaScript Object Notation) feed will prove to be more reliable and easier to parse. Unlike HTML (which is designed to make content viewable by a human’s eyes) XML and JSON are designed to make content viewable by a computer and facilitate the sharing of data across different systems. Most data (news, weather, and more) is available this way, and I will look at examples in #beginner_xml and #JSON. Though much less desirable, manual HTML parsing is still useful for a couple reasons. First, it never hurts to practice text manipulation techniques that reinforce key programming concepts. But more importantly, sometimes there is data you really want that is not available in an API format, and the only way to get it is with such a technique. (I should also mention that regular expressions, an incredibly powerful techinque in text pattern matching, could also be employed here. As much as I love regex, it’s unfortunately beyond the scope of this tutorial.)
+
+ An example of data only available as HTML is the Internet Movie Database. IMDb contains information about movies sorted by year, genre, ratings, etc. For each movie, you can find the cast and crew list, a plot summary, running time, a movie poster image, the list goes on. However, IMDb has no API and does not provide its data as XML or JSON. Pulling the data into Processing therefore requires a bit of detective work. Let's look at the page for the Shaun the Sheep Movie
+
+ Looking in the HTML source from the above URL, I find a giant mess of markup.
+
+ It’s up to me to pore through the raw source and find the data I am looking for. Let's say I want to know the running time of the movie and grab the movie poster image. After some digging, I find that the movie is 139 minutes long as listed in the following HTML. While the numeric index is sometimes useful, it's generally going to be more convenient to access each piece of data by the column name. For example, we could pull out a specific row from the Table. In addition to being read, Table objects can be altered or created on the fly while a sketch is running. Cell values can be adjusted, rows can be removed, and new rows can be added. For example, to set new values in a cell there are functions setInt(), setFloat(), and setString().
-
+
+ Loading text from a URL need not only be an exercise in parsing out small bits of information. It’s possible with Processing to analyze large amounts of text found on the web from news feeds, articles, and speeches, to entire books. A nice source is Project Gutenberg which makes available thousands of public domain texts. Algorithms for analyzing text merits an entire book itself, but let’s look at some basic techniques.
+
+ A text concordance is an alphabetical list of words that appear in a book or body of text along with contextual information. A sophisticated concordance might keep a list of where each word appears (like an index) as well as which words appear next to which other words. In this case, I'm going to create a simple concordance, one that simply stores a list of words and their corresponding counts, i.e., how many times they appeared in the text. Concordances can be used for text analysis applications such as spam filtering or sentiment analysis. To accomplish this task, I am going to use the Processing built-in class IntDict.
+
+ As you learned earlier, an array is an ordered list of variables. Each element of the array is numbered and be accessed by its numeric index.
+
+ However, what if instead of numbering the elements of an array you could name them? This element is named “Sue,” this one “Bob,” this one “Jane,” and so on and so forth. In programming, this kind of data structure is often referred to as an associative array, map, or dictionary. It’s a collection of (key, value) pairs. Imagine you had a dictionary of people's ages. When you look up “Sue” (the key), the definition, or value, is her age, 24.
+
+ Associative arrays can be incredibly convenient for various applications. For example, you could keep a list of student IDs (student name, id) or a list of prices (product name, price) in a dictionary. Here a dictionary is the perfect data structure to hold the concordance. Each element of the dictionary is a word paired with its count.
+
+ While there are many classes in Java for dealing with advanced data structures like maps, Processing provides you with a set of three built-in dictionary classes that are easy to use: IntDict, FloatDict, and StringDict. In all of these classes, the key is always a string while the value is variable (an integer, floating point number, or String). For the concordance, I'll use an IntDict.
+
+ Creating an IntDict is as easy as calling an empty constructor. Let's say you want a dictionary to keep track of an inventory of supplies. To add a new row to a Table, simply call the method addRow() and set the values of each column. To delete a row to a Table, simply call the method removeRow() and pass in the numeric index of the row you would like removed. The following code for example, removes the first row whenever the size of the table is greater than ten rows.
+ The concordance now becomes a rather simple program to write. All I need to do is load in a text file, chop it into words with splitTokens() and call increment() on an IntDict for every single word found in the text. The following example does precisely this with the entire text of Shakespeare’s play, A Midsummer Night's Dream, displaying a simple graph of the most used words.
+ For an example that creates objects from and saves objects to a Table, take a look at LoadSaveTable under Topics --> Advanced Data. For grabbing data from the web, an XML (Extensible Markup Language) feed is an excellent option (if available). Unlike HTML (which is designed to make content vieweable by a human's eyes) XML is designed to make content viewable by a computer and facilitate the sharing of data across different systems. XML organizes information in a tree structure. Let's imagine a list of students. Each student has an id number, name, address, e-mail, and telephone number. Each student's address has a city, state, and zip code. An XML tree for this dataset might look like the following:
+ Processing also includes three classes for lists of numbers and strings: IntList, FloatList, and StringList. In other words, if you just want a list of words (without their counts) you could use a StringList rather than an IntDict.
+
+ If your data is available via a standardized format such as XML or JSON, the process of manually searching through text for individual pieces of data is no longer required. XML is designed to facilitate the sharing of data across different systems, and you can retrieve that data using the built-in Processing XML class.
+
+ XML organizes information in a tree structure. Let’s imagine a list of students. Each student has an ID number, name, address, email, and telephone number. Each student’s address has a city, state, and zip code. An XML tree for this dataset might look like the following:
+
+ The XMl source itself (with two students listed) is: Note the similarities to object-oriented programming. We could think of the XML tree in the following terms. The XML document represents an array of student objects. Each student object has multiple pieces of information, an id, a name, a phone number, an e-mail address, and a mailing address. The mailing address is also an object that also has multiple pieces of data, such as street, city, state, and zip. Let's look at Yahoo's XML feed for weather data. Here is the raw XML source (Note I have edited it for simplification purposes).
+ Let's look at some data made available from a web service such as Yahoo Weather. Here is the raw XML source. (Note I have edited it slightly for simplification purposes.) And here is the data mapped in the tree structure. You may be wondering what the top level "RSS" is all about. Yahoo's XML weather data is provided in RSS format. RSS stands for "Really Simple Syndication" and is a standardized XML format for syndicating web content (such as news articles, etc.) Now that we have a handle on the tree structure, we should look at the specifics inside that structure. With the exception of the first line (which simply indicates that this page is XML formatted), this XML document contains a nested list of elements, each with a start tag, i.e. <channel> and an end tag, i.e. </channel>. Some of these elements have content between the tags:
+ You may be wondering what the top level “RSS” is all about. Yahoo’s XML weather data is provided in RSS format. RSS stands for “Really Simple Syndication” and is a standardized XML format for syndicating web content (such as news articles, etc.). You can read more about RSS on Wikipedia.
+ Now that you have a handle on the tree structure, let's look at the specifics inside that structure. With the exception of the first line (which simply indicates that this page is XML formatted), this XML document contains a nested list of elements, each with a start tag, that is, <channel>, and an end tag, that is, </channel>. Some of these elements have content between the tags: and some have attributes (formatted by attribute name equals attribute value in quotes): Knowing this format, we could certainly be clever with our use of split(), indexOf(), and substring() to find the pieces we want in the raw XML. The point here, however, is that because XML is a standard format, we don't have to do this. Rather, we can use an XML parser. In Processing, the XML parser is called just that: XML.
+ Since the syntax of XML is standardized, I could certainly use split(), indexof(), and substring() to find the pieces I want in the XML source. The point here, however, is that because XML is a standard format, I don't have to do this. Rather, I can use an XML parser. In Processing, XML can be parsed using the built-in Processing class XML. The root of the tree is RSS. RSS has a child named channel. Channel has a child named item. Item has a child named yweather:condition. The temperature is stored in yweather:condition as the attribute temp.
+ The children of an element are accessed via the getChild() function. Here, instead of loadStrings() or loadTable(), we're now calling loadXML() and passing in the address (URL or local file) of our XML document. An XML object represents one element of an XML tree. When a document is first loaded, that XML object is always the root element. Referring back to XML tree diagram, we see that we can find the current temperature via the following path:
+ Following steps one through five outlined above through the XML tree, I have: We could translate the above into code as follows: This is a bit long-winded, however, and so can be compressed down into one (or three as below) lines of code.
+Parsing Yahoo Weather XML
+ It should also be noted that we're accessing the child nodes by their name (i.e. "channel", "item", etc.), but they can also be accessed numerically via an index (starting at zero, same as an array). This is convenient when looping over a list of children. In LoadSaveTable, we used a series of comma separated values in a text file to store information related to Bubble objects. An XML document can also be used in the same manner. Consider the following XML document: hasChildren() — checks whether or not an element has any children getChildren() — returns an array containing all child elements getAttributeCount() — counts the specified element's number of attributes hasAttribute() — checks whether or not an element has the specified attribute
+ In this example I'm accessing the child nodes by their name (i.e., "channel," "item,", etc.), however they can also be accessed numerically via an index (starting at zero, same as an array). This is convenient when looping over a list of children, much like I did with tabular data when I iterated over rows in a table.
+
+ Earlier, we used a Table to store information related to Bubble objects. XML document can also be used in the same manner. Here is a possible solution for an XML tree of Bubble objects:
+Using Processing's XML Class
+ In the above XML, the root element is "bubbles" which has four children. Each child "bubble" has 3 children, "position", "diameter", and "label." The "position" element has two attributes, "x" and "y." To access the list of all XML nodes "bubble" we can use the getChildren() method, passing in the name "bubble"
+ Another increasingly popular data exchange format is JSON (pronounced like the name Jason), which stands for JavaScript Object Notation. Its design was based on the syntax for objects in the JavaScript programming language (and is most commonly used to pass data between web applications) but has become rather ubiquitous and language-agnostic. While you don't need to know anything about JavaScript to work in Processing, it won't hurt to get a sense of some basic JavaScript syntax while learning it.
+
+ JSON is an alternative to XML and the data can be looked at in a similarly tree-like manner. All JSON data comes in the following two ways: an object or an array. Luckily, you already know about these two concepts and only need to learn a new syntax for encoding them.
+
+ Let's take a look at a JSON object first. A JSON object is like a Processing object only with no functions. It’s simply a collection of variables with a name and a value (or "name/value pair"). For example, following is JSON data describing a person:
+ Now that I've covered the syntax of JSON, I can look at using the data in Processing. One thing that can be a bit tricky about working with JSON in Processing is that I have to treat objects and arrays differently. With XML, I simply had a single XML class with all the parsing functionality I needed. With JSON, I have two classes: JSONObject and JSONArray, and I'll have to be conscientious about picking which class I am using during the parsing process.
+
+ The first step is simply loading the data with either loadJSONObject() or loadJSONArray(). But which one? I have to look and see what is at the root of the JSON file, an object or array. This can be a little tricky. Let's look at these two JSON examples:
+
+ Sample 1: Once we have the array of XML objects, we can iterate over them, accessing the individual pieces of data for each "bubble". Notice how the syntax for getting XML attributes (in this case, "x" and "y" of the position element is slightly different than pulling content directly from an element (in this case, "diameter" and "label").
+Using Processing's JSON Classes
+ XML elements can be added and removed from the XML tree with the addChild() and removeChild() methods. For the full example that creates objects from and saves objects to an XML document, take a look at LoadSaveXML under Topics --> Advanced Data. You are likely familiar with the idea of writing a program that follows a specific sequence of steps -- setup() first then draw() over and over and over again! A Thread is also a series of steps with a beginning, a middle, and an end. A Processing sketch is a single thread, often referred to as the "Animation" thread. Other threads sequences, however, can run independently of the main Processing sketch. In fact, you can launch any number of threads at one time and they will all run concurrently. Processing does this all the time, whenever you write an event callback, such as serialEvent(), or captureEvent(), etc. these functions are triggered by a different thread running behind the scenes, and they alert Processing whenever they have something to report. This is useful whenever you need to perform a task that takes too long and would slow down the main animation's frame rate, such as grabbing data from the network (XML, database, etc.) If a separate thread gets stuck or has an error, the entire program won't grind to a halt, since the error only stops that individual thread. To create independent, asynchronous threads, you can use the thread() function built into Processing.
+ As you have seen, the various loading functions — loadStrings(), loadTable(), loadXML(), and loadJSONObject() — can be used for retrieving data from URLs. Nonetheless, unless your sketch only needs to load the data once during setup(), you may have a problem. For example, consider a sketch that grabs the price of AAPL stock from an XML feed every five minutes. Each time loadXML() is called, the sketch will pause while waiting to receive the data. Any animation will stutter. This is because these loading functions are “blocking.” In other words, the sketch will sit and wait at that line of code until loadXML() completes its task. With a local data file, this is extremely fast. Nonetheless, a request for a URL (known as an “HTTP request”) in Processing is synchronous, meaning your sketch waits for a response from the server before continuing. Who knows how will that take? No one; you are at the mercy of the server!
+
+ The answer to this problem lies in the concept of threads. By now you are quite familiar with the idea of writing a program that follows a specific sequence of steps — setup() first then draw() over and over and over again! A thread is also a series of steps with a beginning, a middle, and an end. A Processing sketch is a single thread, often referred to as the animation thread. Other threads’ sequences, however, can run independently of the main animation loop. In fact, you can launch any number of threads at one time, and they will all run concurrently.
+
+ Processing does this quite often, such as with library functions like captureEvent() and movieEvent(). These functions are triggered by a different thread running behind the scenes, and they alert Processing whenever they have something to report. This is useful when you need to perform a task that takes too long and would slow down the main animation's frame rate, such as grabbing data from the network. Here, you want to handle the request asynchronously in a different thread. If that thread gets stuck or has an error, the entire program won't grind to a halt, since the error only stops that individual thread and not the main animation loop.
+
+ Writing your own thread can be a complex endeavor that involves extending the Java Thread class. However, the thread() method is a quick and dirty way to implement a simple thread in Processing. By passing in a string that matches the name of a function declared elsewhere in the sketch, Processing will execute that function in a separate thread. Let's take a look at a skeleton of how this works.
+ Let's look at a more practical example. For an example of data that changes often, I'll use time.jsontest.com which gives you the current time (in milliseconds). While I could retrieve this from the system clock, this works well for demonstrating continuously requesting data that changes over time. Not knowing about threads, my first instinct might be to say: The thread() function receives a String as an argument. The String should match the name of the function you want to run as a thread. This is especially useful in sketches that grab data for the web. Rather than have the animation freeze while the sketch is waiting to retrieve data, the sketch can continue to loop through draw() updating the data when the thread is completed. In these cases, a boolean variable can be useful to track the status of the thread. The function that loads the data can then set loading equal to true at the start and false at the end.
+ In the above example, I likely don't want to request the data sixty times per second (the default frame rate). Instead I might make use of the Timer class, and ask for the data once per second. Here is a full example that does exactly that with added animation to show that draw() never stutters.
+ In draw(), you can choose to display something to indicate the thread is running (when loading equals true).
+ It’s a bit silly for me to call this section “APIs” given that most of this chapter is about data from APIs. Still, it’s worth taking a moment to pause and reflect. What makes something an API versus just some data you found, and what are some pitfalls you might run into when using an API?
+
+ As I've stated, an API (Application Programming Interface) is an interface through which one application can access the services of another. These can come in many forms. Openweathermap.org, as you saw earlier, is an API that offers its data in JSON, XML, and HTML formats. The key element that makes this service an API is exactly that offer; openweathermap.org's sole purpose in life is to offer you its data. And not just offer it, but allow you to query it for specific data in a specific format. Let's look at a short list of sample queries.
+
+ One thing to note about openweathermap.org is that it does not require that you tell the API any information about yourself. You simply send a request to a URL and get the data back. Other APIs, however, require you to sign up and obtain an access token. The New York Times API is one such example. Before you can make a request from Processing, you'll need to visit The New York Times Developer site and request an API key. Once you have that key, you can store it in your code as a string.
+NYTimes API Query
+ Two examples that follow this methodology can be found under Topics --> Advanced Data in the Processing examples. While using the thread() function is a very simple way of getting an independent thread, it should be noted that it is somewhat limited. Being able to make a thread object is a great deal more powerful, and this can be done by extending the Java Thread class. With any luck, the main Processing window will now be visible. Everyone's setup is different, so if the program didn't start, or you're otherwise stuck, visit the troubleshooting page for possible solutions. With any luck, the main Processing window will now be visible. Everyone's setup is different, so if the program didn't start, or you're otherwise stuck, visit the troubleshooting page for possible solutions.
diff --git a/content/static/tutorials/imgs/video.png b/content/static/tutorials/imgs/video.png
new file mode 100644
index 000000000..4a408066c
Binary files /dev/null and b/content/static/tutorials/imgs/video.png differ
diff --git a/content/static/tutorials/index.html b/content/static/tutorials/index.html
index 1001c0010..7434e5bbb 100644
--- a/content/static/tutorials/index.html
+++ b/content/static/tutorials/index.html
@@ -7,8 +7,8 @@ Short video lessons introduce coding exercises that lead to designing an interactive drawing program. How do you analyze a problem and break it down into steps that the computer can do? How to display live and recorded video Level: Advanced How do you analyze a problem and break it down into steps that the computer can do? Level: Advanced
- There are four render modes: the default renderer, P2D, P3D, and PDF. To use a non-default renderer, you can specify via the size() function.
+ There are five render modes: the default renderer, P2D, P3D, PDF, and SVG. To use a non-default renderer, you can specify via the size() function.
- In order to draw something at a point in three dimensions the coordinates are specified in the order you would expect: x, y, z. Cartesian 3D systems are often described as "left-handed" or "right-handed." If you point your index finger in the positive y direction (up) and your thumb in the positive x direction (to the right), the rest of your fingers will point towards the positive z direction. It's left-handed if you use your left hand and do the same. In Processing, the system is left-handed, as follows:
+ In order to draw something at a point in three dimensions the coordinates are specified in the order you would expect: x, y, z. Cartesian 3D systems are often described as "left-handed" or "right-handed." If you point your index finger in the positive y direction (down) and your thumb in the positive x direction (to the right), the rest of your fingers will point towards the positive z direction. It's left-handed if you use your left hand and do the same. In Processing, the system is left-handed, as follows:
Note how the call to the lights() function is included in draw(). Just as with matrix transformations, the 3D scene is reset each time through draw() any therefore any lighting must be included in order to remain persistent. Note how the call to the lights() function is included in draw(). Just as with matrix transformations, the 3D scene is reset each time through draw() and therefore any lighting must be included in order to remain persistent. In order to set custom lighting for your scene there are four different kinds of lights. Note that the goal of this document is not to provide a programming guide to GLSL, but to describe in detail the new shader API in Processing so that users already familiar with GLSL can write their own custom shaders and then use them in Processing. There are several resources, such as online tutorials and forums, books, and coding sandboxes, that can be recommended for learning GLSL programming. Furthermore, the GLSL experience gained using a different programming interface, platform or toolkit (openFrameworks, Cinder, webGL, iOS, Android, etc.) can be easily translated over to Processing.
+ Note that the goal of this document is not to provide a programming guide to GLSL, but to describe in detail the new shader API in Processing so that users already familiar with GLSL can write their own custom shaders and then use them in Processing. There are several resources, such as online tutorials and forums, books, and web coding sandboxes (for example Shader Toy, GLSL Sandbox, and Vertex Shader Art), that can be recommended for learning GLSL programming. Furthermore, the GLSL experience gained using a different programming interface, platform or toolkit (openFrameworks, Cinder, webGL, iOS, Android, etc.) can be easily translated over to Processing.
Let's start with a simple 3D sketch as the model to understand the relationship between the Processing functions and variables and the underlying pipeline running on the GPU. This sketch draws a quad with lights and some geometric transformations applied to it:
@@ -43,14 +43,14 @@
-The vertex shader doesn't know how the vertices are connected to each other forming a shape since it receives each vertex independently of the others. Therefore, the immediate output of the vertex stage is just the list of vertices projected onto the screen plane. In Processing we set how the vertices of a shape are connected with each other by passing an argument to beginShape(). This argument, which in the case of this example is QUADS, determines how the next stage in the pipeline, called primitive assembly, builds geometric primitives out of the individual vertices that come out of the vertex shader.
+The vertex shader doesn't know how the vertices are connected to each other forming a shape since it receives each vertex independently of the others. Therefore, the immediate output of the vertex stage is just the list of vertices projected onto the screen plane. In Processing we set how the vertices of a shape are connected with each other by passing an argument to beginShape(). This argument, which in the case of this example is QUADS, determines how the next stage in the pipeline, called primitive assembly, builds geometric primitives out of the individual vertices that come out of the vertex shader.
@@ -110,7 +110,7 @@
-The fragment shader can perform additional operations on each fragment, and in fact these could be potentially very complex. It is possible to implement a ray-tracer entirely in the fragment shader, and we will touch on this topic briefly with some more advanced examples. One important limitation of the fragment shader to keep in mind is that it cannot access fragments other than the one is currently processing (same as the vertex shader cannot access a vertex other than the one is currently operating on).
+The fragment shader can perform additional operations on each fragment, and in fact these could be potentially very complex. It is possible to implement a ray-tracer entirely in the fragment shader, and we will touch on this topic briefly with some more advanced examples. One important limitation of the fragment shader to keep in mind is that it cannot access fragments other than the one is currently processing (same as the vertex shader cannot access a vertex other than the one is currently operating on). The Book of Shaders by Patricio Gonzalez Vivo and Jen Lowe gives an excellent illustrated introduction to GLSL shaders, and it is a terrific resource for programming of fragment shaders in general.
-From all the stages described in our simplified pipeline, only the vertex and fragment shaders can be modified to run our own custom code. The other stages are all hard-coded in the GPU. With this picture in mind, we can move forward and start working through the actual shader API in Processing.
+From all the stages described in our simplified pipeline, only the vertex and fragment shaders can be modified to run our own custom code. The other stages are all hard-coded in the GPU. With this picture in mind, we can move forward and start working through the actual shader API in Processing.
-The ifdef section in the fragment shader is required to make the shader compatible with OpenGL ES and WebGL. It sets the precision of the float and integer numbers to medium, which should be fine for most devices. These precision statements are optional on the desktop. There is also a #define line declaring the PROCESSING_LIGHT_SHADER symbol. This define is used by Processing to determine the type of shader, and whether or not it is valid to render the geometry in the sketch. This topic will be explain in detail in the next section.
+The ifdef section in the fragment shader is required to make the shader compatible with OpenGL ES and WebGL. It sets the precision of the float and integer numbers to medium, which should be fine for most devices. These precision statements are optional on the desktop.
@@ -248,7 +246,7 @@
-From the code and pseudo-code examples presented in the previous sections, it can be appreciated that different shaders have different uniform and attribute variables. Clearly, a shader that does not compute lighting does not need uniforms holding the light source's position and color, for example. If we work with a low-level toolkit in C or C++ with direct access to the OpenGL API, we are free to name the uniforms and attributes of a shader in any way we like, since we have absolute control on the way the geometry is stored in our application, and how and when it is passed over to the GPU pipeline using the OpenGL functions. This is different when working in Processing, since the shaders are handled automatically by the renderers and should be able to handle the geometry that is described with the drawing API of Processing. This doesn't imply that custom shaders must render things in the same way as Processing does by default, quite in the contrary, the use of custom shaders opens up the possibility of greatly altering the rendering pipeline in Processing. However, custom shaders meant to be used in conjunction with the standard drawing API have to follow certain naming conventions, and are bound by some limitations.
+From the code and pseudo-code examples presented in the previous sections, it can be appreciated that different shaders have different uniform and attribute variables. For example, a shader that does not compute lighting does not need uniforms holding the light source's position and color, for example. If we work with a low-level toolkit in C or C++ with direct access to the OpenGL API, we are free to name the uniforms and attributes of a shader in any way we like, since we have absolute control on the way the geometry is stored in our application, and how and when it is passed over to the GPU pipeline using the OpenGL functions. This is different when working in Processing, since the shaders are handled automatically by the renderers and should be able to handle the geometry that is described with the drawing API of Processing. This doesn't imply that custom shaders must render things in the same way as Processing does by default, quite in the contrary, the use of custom shaders opens up the possibility of greatly altering the rendering pipeline in Processing. However, custom shaders meant to be used in conjunction with the standard drawing API have to follow certain naming conventions, and are bound by some limitations.
@@ -260,20 +258,20 @@
-When setting a shader with the shader() function, if no type argument is specified then the shader will be assumed to be a triangle shader:
+When setting a shader with the shader() function, we can specify the shader type explicitly:
-This code will result in Processing using pointShader to render stroke points, lineShader to render lines, and polyShader to render triangles (anything else).
+This code will result in Processing using pointShader to render stroke points, lineShader to render lines, and polyShader to render the appropriate kind of geometry.
@@ -301,7 +299,7 @@
-As mentioned earlier, a shader for rendering lit geometry requires additional attributes and uniform variables to be sent from Processing that are not needed by a shader that only renders flat-colored geometry without lights or textures. Similarly, a shader for rendering textured polygons needs its own uniforms and attributes (texture sampler and texture coordinates) that would not be required otherwise. Although it could have been possible to have a generic shader in Processing that takes care of all different rendering scenarios, this would be very inefficient because of all the branching that should take place inside the shaders to choose the appropriate rendering path. In general, GPUs are not very efficient at handling branches in their shaders, particularly those available on mobile devices.
+As mentioned earlier, a shader for rendering lit geometry requires additional attributes and uniform variables to be sent from Processing that are not needed by a shader that only renders flat-colored geometry without lights or textures. Similarly, a shader for rendering textured polygons needs its own uniforms and attributes (texture sampler and texture coordinates) that would not be required otherwise. Depending on what uniforms and attributes are defined in the shader, it will be capable of rendering the current scene correctly or not.
In consequence, the triangle shaders are further discriminated in 4 types:
-Together with the POINT and LINE shaders mentioned earlier, we end up having 6 different types of shaders in Processing.
-
-Processing needs to use the right type of shader when drawing a piece of geometry, and by default it picks the correct shader by checking whether the geometry about to be rendered has lights or textures associated to it and then enabling the appropriate shader. When we set our own custom shader, we need to make sure that it belongs to the correct type to handle the subsequent drawing calls. For example, if simpleShader below is of type COLOR, then in the following code the rectangle will be renderer using simpleShader:
- However, if we do:
-then Processing will simply ignore simpleShader and will render the lit rectangle with its own default LIGHT shader.
-
-The type of a shader can be specified inside the GLSL code, either in the vertex shader or the fragment shader (or both), by using a #define line, which are the following:
- The shader type can be set explicitly in the source code of the shader using pre-processor #defines, which override Processing's autodetection. The supported #defines are the following:
-These defines are in fact hints for the renderer, and could be absent from the shader code altogether. This is convenient for more advanced applications where the data used by the shader is not necessarily determined by the texture/lighting state of the scene, but we will leave the discussion of this functionality for a future tutorial.
- In the next sections we will describe each type of shader in detail.
@@ -379,11 +344,11 @@
to load the shader files. Then, right after background(), add
@@ -469,7 +432,7 @@
-The type of shader is indicated here with the define in the vertex shader, but it could also be in the fragment shader. In this example, there is only one uniform variable, transform, which is a 4x4 matrix holding the product of the projection and the modelview matrices. The multiplication of a vertex in world coordinates by the transform matrix gives the clip coordinates. The vertex and color attributes hold the position and color of the input vertex, respectively. The input color is copied without any modification to the vertColor varying, which passes the value down to the fragment shader. The fragment shader is nothing more than a pass-through shader since the color is sent to the output without any further modifications. The uniform transform and the attributes vertex and color are automatically set by Processing.
+The type of shader is indicated here with the define in the vertex shader, but it could also be in the fragment shader. In this example, there is only one uniform variable, transform, which is a 4x4 matrix holding the product of the projection and the modelview matrices. The multiplication of a position in world coordinates by the transform matrix gives the clip coordinates. The position and color attributes hold the position and color of the input vertex, respectively. The input color is copied without any modification to the vertColor varying, which passes the value down to the fragment shader. The fragment shader is nothing more than a pass-through shader since the color is sent to the output without any further modifications. The uniform transform and the attributes position and color are automatically set by Processing.
@@ -499,20 +462,20 @@
-In the vertex shader, the ecVertex variable is the position of the input vertex expressed in eye-coordinates, since it is obtained by multiplying vertex by the modelview matrix. Similarly, multiplying the input normal vector by the normalMatrix yields its coordinates in the eye-system. Once all the vectors are expressed in the same coordinate system, they can be used to calculate the intensity of the incident light at the current vector. From the formula used in the shader, the intensity is directly proportional to the angle between the normal and the vector between the vertex and the light source.
+In the vertex shader, the ecPosition variable is the position of the input vertex expressed in eye-coordinates, since it is obtained by multiplying vertex by the modelview matrix. Similarly, multiplying the input normal vector by the normalMatrix yields its coordinates in the eye-system. Once all the vectors are expressed in the same coordinate system, they can be used to calculate the intensity of the incident light at the current vector. From the formula used in the shader, the intensity is directly proportional to the angle between the normal and the vector between the vertex and the light source.
@@ -701,7 +660,7 @@
-The values in this uniforms completely specify any lighting configuration set in the sketch using the ambientLight(), pointLight(), directionalLight() and spotLight() functions in Processing. To see how all these uniforms are used in the default light shader, which covers all the possible lighting combinations, take a look at its source code from the Processing core. However, a valid light shader doesn't need to declare all of these uniforms, for example in the previous example we only needed the lightPosition uniform.
+The values in this uniforms completely specify any lighting configuration set in the sketch using the ambientLight(), pointLight(), directionalLight() and spotLight() functions in Processing. To see how all these uniforms are used in the default light shader, which covers all the possible lighting combinations, take a look at its source code from the Processing core. However, a valid light shader doesn't need to declare all of these uniforms, for example in the previous example we only needed the lightPosition uniform.
@@ -714,8 +673,6 @@ A few of the most common vertex attributes and shader uniforms have an alternative short-hand name, listed below:
@@ -942,8 +908,6 @@
-You will notice that this time the loadShader() function only receives the filename of the fragment shader. Because the GLSL code contains the #define PROCESSING_TEXTURE_SHADER line, Processing will know that we are providing the fragment stage of a texture shader. How does it complete the entire shader program? The answer is that it uses the default vertex stage for texture shaders. As a consequence of this, and since the varying variables are first declared in the vertex stage, the fragment shader has to follow the varying names adopted in the default shader. In this case, the varying variables for the fragment color and texture coordinate must be named vertColor and vertTexCoord, respectively.
+You will notice that this time the loadShader() function only receives the filename of the fragment shader. How does Processing complete the entire shader program? The answer is that it uses the default vertex stage for texture shaders. As a consequence of this, and since the varying variables are first declared in the vertex stage, the fragment shader has to follow the varying names adopted in the default shader. In this case, the varying variables for the fragment color and texture coordinate must be named vertColor and vertTexCoord, respectively.
@@ -1014,8 +978,6 @@
-Another limitation of the default point rendering in Processing that we can overcome with a custom point shader is the use of many vertices to represent a single point. We saw that in the case of square points, actually 5 vertices are sent to the GPU per point. In the case of rounds points, this number could be significantly higher since the point circles are approximated with regular polygons of n sides. The number n grows as the point is larger on the screen.
+Another limitation of the default point rendering in Processing that we can overcome with a custom point shader is the use of many vertices to represent a single point. We saw that in the case of square points, actually 5 vertices are sent to the GPU per point. In the case of rounds points, this number could be significantly higher since the point circles are approximated with regular polygons of n sides. The number n grows as the point is larger on the screen.
@@ -1516,11 +1472,11 @@ The key calculation here is the dot product between the normal vector and the vector from the center of the stroke quad and the current fragment position, dot(normalize(normal), v), which will be exactly 0 along the spine of the quad, and so, giving alpha equal to 1.
+ The key calculation here is the dot product between the normal vector and the vector from the center of the stroke quad and the current fragment position, dot(normalize(normal), v), which will be exactly 0 along the spine of the quad, and so, giving alpha equal to 1.
The DISABLE_DEPTH_MASK hint in the sketch code is a simple (but not perfect) trick to avoid obvious visual artifacts due to the use of semi-transparent geometry together with alpha blending.
-Before we get into vectors themselves, let's look at a beginner Processing example that demonstrates why it is in the first place we should care. If you've read any of the introductory Processing textbooks or taken a class on programming with Processing (and hopefully you've done one of these things to help prepare you for this book), you probably, at one point or another, learned to how to write a simple bouncing ball sketch.
+Before we get into vectors themselves, let's look at a beginner Processing example that demonstrates why it is in the first place we should care. If you've read any of the introductory Processing textbooks or taken a class on programming with Processing (and hopefully you've done one of these things to help prepare you for this book), you probably, at one point or another, learned how to write a simple bouncing ball sketch.
- This representation of sound, as a discrete “frame” of frequencies and amplitudes independent of time, is more akin to the way in which we perceive our sonic environment than the raw pressure wave of the time domain. Jean-Baptiste-Joseph Fourier, a nineteenth-century French mathematician, developed the equations that allow us to translate a sound pressure wave (no matter how complex) into its constituent frequencies and amplitudes. This Fourier transform is an important tool in working with sound in the computer.
-
Our auditory system takes these streams of frequency and amplitude information from our two ears and uses them to construct an auditory “scene,” akin to the visual scene derived from the light reaching our retinas.6 Our brain analyzes the acoustic information based on a number of parameters such as onset time, stereo correlation, harmonic ratio, and complexity to parse out a number of acoustic sources that are then placed in a three-dimensional image representing what we hear. Many of the parameters that psychoacousticians believe we use to comprehend our sonic environment are similar to the grouping principles defined in Gestalt psychology.
- Classic computer music “languages,” most of which are derived from Max Mathews’ MUSIC program, are still in wide use today. Some of these, such as CSound (developed by Barry Vercoe at MIT) have wide followings and are taught in computer music studios as standard tools for electroacoustic composition. The majority of these MUSIC-N programs use text files for input, though they are increasingly available with graphical editors for many tasks. Typically, two text files are used; the first contains a description of the sound to be generated using a specification language that defines one or more “instruments” made by combining simple unit generators. A second file contains the “score,” a list of instructions specifying which instrument in the first file plays what event, when, for how long, and with what variable parameters. Most of these programs go beyond simple task-based synthesis and audio processing to facilitate algorithmic composition, often by building on top of a standard programming language; F. Richard Moore’s CLM package, for example, is built on top of Common LISP. Some of these languages have been retrofitted in recent years to work in real time (as opposed to rendering a sound file to disk); Real-Time Cmix, for example, contains a C-style parser as well as support for connectivity from clients over network sockets and MIDI.
+ Classic computer music “languages,” most of which are derived from Max Mathews’ MUSIC program, are still in wide use today. Some of these, such as CSound (developed by Barry Vercoe at MIT) have wide followings and are taught in computer music studios as standard tools for electroacoustic composition. The majority of these MUSIC-N programs use text files for input, though they are increasingly available with graphical editors for many tasks. Typically, two text files are used; the first contains a description of the sound to be generated using a specification language that defines one or more “instruments” made by combining simple unit generators. A second file contains the “score,” a list of instructions specifying which instrument in the first file plays what event, when, for how long, and with what variable parameters. Most of these programs go beyond simple task-based synthesis and audio processing to facilitate algorithmic composition, often by building on top of a standard programming language; Bill Schottstaedt ’s CLM package, for example, is built on top of Common LISP. Some of these languages have been retrofitted in recent years to work in real time (as opposed to rendering a sound file to disk); Real-Time Cmix, for example, contains a C-style parser as well as support for connectivity from clients over network sockets and MIDI.
@@ -237,140 +233,140 @@
- This page only covers some of the available methods of the String class. The full documentation can be found on java's String page.
+ This page only covers some of the available methods of the String class. The full documentation can be found on java's String page.
Translation and rotation can also be applied to text. For example, to rotate text around its center, translate to an origin point and use textAlign(CENTER) before displaying the text.
-What, about the push and pop part of the names? These come from a computer
+What about the push and pop part of the names? These come from a computer
concept known as a stack, which works like a spring-loaded tray
dispenser in a cafeteria.
When someone returns a tray to the stack, its weight pushes the platform down.
diff --git a/content/static/tutorials/tutorials.xml b/content/static/tutorials/tutorials.xml
index a9cad915b..9db78bd35 100644
--- a/content/static/tutorials/tutorials.xml
+++ b/content/static/tutorials/tutorials.xml
@@ -119,12 +119,14 @@
- To work with fonts different than the default, more functions are needed to prepare a font to be used with Processing. The createFont() function is used to convert a TrueType font (.ttf) or OpenType font (.otf) so that is can display through text(). The textFont() function is used to define the current font to display. Any compatible font installed on the computer running Processing or stored in the sketch’s data folder may be used. The following short program is used to print the list of the available installed fonts to the console:
+ To work with fonts different than the default, more functions are needed to prepare a font to be used with Processing. The createFont() function is used to convert a TrueType font (.ttf) or OpenType font (.otf) so that it can display through text(). The textFont() function is used to define the current font to display. Any compatible font installed on the computer running Processing or stored in the sketch’s data folder may be used. The following short program is used to print the list of the available installed fonts to the console:
+ This tutorial is from the book Learning Processing, 2nd Edition by Daniel Shiffman, published by Morgan Kaufmann, © 2015 Elsevier Inc. All rights reserved. If you see any errors or have comments, please let us know.
+
+Now that you’ve explored static images in Processing, you are ready to move on to moving images, specifically from a live camera (and later, from a recorded movie). I’ll begin by walking through the basic steps of importing the video library and using the Capture class to display live video.
+
+Displaying recorded video follows much of the same structure as live video. Processing’s video library accepts most video file formats; for specifics, visit the Movie reference.
+With small video cameras attached to more and more personal computers, developing software that manipulates an image in real-time is becoming increasingly popular. These types of applications are sometimes referred to as “mirrors,” as they provide a digital reflection of a viewer’s image. Processing’s extensive library of functions for graphics and its ability to capture from a camera in real-time make it an excellent environment for prototyping and experimenting with software mirrors.
+ Earlier releases have been removed because we can only support the current versions of the software. To update old code, read the changes page. Per-release changes can be found in revisions.txt. If you have problems with the current release, please file a bug so that we can fix it. Older releases can also be built from the source. Read More about the releases and their numbering. To use Android Mode, Processing 3.0 beta or later is required. The revisions cover incremental changes between releases, and are especially important to read for pre-releases. mailed returned " . $result . " ErrorInfo is " . $mail->ErrorInfo . " Processing is open source, free software. All donations fund the Processing Foundation, a nonprofit organization devoted to advancing the role of programming within the visual arts through developing Processing. ' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . " ' . $this->lang('smtp_error') . $lasterror['smtp_msg'] . "
-
-This demonstrates sending multiple email messages with binary attachments
-from a MySQL database using multipart/alternative messages.
-
-
-
-
-
-Extending classes with inheritance is one of the most
-powerful features of object-oriented programming. It allows you to make changes to the
-original class for your own personal use without hacking the original
-classes, and it's very easy to do:
-
-
-Here's a class that extends the phpmailer class and sets the defaults
-for the particular site:
-
- This example uses HTML. The PHPMailer image at the top has been embedded automatically. This folder contains a collection of examples of using PHPMailer. When working on email sending code you'll find yourself worrying about what might happen if all these test emails got sent to your mailing list. The solution is to use a fake mail server, one that acts just like the real thing, but just doesn't actually send anything out. Some offer web interfaces, feedback, logging, the ability to return specific error codes, all things that are useful for testing error handling, authentication etc. Here's a selection of mail testing tools you might like to try: Before running these examples you'll need to rename them with '.php' extensions. They are supplied as '.phps' files which will usually be displayed with syntax highlighting by PHP instead of running them. This prevents potential security issues with running potential spam-gateway code if you happen to deploy these code examples on a live site - please don't do that! Similarly, don't leave your passwords in these files as they will be visible to the world! This script is a simple code generator - fill in the form and hit submit, and it will use when you entered to email you a message, and will also generate PHP code using your settings that you can copy and paste to use in your own apps. If you need to get going quickly, this is probably the best place to start. This script is a basic example which creates an email message from an external HTML file, creates a plain text body, sets various addresses, adds an attachment and sends the message. It uses PHP's built-in mail() function which is the simplest to use, but relies on the presence of a local mail server, something which is not usually available on Windows. If you find yourself in that situation, either install a local mail server, or use a remote one and send using SMTP instead. The same as the mail example, but shows how to use PHPMailer's optional exceptions for error handling. A simple example sending using SMTP with authentication. A simple example sending using SMTP without authentication. A simple example using sendmail. Sendmail is a program (usually found on Linux/BSD, OS X and other UNIX-alikes) that can be used to submit messages to a local mail server without a lengthy SMTP conversation. It's probably the fastest sending mechanism, but lacks some error reporting features. There are sendmail emulators for most popular mail servers including postfix, qmail, exim etc. Submitting email via Google's Gmail service is a popular use of PHPMailer. It's much the same as normal SMTP sending, just with some specific settings, namely using TLS encryption, authentication is enabled, and it connects to the SMTP submission port 587 on the smtp.gmail.com host. This example does all that. Before effective SMTP authentication mechanisms were available, it was common for ISPs to use POP-before-SMTP authentication. As it implies, you authenticate using the POP3 protocol (an older protocol now mostly replaced by the far superior IMAP), and then the SMTP server will allow send access from your IP address for a short while, usually 5-15 minutes. PHPMailer includes a POP3 protocol client, so it can carry out this sequence - it's just like a normal SMTP conversation (without authentication), but connects via POP first. This is a somewhat naïve example of sending similar emails to a list of different addresses. It sets up a PHPMailer instance using SMTP, then connects to a MySQL database to retrieve a list of recipients. The code loops over this list, sending email to each person using their info and marks them as sent in the database. It makes use of SMTP keepalive which saves reconnecting and re-authenticating between each message. This is an example showing how to use the SMTP class by itself (without PHPMailer) to check an SMTP connection. Most of these examples use the 'example.com' domain. This domain is reserved by IANA for illustrative purposes, as documented in RFC 2606. Don't use made-up domains like 'mydomain.com' or 'somedomain.com' in examples as someone, somewhere, probably owns them! ";
$html .= nl2br($this->doc);
#$html .= $this->doc;
$html .= "
+
+
@@ -44,7 +44,7 @@ void pinEvent(int pin) {
-You need set the pin to output by calling pinMode() before calling this function. Unlike on Arduino, it is not possible to set a input pin's internal pull-up resistor using this function.
+You need to set the pin to output by calling pinMode() before calling this function. Unlike on Arduino, it is not possible to set a input pin's internal pull-up resistor using this function.
]]>
-You can use noInterrupts() and interrupts() in tandem to make sure no interrupts are occuring while your sketch is doing a particular task. By default, interrupts are enabled.
+You can use noInterrupts() and interrupts() in tandem to make sure no interrupts are occuring while your sketch is doing a particular task. By default, interrupts are enabled.
]]>
@@ -36,14 +38,13 @@ void setup() {
Unlike on Arduino, where pins are implicitly set to inputs by default, it is necessary
-to call this function for any pin you want to access, including input pins.
+to call this function for any pin you want to access, including input pins.
+
+Pull-up and pull-down resistors are very useful when connecting buttons and switches, since they will force the value of the pin in a specified electrical state when no electrical connection is made, and the pin would otherwise be left "floating".
+
+The ability to set (and clear) pull-up and pull-down resistors is currently limited to the Raspberry Pi running the Raspbian distribution. On other systems, a warning will be shown.
]]>
-Without calling this function the pin will remain in the current state even after the sketch has been closed.
+Without calling this function, the pin will remain in the current state even after the sketch has been closed.
]]>
-The mode parameter determines when the function will will return: GPIO.FALLING occurs when the level changes from high to low, GPIO.RISING when the level changes from low
-to high, and GPIO.CHANGE when either occurs.
+The mode parameter determines when the function will return: GPIO.FALLING occurs when the level changes from high to low, GPIO.RISING when the level changes from low to high, and GPIO.CHANGE when either occurs.
-This function returns true if the change, false if the timeout occured.
+The optional timeout parameter determines how many milliseconds the function will wait at the most. If the value of the input pin hasn't changed at this point, an exception is raised for this line. Without a timeout parameter the function will wait indefinitely until the input pin has changed to the desired state.
]]>
-I2C is a serial bus, commonly used to attach peripheral ICs (integrated circuits)
+I2C is a serial bus, commonly used to attach peripheral ICs (Integrated Circuits)
to processors and microcontrollers. It uses two pins, SDA (for data) and SDL (for
the clock signal). Multiple "slave" devices can be connected to the same bus, as
long as they are responding to different addresses (see below).
diff --git a/content/api_en/LIB_io/I2C_beginTransmission.xml b/content/api_en/LIB_io/I2C_beginTransmission.xml
index 55a6ce909..582fb97ff 100755
--- a/content/api_en/LIB_io/I2C_beginTransmission.xml
+++ b/content/api_en/LIB_io/I2C_beginTransmission.xml
@@ -23,7 +23,7 @@ void setup() {
void draw() {
background(map(mouseX, 0, width, 0, 255));
- // send value over I2C to an digital-to-analog
+ // send value over I2C to a digital-to-analog
// converter with address 96 (hex 0x60)
int val = int(4095 * map(mouseX, 0, width, 0.0, 1.0));
dac.beginTransmission(0x60);
diff --git a/content/api_en/LIB_io/I2C_close.xml b/content/api_en/LIB_io/I2C_close.xml
index 43db9573d..b3754a327 100755
--- a/content/api_en/LIB_io/I2C_close.xml
+++ b/content/api_en/LIB_io/I2C_close.xml
@@ -18,7 +18,7 @@ I2C i2c;
void setup() {
//printArray(I2C.list());
i2c = new I2C(I2C.list()[0]);
- // send a value over I2C to an digital-to-analog
+ // send a value over I2C to a digital-to-analog
// converter with address 96 (hex 0x60)
int val = 4095;
i2c.beginTransmission(0x60);
diff --git a/content/api_en/LIB_io/I2C_endTransmission.xml b/content/api_en/LIB_io/I2C_endTransmission.xml
index 83402ff1f..f5f909324 100755
--- a/content/api_en/LIB_io/I2C_endTransmission.xml
+++ b/content/api_en/LIB_io/I2C_endTransmission.xml
@@ -23,7 +23,7 @@ void setup() {
void draw() {
background(map(mouseX, 0, width, 0, 255));
- // send value over I2C to an digital-to-analog
+ // send value over I2C to a digital-to-analog
// converter with address 96 (hex 0x60)
int val = int(4095 * map(mouseX, 0, width, 0.0, 1.0));
dac.beginTransmission(0x60);
diff --git a/content/api_en/LIB_io/I2C_read.xml b/content/api_en/LIB_io/I2C_read.xml
index fee60f84d..db2332f3e 100755
--- a/content/api_en/LIB_io/I2C_read.xml
+++ b/content/api_en/LIB_io/I2C_read.xml
@@ -39,10 +39,10 @@ void draw() {
You must call beginTransmission() before calling this function.
-This function also ends the current transmisison and sends any data
+This function also ends the current transmission and sends any data
that was queued using write() before. It is not necessary to call
endTransmission() after read().
]]>
You must call beginTransmission() before calling this function. The actual writing takes part when read() or endTransmission() is being called.
]]>
+When no period is specified, a default 1 kHz (1000 Hz) is used.
]]>
-
The "master" device initiates a transfer by pulling the SS pin of the "slave"
low, and begins outputting a clock signal. In SPI, both the "master" as well as
the "slave" device output data at the same time. It is hence not possible to
-read data without also writing some (even if it means outputting zeros or other
+read data without writing some (even if it means outputting zeros or other
dummy data).
There are multiple possible configuration settings for SPI, see
diff --git a/content/api_en/LIB_io/SPI_close.xml b/content/api_en/LIB_io/SPI_close.xml
index e66756e3e..2e9d7f4a1 100755
--- a/content/api_en/LIB_io/SPI_close.xml
+++ b/content/api_en/LIB_io/SPI_close.xml
@@ -41,7 +41,7 @@ Closes the SPI interface
It is normally not necessary to explicitly close SPI interfaces, as they
are closed automatically by the operating system when the sketch exits.
-Note: It is possible to have two or more object using the same interface at
+Note: It is possible to have two or more objects using the same interface at
a time.
]]>
+
+
+Connect the signal wire (typically colored yellow) to any available GPIO pin
+and control the servo's angle as shown in the example sketch.
+]]>
+
+You must call this function before calling write(). Note that the
+servo motor will only be instructed to move after the first time
+write() is called.
+
+The optional parameters minPulse and maxPulse control the minimum
+and maximum pulse width durations. The default values, identical to
+those of Arduino's Servo class, should be compatible with most servo
+motors.
+]]>
+
+
+Calling this method will stop the servo from moving or trying to
+hold the current orientation.
+]]>
+
+If you are using this class in combination with a continuous rotation
+servo, different angles will result in the servo rotating forward or
+backward at different speeds. For regular servo motors, this will
+instruct the servo to rotate to and hold a specific angle.
+]]>GPIO
noInterrupts()
interrupts()
releaseInterrupt()
- waitForInterrupt()
+ waitFor()
releasePin()
@@ -66,7 +66,7 @@ LED
PWM
+ Use the SoftwareServo class below for the time being. Hardware PWM has yet to be made available by the hardware platforms we support.
PWM
list()
@@ -76,11 +76,15 @@ PWM
- RPI
+ SoftwareServo
+ The SoftwareServo class controls RC servo motors attached to General Purpose I/O pins.
- RPI
+ SoftwareServo
+ attach()
+ write()
+ attached()
+ detach()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/content/api_en/LIB_sound/Reverb.xml b/content/api_en/LIB_sound/Reverb.xml
index 8d34c05ce..6697df3b9 100755
--- a/content/api_en/LIB_sound/Reverb.xml
+++ b/content/api_en/LIB_sound/Reverb.xml
@@ -28,6 +28,7 @@ void setup() {
// start the input stream
in.play();
+ reverb.process(in);
}
void draw() {
diff --git a/content/api_en/LIB_sound/Reverb_stop.xml b/content/api_en/LIB_sound/Reverb_stop.xml
index 8d2fe420d..574071bfc 100755
--- a/content/api_en/LIB_sound/Reverb_stop.xml
+++ b/content/api_en/LIB_sound/Reverb_stop.xml
@@ -32,14 +32,14 @@ void setup() {
// Patch the reverb
reverb.process(in, 5);
- reverb.time(0.5);
+ //reverb.damp(0.5);
}
void draw() {
}
void mousePressed() {
- in.stop();
+ //in.stop();
reverb.stop();
}
diff --git a/content/api_en/LIB_sound/SawOsc.xml b/content/api_en/LIB_sound/SawOsc.xml
index 514326e8f..979ca1bb5 100755
--- a/content/api_en/LIB_sound/SawOsc.xml
+++ b/content/api_en/LIB_sound/SawOsc.xml
@@ -9,7 +9,7 @@
-
-
+
+
+
+
+
+
+
+
-
-
+Sound
- AudioIn
-
-
- PinkNoise
- BrownNoise
-
- SawOsc
- SqrOsc
- TriOsc
- Pulse
-
- Sound
+
+
+ AudioSample
+
+ PinkNoise
+ BrownNoise
+
+ SawOsc
+ SqrOsc
+ TriOsc
+ Pulse
+
+ SVG Export
+
+ This library can be used with the core Processing function size(), or createGraphics(). See the examples below for different techniques.
+
+This example draws a single frame to a SVG file and quits. (Note that no display window will open; this helps when you're trying to create massive SVG images that are far larger than the screen size.)import processing.svg.*;
+
+void setup() {
+ size(400, 400, SVG, "filename.svg");
+}
+
+void draw() {
+ // Draw something good here
+ line(0, 0, width/2, height);
+
+ // Exit the program
+ println("Finished.");
+ exit();
+}
+
+
+
+
+To draw to the screen while also saving an SVG beginRecord()
+and endRecord() functions. Unlike the PDF renderer, the SVG renderer will only save the final frame of a sequence. This is slower, but is useful when you need to
+see what you're working on as it saves.import processing.svg.*;
+
+void setup() {
+ size(400, 400);
+ noLoop();
+ beginRecord(SVG, "filename.svg");
+}
+
+void draw() {
+ // Draw something good here
+ line(0, 0, width/2, height);
+
+ endRecord();
+}
+
+
+
+It's also possible to save one frame from a program with moving elements.
+Create a boolean variable to turn the SVG recording process on and offimport processing.svg.*;
+
+boolean record;
+
+void setup() {
+ size(400, 400);
+}
+
+void draw() {
+ if (record) {
+ // Note that #### will be replaced with the frame number. Fancy!
+ beginRecord(SVG, "frame-####.svg");
+ }
+
+ // Draw something good here
+ background(255);
+ line(mouseX, mouseY, width/2, height/2);
+
+ if (record) {
+ endRecord();
+ record = false;
+ }
+}
+
+// Use a keypress so thousands of files aren't created
+void mousePressed() {
+ record = true;
+}
+
+
+
+
+To create vectors from 3D data, use the beginRaw() and endRaw() commands.
+These commands will grab the shape data just before it is rendered to the screen.
+At this stage, your entire scene is nothing but a long list of lines and triangles.
+This means that a shape created with sphere() method will be made up of hundreds of
+triangles, rather than a single object.import processing.svg.*;
+
+boolean record;
+
+void setup() {
+ size(500, 500, P3D);
+}
+
+void draw() {
+ if (record) {
+ beginRaw(SVG, "output.svg");
+ }
+
+ // Do all your drawing here
+ background(204);
+ translate(width/2, height/2, -200);
+ rotateZ(0.2);
+ rotateY(mouseX/500.0);
+ box(200);
+
+ if (record) {
+ endRaw();
+ record = false;
+ }
+}
+
+// Hit 'r' to record a single frame
+void keyPressed() {
+ if (key == 'r') {
+ record = true;
+ }
+}
+
+
+
+
+To write a SVG file using only the createGraphics() command, rather than as
+part of a sketch, it's necessary to call dispose() on the PGraphicsSVG object.
+This is the same as calling exit(), but it won't quit the sketch.import processing.svg.*;
+
+PGraphics svg = createGraphics(300, 300, SVG, "output.svg");
+svg.beginDraw();
+svg.background(128, 0, 0);
+svg.line(50, 50, 250, 250);
+svg.dispose();
+svg.endDraw();
+
+
+
+
+
+
+
+
+
+Main graphics and rendering context, as well as the base API implementation for processing "core". Use this class if you need to draw into an off-screen graphics buffer. A PGraphics object can be constructed with the createGraphics() function. The beginDraw() and endDraw() methods (see above example) are necessary to set up the buffer and to finalize it. The fields and methods for this class are extensive. For a complete list, visit the developer's reference.
To create a new graphics context, use the createGraphics() function. Do not use the syntax new PGraphics().
]]>
Limits each channel of the image to the number of colors specified as the parameter. The parameter can be set to values between 2 and 255, but results are most noticeable in the lower ranges.
BLUR
-Executes a Guassian blur with the level parameter specifying the extent of the blurring. If no parameter is used, the blur is equivalent to Guassian blur of radius 1. Larger values increase the blur.
+Executes a Gaussian blur with the level parameter specifying the extent of the blurring. If no parameter is used, the blur is equivalent to Gaussian blur of radius 1. Larger values increase the blur.
ERODE
Reduces the light areas. No parameter is used.
diff --git a/content/api_en/PImage_loadPixels.xml b/content/api_en/PImage_loadPixels.xml
index 5e84cfc90..a9c353f84 100644
--- a/content/api_en/PImage_loadPixels.xml
+++ b/content/api_en/PImage_loadPixels.xml
@@ -34,8 +34,6 @@ void draw() {
-Certain renderers may or may not seem to require loadPixels() or updatePixels(). However, the rule is that any time you want to manipulate the pixels[] array, you must first call loadPixels(), and after changes have been made, call updatePixels(). Even if the renderer may not seem to use this function in the current Processing release, this will always be subject to change.
]]>
+
+Before accessing this array, the data must loaded with the loadPixels() method. Failure to do so may result in a NullPointerException. After the array data has been modified, the updatePixels() method must be run to update the content of the display window.
]]>
To save an image created within the code, rather than through loading, it's necessary to make the image with the createImage() function so it is aware of the location of the program and can therefore save the file to the right place. See the createImage() reference for more information.
+Saves the image into a file. Append a file extension to the name of the file, to indicate the file format to be used: either TIFF (.tif), TARGA (.tga), JPEG (.jpg), or PNG (.png). If no extension is included in the filename, the image will save in TIFF format and .tif will be added to the name. These files are saved to the sketch's folder, which may be opened by selecting "Show sketch folder" from the "Sketch" menu.
To save an image created within the code, rather than through loading, it's necessary to make the image with the createImage() function so it is aware of the location of the program and can therefore save the file to the right place. See the createImage() reference for more information.
]]>
-Certain renderers may or may not seem to require loadPixels() or updatePixels(). However, the rule is that any time you want to manipulate the pixels[] array, you must first call loadPixels(), and after changes have been made, call updatePixels(). Even if the renderer may not seem to use this function in the current Processing release, this will always be subject to change.
-
-Currently, none of the renderers use the additional parameters to updatePixels(), however this may be implemented in the future.
]]>
-The PShape object contains a group of methods that can operate on the shape data. Some of the methods are listed below, but the full list used for creating and modifying shapes is available here in the Processing Javadoc.
+The PShape object contains a group of methods that can operate on the shape data. Some of the methods are listed below, but the full list used for creating and modifying shapes is available here in the Processing Javadoc.
To create a new shape, use the createShape() function. Do not use the syntax new PShape().
]]>
+
+Additional Table methods are documented in the Processing Table Javadoc.
+
]]>
+
+Additional TableRow methods are documented in the Processing Data Javadoc.
]]>
+
+
+
+
+Expands a one-dimensional array by one element and adds data to the new position. The datatype of the element parameter must be the same as the datatype of the array.
When using an array of objects, the data returned from the function must be cast to the object array's data type. For example: SomeClass[] items = (SomeClass[]) append(originalArray, element)
]]>
-
-There are three ways to draw an arc; the rendering technique used is defined by the optional seventh parameter. The three options, depicted in the above examples, are PIE, OPEN, and CHORD. The default mode is the OPEN stroke with a PIE fill.
-
+Draws an arc to the screen. Arcs are drawn along the outer edge of an ellipse defined by the a, b, c, and d parameters. The origin of the arc's ellipse may be changed with the ellipseMode() function. Use the start and stop parameters to specify the angles (in radians) at which to draw the arc. The start/stop values must be in clockwise order.
+
+There are three ways to draw an arc; the rendering technique used is defined by the optional seventh parameter. The three options, depicted in the above examples, are PIE, OPEN, and CHORD. The default mode is the OPEN stroke with a PIE fill.
+
In some cases, the arc() function isn't accurate enough for smooth drawing. For example, the shape may jitter on screen when rotating slowly. If you're having an issue with how arcs are rendered, you'll need to draw the arc yourself with beginShape()/endShape() or a PShape.
]]>
The simplified version with only two arguments — arrayCopy(src, dst) — copies an entire array to another of the same size. It is equivalent to arrayCopy(src, 0, dst, 0, src.length).
-Using this function is far more efficient for copying array data than iterating through a for() loop and copying each element individually. This function only copies references, which means that for most purposes it only copies one-dimensional arrays (a single set of brackets). If used with a two (or three or more) dimensional array, it will only copy the references at the first level, because a two dimensional array is simply an "array of arrays". This does not produce an error, however, because this is often the desired behavior. Internally, this function calls Java's System.arraycopy() method, so most things that apply there are inherited.
+Using this function is far more efficient for copying array data than iterating through a for() loop and copying each element individually. This function only copies references, which means that for most purposes it only copies one-dimensional arrays (a single set of brackets). If used with a two (or three or more) dimensional array, it will only copy the references at the first level, because a two dimensional array is simply an "array of arrays". This does not produce an error, however, because this is often the desired behavior. Internally, this function calls Java's System.arraycopy() method, so most things that apply there are inherited.
]]>
diff --git a/content/api_en/attrib.xml b/content/api_en/attrib.xml
new file mode 100644
index 000000000..3d21bc538
--- /dev/null
+++ b/content/api_en/attrib.xml
@@ -0,0 +1,63 @@
+
+
+
If you want a background to show up in your files, use rect(0, 0, width, height) after setting the fill() to the background color. Otherwise the background will not be rendered to the file because the background is not shape.
-Using hint(ENABLE_DEPTH_SORT) can improve the appearance of 3D geometry drawn to 2D file formats. See the hint() reference for more details.
+Using hint(ENABLE_DEPTH_SORT) can improve the appearance of 3D geometry drawn to 2D file formats.
See examples in the reference for the PDF and DXF libraries for more information.
]]>
diff --git a/content/api_en/blend.xml b/content/api_en/blend.xml
index d10a95f76..59d8431c9 100755
--- a/content/api_en/blend.xml
+++ b/content/api_en/blend.xml
@@ -52,15 +52,15 @@ blend(img, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST);
-BLEND - linear interpolation of colours: C = A*factor + B
+BLEND - linear interpolation of colors: C = A*factor + B
ADD - additive blending with white clip: C = min(A*factor + B, 255)
SUBTRACT - subtractive blending with black clip: C = max(B - A*factor, 0)
-DARKEST - only the darkest colour succeeds: C = min(A*factor, B)
+DARKEST - only the darkest color succeeds: C = min(A*factor, B)
-LIGHTEST - only the lightest colour succeeds: C = max(A*factor, B)
+LIGHTEST - only the lightest color succeeds: C = max(A*factor, B)
DIFFERENCE - subtract colors from underlying image.
diff --git a/content/api_en/blendMode.xml b/content/api_en/blendMode.xml
index 26e3285a2..a3c309cb1 100755
--- a/content/api_en/blendMode.xml
+++ b/content/api_en/blendMode.xml
@@ -35,17 +35,17 @@ line(75, 25, 25, 75);
-BLEND - linear interpolation of colours: C = A*factor + B. This is the default blending mode.
+BLEND - linear interpolation of colors: C = A*factor + B. This is the default.
ADD - additive blending with white clip: C = min(A*factor + B, 255)
SUBTRACT - subtractive blending with black clip: C = max(B - A*factor, 0)
-DARKEST - only the darkest colour succeeds: C = min(A*factor, B)
+DARKEST - only the darkest color succeeds: C = min(A*factor, B)
-LIGHTEST - only the lightest colour succeeds: C = max(A*factor, B)
+LIGHTEST - only the lightest color succeeds: C = max(A*factor, B)
DIFFERENCE - subtract colors from underlying image.
diff --git a/content/api_en/circle.xml b/content/api_en/circle.xml
new file mode 100755
index 000000000..0e1d9adfb
--- /dev/null
+++ b/content/api_en/circle.xml
@@ -0,0 +1,23 @@
+
+
+
+Creates and returns a new PGraphics object. Use this class if you need to draw into an off-screen graphics buffer. The first two parameters define the width and height in pixels. The third, optional parameter specifies the renderer. It can be defined as P2D, P3D, PDF, or SVG. If the third parameter isn't used, the default renderer is set. The PDF and SVG renderers require the filename parameter.
-It's important to consider the renderer used with createGraphics() in relation to the main renderer specified in size(). For example, it's only possible to use P2D or P3D with createGraphics() when one of them is defined in size(). Unlike Processing 1.0, P2D and P3D use OpenGL for drawing, and when using an OpenGL renderer it's necessary for the main drawing surface to be OpenGL-based. If P2D or P3D are used as the renderer in size(), then any of the options can be used with createGraphics(). If the default renderer is used in size(), then only the default or PDF can be used with createGraphics().
+It's important to consider the renderer used with createGraphics() in relation to the main renderer specified in size(). For example, it's only possible to use P2D or P3D with createGraphics() when one of them is defined in size(). Unlike Processing 1.0, P2D and P3D use OpenGL for drawing, and when using an OpenGL renderer it's necessary for the main drawing surface to be OpenGL-based. If P2D or P3D are used as the renderer in size(), then any of the options can be used with createGraphics(). If the default renderer is used in size(), then only the default, PDF, or SVG can be used with createGraphics().
-It's important to call any drawing functions between beginDraw() and endDraw() statements. This is also true for any functions that affect drawing, such as smooth() or colorMode().
+It's important to run all drawing functions between the beginDraw() and endDraw(). As the exception to this rule, smooth() should be run on the PGraphics object before beginDraw(). See the reference for smooth() for more detail.
+
+The createGraphics() function should almost never be used inside draw() because of the memory and time needed to set up the graphics. One-time or occasional use during draw() might be acceptable, but code that calls createGraphics() at 60 frames per second might run out of memory or freeze your sketch.
Unlike the main drawing surface which is completely opaque, surfaces created with createGraphics() can have transparency. This makes it possible to draw into a graphics and maintain the alpha channel. By using save() to write a PNG or TGA file, the transparency of the graphics object will be honored.
]]>
+Creates a BufferedReader object that can be used to read files line-by-line as individual String objects. This is the complement to the createWriter() function. For more information about the BufferedReader class and its methods like readLine() and close used in the above example, please consult a Java reference.
+
Starting with Processing release 0134, all files loaded and saved by the Processing API use UTF-8 encoding. In previous releases, the default encoding for your platform was used, which causes problems when files are moved to other platforms.
]]>
+The createShape() function is used to define a new shape. Once created, this shape can be drawn with the shape() function. The basic way to use the function defines new primitive shapes. One of the following parameters are used as the first parameter: ELLIPSE, RECT, ARC, TRIANGLE, SPHERE, BOX, QUAD, or LINE. The parameters for each of these different shapes are the same as their corresponding functions: ellipse(), rect(), arc(), triangle(), sphere(), box(), quad(), and line(). The first example above clarifies how this works.
Custom, unique shapes can be made by using createShape() without a parameter. After the shape is started, the drawing attributes and geometry can be set directly to the shape within the beginShape() and endShape() methods. See the second example above for specifics, and the reference for beginShape() for all of its options.
The createShape() function can also be used to make a complex shape made of other shapes. This is called a "group" and it's created by using the parameter GROUP as the first parameter. See the fourth example above to see how it works.
-After using createShape(), stroke and fill color can be set by calling methods like setFill() and setStroke(), as seen in the examples above. The complete list of methods and fields for the PShape class are in the Processing Javadoc.
+After using createShape(), stroke and fill color can be set by calling methods like setFill() and setStroke(), as seen in the examples above. The complete list of methods and fields for the PShape class are in the Processing Javadoc.
]]>
+Sets the cursor to a predefined symbol or an image, or makes it visible if already hidden. If you are trying to set an image as the cursor, the recommended size is 16x16 or 32x32 pixels. The values for parameters x and y must be less than the dimensions of the image.
+
Setting or hiding the cursor does not generally work with "Present" mode (when running full-screen).
-
+
With the P2D and P3D renderers, a generic set of cursors are used because the OpenGL renderer doesn't have access to the default cursor images for each platform (Issue 3791).
]]>
+Called directly after setup(), the draw() function continuously executes the lines of code contained inside its block until the program is stopped or noLoop() is called. draw() is called automatically and should never be called explicitly. All Processing programs update the screen at the end of draw(), never earlier.
-It should always be controlled with noLoop(), redraw() and loop(). If noLoop() is used to stop the code in draw() from executing, then redraw() will cause the code inside draw() to be executed a single time, and loop() will cause the code inside draw() to resume executing continuously.
+To stop the code inside of draw() from running continuously, use noLoop(), redraw() and loop(). If noLoop() is used to stop the code in draw() from running, then redraw() will cause the code inside draw() to run a single time, and loop() will cause the code inside draw() to resume running continuously.
The number of times draw() executes in each second may be controlled with the frameRate() function.
-It is common to call background() near the beginning of the draw() loop to clear the contents of the window, as shown in the first example above. Since pixels drawn to the window are cumulative, omitting background() may result in unintended results, especially when drawing anti-aliased shapes or text.
-
+It is common to call background() near the beginning of the draw() loop to clear the contents of the window, as shown in the first example above. Since pixels drawn to the window are cumulative, omitting background() may result in unintended results.
+
There can only be one draw() function for each sketch, and draw() must exist if you want the code to run continuously, or to process events such as mousePressed(). Sometimes, you might have an empty call to draw() in your program, as shown in the second example above.
]]>
File
"sketch_YYMMDDa".
Open a sketch in a new window.
-
- Open a sketch from the sketchbook folder.
Select a sketch to open from the list of recently closed sketches.
@@ -533,8 +531,8 @@ Android Mode
+Quits/stops/exits the program. Programs without a draw() function stop automatically after the last line has run, but programs with draw() run continuously until the program is manually stopped or exit() is run.
Rather than terminating immediately, exit() will cause the sketch to exit after draw() has completed (or after setup() completes if called during the setup() function).
diff --git a/content/api_en/expand.xml b/content/api_en/expand.xml
index 30c9d4afe..f0f020319 100755
--- a/content/api_en/expand.xml
+++ b/content/api_en/expand.xml
@@ -32,7 +32,7 @@ println(imgs.length); // Prints "64"
When using an array of objects, the data returned from the function must be cast to the object array's data type. For example: SomeClass[] items = (SomeClass[]) expand(originalArray)
]]>
A frustum is a geometric form: a pyramid with its top cut off. With the viewer's eye at the imaginary top of the pyramid, the six planes of the frustum act as clipping planes when rendering a 3D view. Thus, any form inside the clipping planes is rendered and visible; anything outside those planes is not visible.
-Setting the frustum has the effect of changing the perspective with which the scene is rendered. This can be acheived more simply in many cases by using perspective().
+Setting the frustum has the effect of changing the perspective with which the scene is rendered. This can be achieved more simply in many cases by using perspective().
Note that the near value must be greater than zero (as the point of the frustum "pyramid" cannot converge "behind" the viewer). Similarly, the far value must be greater than the near value (as the "far" plane of the frustum must be "farther away" from the viewer than the near plane).
diff --git a/content/api_en/fullScreen.xml b/content/api_en/fullScreen.xml
index eb1fea958..e75bfd541 100755
--- a/content/api_en/fullScreen.xml
+++ b/content/api_en/fullScreen.xml
@@ -34,7 +34,7 @@ void draw() {
+This function is new for Processing 3.0. It opens a sketch using the full size of the computer's display. This function must be the first line in setup(). The size() and fullScreen() functions cannot both be used in the same program, just choose one.
-The size() and fullScreen() methods cannot both be used in the same program, just choose one. Prior to Processing 3.0, a full-screen program was defined with size(displayWidth, displayHeight).
+When fullScreen() is used without a parameter, it draws the sketch to the screen currently selected inside the Preferences window. When it is used with a single parameter, this number defines the screen to display to program on (e.g. 1, 2, 3...). When used with two parameters, the first defines the renderer to use (e.g. P2D) and the second defines the screen. The SPAN parameter can be used in place of a screen number to draw the sketch as a full-screen window across all of the attached displays if there are more than one.
+
+Prior to Processing 3.0, a full-screen program was defined with size(displayWidth, displayHeight).
]]>
-
+Reads the color of any pixel or grabs a section of an image. If no parameters are specified, the entire image is returned. Use the x and y parameters to get the value of one pixel. Get a section of the display window by specifying additional w and h parameters. When getting an image, the x and y parameters define the coordinates for the upper-left corner of the image, regardless of the current imageMode().
+
If the pixel requested is outside of the image window, black is returned. The numbers returned are scaled according to the current color ranges, but only RGB values are returned by this function. For example, even though you may have drawn a shape with colorMode(HSB), the numbers returned will be in RGB format.
+If a width and a height are specified, get(x, y, w, h) returns a PImage corresponding to the part of the original PImage where the top left pixel is at the (x, y) position with a width of w a height of h.
+
Getting the color of a single pixel with get(x, y) is easy, but not as fast as grabbing the data directly from pixels[]. The equivalent statement to get(x, y) using pixels[] is pixels[y*width+x]. See the reference for pixels[] for more information.
]]>
-float r1 = green(c); // Simpler, but slower to calculate
-float r2 = c >> 8 & 0xFF; // Very fast to calculate
+float g1 = green(c); // Simpler, but slower to calculate
+float g2 = c >> 8 & 0xFF; // Very fast to calculate
]]>
An ArrayList is a resizable-array implementation of the Java List interface. It has many methods used to control and search its contents. For example, the length of the ArrayList is returned by its size() method, which is an integer value for the total number of elements in the list. An element is added to an ArrayList with the add() method and is deleted with the remove() method. The get() method returns the element at the specified position in the list. (See the above example for context.)
-For a list of the numerous ArrayList features, please read the Java reference description.
+For a list of the numerous ArrayList features, please read the Java reference description.
]]>
-For a list of the numerous HashMap features, please read the Java reference description.
+For a list of the numerous HashMap features, please read the Java reference description.
]]>
@@ -46,11 +43,11 @@ println(quoted); // This one has "quotes"
-To compare the contents of two Strings, use the equals() method, as in if (a.equals(b)), instead of if (a == b). A String is an Object, so comparing them with the == operator only compares whether both Strings are stored in the same memory location. Using the equals() method will ensure that the actual contents are compared. (The troubleshooting reference has a longer explanation.)
+To compare the contents of two Strings, use the equals() method, as in if (a.equals(b)), instead of if (a == b). A String is an Object, so comparing them with the == operator only compares whether both Strings are stored in the same memory location. Using the equals() method will ensure that the actual contents are compared. (The troubleshooting reference has a longer explanation.)
Because a String is defined between double quotation marks, to include such marks within the String itself you must use the \ (backslash) character. (See the third example above.) This is known as an escape sequence. Other escape sequences include \t for the tab character and \n for new line. Because backslash is the escape character, to include a single backslash within a String, you must use two consecutive backslashes, as in: \\
-There are more string methods than those linked from this page. Additional documentation is located online in the official Java documentation.
+There are more string methods than those linked from this page. Additional documentation is located online in the official Java documentation.
]]>
Using print() or println() on a color will produce strange results (usually negative numbers) because of the way colors are stored in memory. A better technique is to use the hex() function to format the color data, or use the red(), green(), and blue() functions to get individual values and print those. The hue(), saturation(), and brightness() functions work in a similar fashion. To extract red, green, and blue values more quickly (for instance when analyzing an image or a frame of video), use bit shifting.
diff --git a/content/api_en/include/curlybraces.xml b/content/api_en/include/curlybraces.xml
index f4f1898c9..e9984f0d7 100755
--- a/content/api_en/include/curlybraces.xml
+++ b/content/api_en/include/curlybraces.xml
@@ -26,7 +26,7 @@ void draw() {
+Doc comments may be converted into browseable documentation using external editors and tools such as the command line javadoc, doc generators such as Doxygen, or IDEs such as Eclipse, Netbeans, or IntelliJ IDEA.
]]>
+
+Note that when comparing String objects, you must use the equals() method instead of ==. See the reference for String or the troubleshooting note for more explanation.
-Note that when comparing String objects, you must use the equals() method instead of == to compare their contents. See the reference for String or the troubleshooting note for more explanation.
]]>
Floats are not precise, so adding small values (such as 0.0001) may not always increment precisely due to rounding errors. If you want to increment a value in small intervals, use an int, and divide by a float value before using it. (See the second example above.)
-Floating-point numbers can be as large as 3.40282347E+38 and as low as -3.40282347E+38. They are stored as 32 bits (4 bytes) of information. The float data type is inherited from Java; you can read more about the technical details here and here.
+Floating-point numbers can be as large as 3.40282347E+38 and as low as -3.40282347E+38. They are stored as 32 bits (4 bytes) of information. The float data type is inherited from Java; you can read more about the technical details here and here.
Processing supports the double datatype from Java as well. However, none of the Processing functions use double values, which use more memory and are typically overkill for most work created in Processing. We do not plan to add support for double values, as doing so would require increasing the number of API functions significantly.
]]>
+
Hints for use with P2D and P3D:
+DISABLE_ASYNC_SAVEFRAME
+save() and saveFrame() will not use separate threads for saving and will block until the image is written to the drive. This was the default behavior in 3.0b7 and before. To enable, call hint(ENABLE_ASYNC_SAVEFRAME).
+
DISABLE_OPENGL_ERRORS
Speeds up the P3D renderer setting by not checking for errors while running.
@@ -45,4 +68,27 @@ Forces the P3D renderer to draw each shape (including its strokes) separately, i
Enables stroke geometry (lines and points) to be affected by the perspective, meaning that they will look smaller as they move away from the camera.
]]>
+Converts any value of a primitive data type (boolean, byte, char, color, float, int, or long) or String to its integer representation.
When an array of values is passed in, then an int array of the same length is returned.
]]>
Bit shifting is helpful when using the color data type. A right shift can extract red, green, blue, and alpha values from a color. A left shift can be used to quickly reassemble a color value (more quickly than the color() function).
]]>
+
+There are more features of PSurface documented in the Processing JavaDoc.
+]]>
+
+There are more features of PSurface documented in the Processing JavaDoc.
+]]>
+
+There are more features of PSurface documented in the Processing JavaDoc.
+]]>
+Converts a value of a primitive data type (boolean, byte, char, int, or float) to its String representation. For example, converting an integer with str(3) will return the String value of "3", converting a float with str(-12.6) will return "-12.6", and converting a boolean with str(true) will return "true".
When an array of values is passed in, then a String array of the same length is returned.
]]>
-For non-ASCII keys, use the keyCode variable. The keys included in the ASCII specification (BACKSPACE, TAB, ENTER, RETURN, ESC, and DELETE) do not require checking to see if they key is coded, and you should simply use the key variable instead of keyCode If you're making cross-platform projects, note that the ENTER key is commonly used on PCs and Unix and the RETURN key is used instead on Macintosh. Check for both ENTER and RETURN to make sure your program will work for all platforms.
+For non-ASCII keys, use the keyCode variable. The keys included in the ASCII specification (BACKSPACE, TAB, ENTER, RETURN, ESC, and DELETE) do not require checking to see if the key is coded, and you should simply use the key variable instead of keyCode If you're making cross-platform projects, note that the ENTER key is commonly used on PCs and Unix and the RETURN key is used instead on Macintosh. Check for both ENTER and RETURN to make sure your program will work for all platforms.
There are issues with how keyCode behaves across different renderers and operating systems. Watch out for unexpected behavior as you switch renderers and operating systems.
]]>
The keys included in the ASCII specification (BACKSPACE, TAB, ENTER, RETURN, ESC, and DELETE) do not require checking to see if the key is coded; for those keys, you should simply use the key variable directly (and not keyCode). If you're making cross-platform projects, note that the ENTER key is commonly used on PCs and Unix, while the RETURN key is used on Macs. Make sure your program will work on all platforms by checking for both ENTER and RETURN.
-For those familiar with Java, the values for UP and DOWN are simply shorter versions of Java's KeyEvent.VK_UP and KeyEvent.VK_DOWN. Other keyCode values can be found in the Java KeyEvent reference.
+For those familiar with Java, the values for UP and DOWN are simply shorter versions of Java's KeyEvent.VK_UP and KeyEvent.VK_DOWN. Other keyCode values can be found in the Java KeyEvent reference.
There are issues with how keyCode behaves across different renderers and operating systems. Watch out for unexpected behavior as you switch renderers and operating systems and you are using keys are aren't mentioned in this reference entry.
+
+If you are using P2D or P3D as your renderer, use the NEWT KeyEvent constants.
]]>
diff --git a/content/api_en/keyPressed.xml b/content/api_en/keyPressed.xml
index 224ed7da8..9cc506b40 100755
--- a/content/api_en/keyPressed.xml
+++ b/content/api_en/keyPressed.xml
@@ -41,6 +41,8 @@ Because of how operating systems handle key repeats, holding down a key may caus
Note that there is a similarly named boolean variable called keyPressed. See its reference page for more information.
Mouse and keyboard events only work when a program has draw(). Without draw(), the code is only run once and then stops listening for events.
+
+With the release of macOS Sierra, Apple changed how key repeat works, so keyPressed may not function as expected. See here for details of the problem and how to fix it.
]]>
diff --git a/content/api_en/launch.xml b/content/api_en/launch.xml
index 464902f0a..87b86e389 100755
--- a/content/api_en/launch.xml
+++ b/content/api_en/launch.xml
@@ -27,36 +27,14 @@ void mousePressed() {
]]>
-
-
-
-The argv parameter is a String or String array which is passed to the command line. If you have multiple parameters, e.g. an application and a document, or a command with multiple switches, use the version that takes a String array, and place each individual item in a separate element.
-
-If argv is a String (not an array), then it can only be a single file or application with no parameters. It's not the same as executing that String using a shell. For instance, open("jikes -help") will not work properly.
-
-This function behaves differently on each platform. On Windows, the parameters are sent to the Windows shell via "cmd /c". On Mac OS X, the "open" command is used (type "man open" in Terminal.app for documentation). On Linux, it first tries gnome-open, then kde-open, but if neither are available, it sends the command to the shell without any alterations.
-
-For users familiar with Java, this is not quite the same as Runtime.exec(), because the launcher command is prepended. Instead, the exec(String[]) function is a shortcut for Runtime.getRuntime.exec(String[]).
+Attempts to open an application or file using your platform's launcher. The filename parameter is a String specifying the file name and location. The location parameter must be a full path name, or the name of an executable in the system's PATH. In most cases, using a full path is the best option, rather than relying on the system PATH. Be sure to make the file executable before attempting to open it (chmod +x).
+
+This function (roughly) emulates what happens when you double-click an application or document in the macOS Finder, the Windows Explorer, or your favorite Linux file manager. If you're trying to run command line functions directly, use the exec() function instead (see below).
+
+This function behaves differently on each platform. On Windows, the parameters are sent to the Windows shell via "cmd /c". On Mac OS X, the "open" command is used (type "man open" in Terminal.app for documentation). On Linux, it first tries gnome-open, then kde-open, but if neither are available, it sends the command to the shell and prays that something useful happens.
+
+For users familiar with Java, this is not the same as Runtime.exec(), because the launcher command is prepended. Instead, the exec(String[]) function is a shortcut for Runtime.getRuntime.exec(String[]). The exec() function is documented in the JavaDoc in the PApplet class.
]]>
An amount below 0 will be treated as 0. Likewise, amounts above 1 will be capped at 1. This is different from the behavior of lerp(), but necessary because otherwise numbers outside the range will produce strange and unexpected colors.
]]>PDF Export
Network
SVG Export
+ Serial
-
-Certain renderers may or may not seem to require loadPixels() or updatePixels(). However, the rule is that any time you want to manipulate the pixels[] array, you must first call loadPixels(), and after changes have been made, call updatePixels(). Even if the renderer may not seem to use this function in the current Processing release, this will always be subject to change.
+Loads the pixel data of the current display window into the pixels[] array. This function must always be called before reading from or writing to pixels[]. Subsequent changes to the display window will not be reflected in pixels until loadPixels() is called again.
]]>
+Reads the contents of a file or URL and creates an Table object with its values. If a file is specified, it must be located in the sketch's "data" folder. The filename parameter can also be a URL to a file found online. The filename must either end in an extension or an extension must be specified in the options parameter. For example, to use tab-separated data, include "tsv" in the options parameter if the filename or URL does not end in .tsv. Note: If an extension is in both places, the extension in the options is used.
+
+If the file contains a header row, include "header" in the options parameter. If the file does not have a header row, then simply omit the "header" option.
-If the file contains a header row, include "header" in the options parameter. If the file does not have a header row, then simply omit the "header" option.
+Some CSV files contain newline (CR or LF) characters inside cells. This is rare, but adding the "newlines" option will handle them properly. (This is not enabled by default because the parsing code is much slower.)
-When specifying both a header and the file type, separate the options with commas, as in: loadTable("data.csv", "header, tsv")
+When specifying multiple options, separate them with commas, as in: loadTable("data.csv", "header, tsv")
All files loaded and saved by the Processing API use UTF-8 encoding.
]]>
-All files loaded and saved by the Processing API use UTF-8 encoding. If you need to load an XML file that's not in UTF-8 format, see the developer's reference for the XML object.
+All files loaded and saved by the Processing API use UTF-8 encoding. If you need to load an XML file that's not in UTF-8 format, see the developer's reference for the XML object.
]]>
If there are groups (specified by sets of parentheses) in the regular expression, then the contents of each will be returned in the array. Element [0] of a regular expression match returns the entire matching string, and the match groups start at element [1] (the first group is [1], the second [2], and so on).
-The syntax can be found in the reference for Java's Pattern class. For regular expression syntax, read the Java Tutorial on the topic.
+The syntax can be found in the reference for Java's Pattern class. For regular expression syntax, read the Java Tutorial on the topic.
]]>
diff --git a/content/api_en/matchAll.xml b/content/api_en/matchAll.xml
index 56feb6b5b..4f0345fbe 100644
--- a/content/api_en/matchAll.xml
+++ b/content/api_en/matchAll.xml
@@ -33,7 +33,7 @@ To use the function, first check to see if the result is null. If the result is
If there are groups (specified by sets of parentheses) in the regular expression, then the contents of each will be returned in the array. Assuming a loop with counter variable i, element [i][0] of a regular expression match returns the entire matching string, and the match groups start at element [i][1] (the first group is [i][1], the second [i][2], and so on).
-The syntax can be found in the reference for Java's Pattern class. For regular expression syntax, read the Java Tutorial on the topic.
+The syntax can be found in the reference for Java's Pattern class. For regular expression syntax, read the Java Tutorial on the topic.
]]>
diff --git a/content/api_en/mouseWheel.xml b/content/api_en/mouseWheel.xml
index 02c01cd7a..0a2344176 100755
--- a/content/api_en/mouseWheel.xml
+++ b/content/api_en/mouseWheel.xml
@@ -26,7 +26,7 @@ void mouseWheel(MouseEvent event) {
Mouse and keyboard events only work when a program has draw(). Without draw(), the code is only run once and then stops listening for events.
]]>
As shown in the above example, nf() is used to add zeros to the left and/or right of a number. This is typically for aligning a list of numbers. To remove digits from a floating-point number, use the int(), ceil(), floor(), or round() functions.
+Utility function for formatting numbers into strings. There are two versions: one for formatting floats, and one for formatting ints. The values for the digits and right parameters should always be positive integers. The left parameter should be positive or 0. If it is zero, only the right side is formatted.
As shown in the above example, nf() is used to add zeros to the left and/or right of a number. This is typically for aligning a list of numbers. To remove digits from a floating-point number, use the int(), ceil(), floor(), or round() functions.
]]>
+
+Utility function for formatting numbers into strings and placing appropriate commas to mark units of 1000. There are four versions: one for formatting ints, one for formatting an array of ints, one for formatting floats, and one for formatting an array of floats.
+
+The value for the right parameter should always be a positive integer.
+
For a non-US locale, this will insert periods instead of commas, or whatever is apprioriate for that region.
]]>
By default, noise is computed over 4 octaves with each octave contributing exactly half than its predecessor, starting at 50% strength for the first octave. This falloff amount can be changed by adding an additional function parameter. For example, a falloff factor of 0.75 means each octave will now have 75% impact (25% less) of the previous lower octave. While any number between 0.0 and 1.0 is valid, note that values greater than 0.5 may result in noise() returning values greater than 1.0.
diff --git a/content/api_en/parseJSONArray.xml b/content/api_en/parseJSONArray.xml
index f4cbb0b98..cdb4a4832 100755
--- a/content/api_en/parseJSONArray.xml
+++ b/content/api_en/parseJSONArray.xml
@@ -11,7 +11,7 @@
size() in a program without a setup() and used within setup() when a program has one. The pixelDensity() should only be used with hardcoded numbers (in almost all cases this number will be 2) or in combination with displayDensity() as in the third example above.
-
+
+When the pixel density is set to more than 1, it changes all of the pixel operations including the way get(), set(), blend(), copy(), and updatePixels() all work. See the reference for pixelWidth and pixelHeight for more information.
+
To use variables as the arguments to pixelDensity() function, place the pixelDensity() function within the settings() function. There is more information about this on the settings() reference page.
-
]]>
+
+
-
-Before accessing this array, the data must loaded with the loadPixels() function. After the array data has been modified, the updatePixels() function must be run to update the changes. Without loadPixels(), running the code may (or will in future releases) result in a NullPointerException.
+The pixels[] array contains the values for all the pixels in the display window. These values are of the color datatype. This array is defined by the size of the display window. For example, if the window is 100 x 100 pixels, there will be 10,000 values and if the window is 200 x 300 pixels, there will be 60,000 values. When the pixel density is set to higher than 1 with the pixelDensity() function, these values will change. See the reference for pixelWidth or pixelHeight for more information.
+
+Before accessing this array, the data must loaded with the loadPixels() function. Failure to do so may result in a NullPointerException. Subsequent changes to the display window will not be reflected in pixels until loadPixels() is called again. After pixels has been modified, the updatePixels() function must be run to update the content of the display window.
]]>
+Use stroke() to set the color of a point().
+
+Point appears round with the default strokeCap(ROUND) and square with strokeCap(PROJECT). Points are invisible with strokeCap(SQUARE) (no cap).
+
+Using point() with strokeWeight(1) or smaller may draw nothing to the screen, depending on the graphics settings of the computer. Workarounds include setting the pixel using set() or drawing the point using either circle() or square().
]]>
+
+
+
+push() stores information related to the current transformation state and style settings controlled by the following functions: rotate(), translate(), scale(), fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textMode(), textSize(), textLeading().
+
+The push() and pop() functions were added with Processing 3.5. They can be used in place of pushMatrix(), popMatrix(), pushStyles(), and popStyles(). The difference is that push() and pop() control both the transformations (rotate, scale, translate) and the drawing styles at the same time.
+]]>
+
+
+
+push() stores information related to the current transformation state and style settings controlled by the following functions: rotate(), translate(), scale(), fill(), stroke(), tint(), strokeWeight(), strokeCap(), strokeJoin(), imageMode(), rectMode(), ellipseMode(), colorMode(), textAlign(), textFont(), textMode(), textSize(), textLeading().
+
+The push() and pop() functions were added with Processing 3.5. They can be used in place of pushMatrix(), popMatrix(), pushStyles(), and popStyles(). The difference is that push() and pop() control both the transformations (rotate, scale, translate) and the drawing styles at the same time.
+]]>scale(2.0) increases the dimension of a shape by 200%.
-Transformations apply to everything that happens after and subsequent calls to the function multiply the effect. For example, calling scale(2.0) and then scale(1.5) is the same as scale(3.0). If scale() is called within draw(), the transformation is reset when the loop begins again. Using this fuction with the z parameter requires using P3D as a parameter for size(), as shown in the third example above. This function can be further controlled with pushMatrix() and popMatrix().
+Transformations apply to everything that happens after and subsequent calls to the function multiply the effect. For example, calling scale(2.0) and then scale(1.5) is the same as scale(3.0). If scale() is called within draw(), the transformation is reset when the loop begins again. Using this function with the z parameter requires using P3D as a parameter for size(), as shown in the third example above. This function can be further controlled with pushMatrix() and popMatrix().
]]>
diff --git a/content/api_en/shorten.xml b/content/api_en/shorten.xml
index 82961260a..41746c5ad 100755
--- a/content/api_en/shorten.xml
+++ b/content/api_en/shorten.xml
@@ -20,7 +20,7 @@ println(sa2); // 'sa2' now contains OH, NY
When using an array of objects, the data returned from the function must be cast to the object array's data type. For example: SomeClass[] items = (SomeClass[]) shorten(originalArray)
]]>
+Defines the dimension of the display window width and height in units of pixels. In a program that has the setup() function, the size() function must be the first line of code inside setup(), and the setup() function must appear in the code tab with the same name as your sketch folder.
-The system variables width and height are set by the parameters passed to this function. For example, running size(640, 480) will assign 640 to the width variable and 480 to the height variable. If size() is not used, the window will be given a default size of 100 x 100 pixels.
+The built-in variables width and height are set by the parameters passed to this function. For example, running size(640, 480) will assign 640 to the width variable and 480 to the height variable. If size() is not used, the window will be given a default size of 100 x 100 pixels.
The size() function can only be used once inside a sketch, and it cannot be used for resizing.
-As of Processing 3.0, to run a sketch at the full dimensions of a screen, use the fullScreen() function, rather than the older way of using size(displayWidth, displayHeight).
+As of Processing 3, to run a sketch at the full dimensions of a screen, use the fullScreen() function, rather than the older way of using size(displayWidth, displayHeight).
The maximum width and height is limited by your operating system, and is usually the width and height of your actual screen. On some machines it may simply be the number of pixels on your current screen, meaning that a screen of 800 x 600 could support size(1600, 300), since that is the same number of pixels. This varies widely, so you'll have to try different rendering modes and sizes until you get what you're looking for. If you need something larger, use createGraphics to create a non-visible drawing surface.
+The minimum width and height is around 100 pixels in each direction. This is the smallest that is supported across Windows, macOS, and Linux. We enforce the minimum size so that sketches will run identically on different machines.
+
The renderer parameter selects which rendering engine to use. For example, if you will be drawing 3D shapes, use P3D. In addition to the default renderer, other renderers are:
P2D (Processing 2D): 2D graphics renderer that makes use of OpenGL-compatible graphics hardware.
P3D (Processing 3D): 3D graphics renderer that makes use of OpenGL-compatible graphics hardware.
+FX2D (JavaFX 2D): A 2D renderer that uses JavaFX, which may be faster for some applications, but has some compatibility quirks.
+
PDF: The PDF renderer draws 2D graphics directly to an Acrobat PDF file. This produces excellent results when you need vector shapes for high-resolution output or printing. You must first use Import Library → PDF to make use of the library. More information can be found in the PDF library reference.
-As of Processing 3.0, to use variables as the parameters to size() function, place the size() function within the settings() function. There is more information about this on the settings() reference page.
+SVG: The SVG renderer draws 2D graphics directly to an SVG file. This is great for importing into other vector programs or using for digital fabrication. You must first use Import Library → SVG Export to make use of the library.
+
+As of Processing 3.0, to use variables as the parameters to size() function, place the size() function within the settings() function (instead of setup()). There is more information about this on the settings() reference page.
]]>
+
-
-With the P2D and P3D renderers, smooth(2) is the default, this is called "2x anti-aliasing." The code smooth(4) is used for 4x anti-aliasing and smooth(8) is specified for 8x anti-aliasing. The maximum anti-aliasing level is determined by the hardware of the machine that is running the software, so smooth(4) and smooth(8) will not work with every computer.
-
-The default renderer uses smooth(3) by default. This is bicubic smoothing. The other option for the default renderer is smooth(2), which is bilinear smoothing.
-
+Draws all geometry with smooth (anti-aliased) edges. This behavior is the default, so smooth() only needs to be used when a program needs to set the smoothing in a different way. The level parameter increases the amount of smoothness. This is the level of over sampling applied to the graphics buffer.
+
+With the P2D and P3D renderers, smooth(2) is the default, this is called "2x anti-aliasing." The code smooth(4) is used for 4x anti-aliasing and smooth(8) is specified for "8x anti-aliasing." The maximum anti-aliasing level is determined by the hardware of the machine that is running the software, so smooth(4) and smooth(8) will not work with every computer.
+
+The default renderer uses smooth(3) by default. This is bicubic smoothing. The other option for the default renderer is smooth(2), which is bilinear smoothing.
+
With Processing 3.0, smooth() is different than before. It was common to use smooth() and noSmooth() to turn on and off antialiasing within a sketch. Now, because of how the software has changed, smooth() can only be set once within a sketch. It can be used either at the top of a sketch without a setup(), or after the size() function when used in a sketch with setup(). The noSmooth() function also follows the same rules.
+
+When smooth() is used with a PGraphics object, it should be run right after the object is created with createGraphics(), as shown in the Reference in the third example.
]]>
When splicing an array of objects, the data returned from the function must be cast to the object array's data type. For example: SomeClass[] items = (SomeClass[]) splice(array1, array2, index)
]]>
-If the result is a set of numbers, you can convert the String[] array to to a float[] or int[] array using the datatype conversion functions int() and float(). (See the second example above.)
+If the result is a set of numbers, you can convert the String[] array to a float[] or int[] array using the datatype conversion functions int() and float(). (See the second example above.)
The splitTokens() function works in a similar fashion, except that it splits using a range of characters instead of a specific character or sequence.
-Certain renderers may or may not seem to require loadPixels() or updatePixels(). However, the rule is that any time you want to manipulate the pixels[] array, you must first call loadPixels(), and after changes have been made, call updatePixels(). Even if the renderer may not seem to use this function in the current Processing release, this will always be subject to change.
-
-Currently, while none of the renderers use the additional parameters to updatePixels(), this may be implemented in the future.
]]>Books. Processing books cove
-
diff --git a/content/static/download.html b/content/static/download.html
new file mode 100644
index 000000000..122db5e30
--- /dev/null
+++ b/content/static/download.html
@@ -0,0 +1,334 @@
+
-
@@ -12,22 +11,22 @@ 
Books. Processing books cove
Processing: A Programming Handbook for Visual Designers,
Second Edition
Casey Reas and Ben Fry.
Published December 2014, The MIT Press. 720 pages. Hardcover.
- » Order from MIT Press
+ » Order from MIT Press
» Order from Amazon
The second edition of the Handbook has been thoroughly updated, influenced by the seven years of Processing being taught in classrooms, computer labs, and studios since the first edition. Every chapter has been revised, and added chapters introduce new ways to work with data and geometry. New “synthesis” chapters offer discussion and worked examples of such topics as sketching with code, modularity, and algorithms. Interviews have been added that cover a wider range of projects and history. “Extension” chapters are now offered online so they can be updated to keep pace with technological developments in such fields as computer vision and electronics.
- If you are an educator, you can request a desk/exam copy from the MIT Press website.
+ If you are an educator, you can request a desk/exam copy from the MIT Press website.
+
+
-
-
+
+
+ 
@@ -38,7 +37,7 @@
Books. Processing books cove
» Order Print/EBook from O'Reilly
» Order from Amazon.com
- This casual book is a concise introduction to Processing and interactive computer graphics. Written by the founders of Processing, it takes you through the learning process one step at a time to help you grasp core programming concepts. You'll learn how to sketch with code -- creating a program with a few lines of code, observing the result, and then adding to it. It was written to help reader:
+ This casual book is a concise introduction to Processing and interactive computer graphics. Written by the founders of Processing, it takes you through the learning process one step at a time to help you grasp core programming concepts. You'll learn how to sketch with code -- creating a program with a few lines of code, observing the result, and then adding to it. It was written to help readers:
Books. Processing books cove
+
+
+
+
+
+
+ 
+
+
+ Andrés Colubri.
+ Published 2017, Apress. 381 pages. Paperback.
+ » Order Print/EBook from Apress
+ » Order Print from Amazon
+
+ Learn how to use the Processing programming language and environment to create Android applications with ease. This book covers the basics of the Processing language, allowing users to effectively program interactive graphics in 2D and 3D. It also details the application of these techniques to different types of Android devices (smartphones, tablets, wearables and smartwatches).
+
+ Processing for Android walks you through the steps of taking an initial idea to a final app. With this book, you will be able to write engaging apps with interactive visuals driven by motion and location information obtained from the device’s sensors; including health data from the wearer, like step count and heart rate.
+
+ An advantage of Processing for Android over more complex programming environments is the ability for users to focus on the interactions and visual output of their code rather than in the implementation details of the Android platform. This book goes through a comprehensive series of hand-on projects, ranging from simple sketches to more complex projects involving sensors and integration with larger apps. It also covers important aspects such as exporting your Processing projects as signed apps are ready to upload to the Google Play store and be share with the world!
+
@@ -62,7 +85,7 @@
@@ -96,9 +119,61 @@ Books. Processing books cove
Learning Processing, Second Edition: A Beginner's Guide to Programming Images, Animation, and Interaction
+
Daniel Shiffman.
Published August 2015, Morgan Kaufmann. 564 pages. Paperback.
- » Order from Amazon.com
+ » Order from Amazon.com
The second edition of Learning Processing has been updated for compatibility with Processing 3 and includes several new chapters of content including video, sound, data visualization, and networking. For more, visit the Learning Processing website.
@@ -73,7 +96,7 @@ Books. Processing books cove
If you are an educator, you can request a desk/exam copy from the Elsevier website.
- Books. Processing books cove
How can we capture the unpredictable evolutionary and emergent properties of nature in software? How can understanding the mathematical principles behind our physical world help us to create digital worlds? This book focuses on a range of programming strategies and techniques behind computer simulations of natural systems, from elementary concepts in mathematics and physics to more advanced algorithms that enable sophisticated visual results. Readers will progress from building a basic physics engine to creating intelligent moving objects and complex systems, setting the foundation for further experiments in generative design. Subjects covered include forces, trigonometry, fractals, cellular automata, self-organization, and genetic algorithms.
-
+
+
+
+
+
+
+
+
+ 
Coding Art: The Four Steps to Creative Programming with the Processing Language
+
+ Yu Zhang, Mathias Funk.
+ Published January 2021, Apress. 280 pages. Paperback.
+ » Order from Apress
+ » Order from Amazon
+
+
+ The authors write, "Finally, a book on creative programming, written directly for artists and designers! Rather than following a computer science curriculum, this book is aimed at creatives who are working in the intersection of design, art, and education. In this book you'll learn to apply computation into the creative process by following a four-step process, and through this, land in the cross section of coding and art, with a focus on practical examples and relevant work structures. You'll follow a real-world use case of computation art and see how it relates back to the four key pillars, and addresses potential pitfalls and challenges in the creative process. All code examples are presented in a fully integrated Processing example library, making it easy for readers to get started."
+
+
+
+
+
+
+
+
+
+ 
Pro Processing for Images and Computer Vision with OpenCV
+
+ Bryan WC Chung.
+ Published 2017, APress. Paperback, eBook.
+ » Order from APress
+
+ The Publisher writes, "Pro Processing for Images and Computer Vision with OpenCV is a step-by-step training tool that guides you through a series of worked examples in linear order. Each chapter begins with a basic demonstration, including the code to recreate it on your own system. Then comes a creative challenge by which to engage and develop mastery of the chapter’s topic. The book also includes hints and tips relating to visual arts, interaction design, and industrial best practices. This book is intended for any developer of artistic and otherwise visual applications, such as in augmented reality and digital effects, with a need to manipulate images, and to recognize and manipulate objects within those images. The book is specifically targeted at those making use of the Processing language that is common in artistic fields, and to Java programmers because of Processing’s easy integration into the Java programming environment."
+
+
+
+
+
+
+
+
+
+ 
Programming 101: The How and Why of Programming Revealed Using the Processing Programming Language
+
+ Jeanine Meyer.
+ Published 2018, APress. Paperback, eBook.
+ » Order from Apress
+
+ The Publisher writes, "Understand the importance of programming, even if you’ve never programmed before! This book will teach you the basics of programming using the Processing programming language. You will create your own Processing sketches, using personal images, themes, or hobbies that you enjoy. The chapters in the book will demonstrate the process of programming, starting with formulating an idea, planning, building on past projects, and refining the work, similar to writing an essay or composing a song. This approach will guide you to make use of logic and mathematics to produce beautiful effects. The term for program in Processing is sketch, though the sketches featured in this book are far more than static drawings; they incorporate interaction, animation, video, audio, and accessing files on the local computer and on the Web. Technical features are introduced and explained in the context of complete examples: games (Snake, Hangman, jigsaw, slingshot), making a collage of family images and video clips, preparing directions for folding an origami model, rotating objects in 3D, and others."
+
@@ -115,10 +190,9 @@ Books. Processing books cove
The O'Reilly website says, "How you can take advantage of data that you might otherwise never use? With the help of a powerful new programming environment [Processing], this book helps you represent data accurately on the Web and elsewhere, complete with user interaction, animation, and more. You'll learn basic visualization principles, how to choose the right kind of display for your purposes, and how to provide interactive features to design entire interfaces around large, complex data sets."
Martin Wattenberg from the IBM Watson Research Center says, "This wonderfully detailed guide, by one of the masters of modern data graphics, tells you everything you need to know to code your own visualizations from scratch. Perhaps most valuable are the many examples where Fry demonstrates how to refine a bare-bones concept into a beautiful, effective finished piece. Read this book, and you'll never again be dependent on someone else's view of your data."
-
+
-
@@ -130,14 +204,14 @@ Books. Processing books cove
Generative Design
+
Hartmut Bohnacker, Benedikt Gross, Julia Laub, and Claudius Lazzeroni.
August 2012, Princeton Architectural Press. 472 pages.
- Originally published in German November 2009, Schmidt Hermann Verlag. 500 pages.
+ Originally published in German November 2009, Schmidt Hermann Verlag. 500 pages.
» Order from Amazon.com
This book is extraordinary; the design is clear and the production quality is fantastic. This is the design book about Processing that we've hoped for. Unlike most other Processing books, it doesn't discuss programming basics so it's free to start with exciting examples. The publisher promotes, "Generative design is a revolutionary new method of creating artwork, models, and animations from sets of rules, or algorithms. By using accessible programming languages such as Processing, artists and designers are producing extravagant, crystalline structures that can form the basis of anything from patterned textiles and typography to lighting, scientific diagrams, sculptures, films, and even fantastical buildings. Opening with a gallery of thirty-five illustrated case studies, Generative Design takes users through specific, practical instructions on how to create their own visual experiments by combining simple-to-use programming codes with basic design principles. A detailed handbook of advanced strategies provides visual artists with all the tools to achieve proficiency. Both a how-to manual and a showcase for recent work in this exciting new field, Generative Design is the definitive study and reference book that designers have been waiting for."
More information about buying this book in German, as well as the complete source code for the examples, are at the book's website.
-
@@ -150,7 +224,7 @@
Books. Processing books cove
alt="The SparkFun Guide to Processing"/>
The SparkFun Guide to Processing
+
Derek Runberg.
- 2015, No Starch Press. 232 pages.
+ 2015, No Starch Press. 232 pages. Paperback.
» Order from Amazon.com
The publisher writes, "The SparkFun Guide to Processing teaches you to craft your own digital artwork and even combine it with hardware—no prior programming experience required. Over the course of the book, you’ll learn the basics by drawing simple shapes, move on to photo editing and video manipulation, and ultimately affect the physical world by using Processing with an Arduino."
@@ -163,7 +237,7 @@ Books. Processing books cove
@@ -171,6 +245,34 @@
+ Books. Processing books cove
+
+
+
+ 
Processing: An Introduction to Programming
+
+ Jeffrey L. Nyhoff, Larry R. Nyhoff.
+ Published May 2017, CRC Press. 544 pages. eBook, Paperback.
+ » Order from CRC Press
+
+ » Order from Amazon.com
+
+ The publisher writes, "The book uses Processing’s capabilities for graphics and interactivity in order to create examples that are simple, illustrative, interesting, and fun. It is designed to appeal to a broad range of readers, including those who want to learn to program to create digital art, as well as those who seek to learn to program to process numerical information or data. It can be used by students and instructors in a first course on programming, as well as by anyone eager to teach them self to program."
+
+ The publisher lists:
+
+
+
+
+
+
+
-
@@ -209,13 +311,11 @@ 
Books. Processing books cove
This book has a different perspective from the others because of Glassner's deep experience in computer graphics. His bio reads, "Dr. Andrew Glassner is a writer-director, and a consultant in story structure, interactive fiction, and computer graphics. He started working in 3D computer graphics in 1978, and has carried out research at the NYIT Computer Graphics Lab, Case Western Reserve University, the IBM TJ Watson Research Lab, the Delft University of Technology, Bell Communications Research, Xerox PARC, and Microsoft Research... He is also a well-known writer, and has published numerous technical papers and books on topics ranging from 3D modeling, rendering, and animation to digital sound synthesis. His book '3D Computer Graphics: A Handbook for Artists and Designers' has taught a generation of artists through two editions and three languages. Glassner created and edited the 'Graphics Gems' series and created and wrote several chapters in the book 'An Introduction to Ray Tracing'. He wrote the two-volume text 'Principles of Digital Image Synthesis'."
-
- 
Processing: Creative Coding and Computational Art (Foundation)
@@ -227,11 +327,10 @@ Books. Processing books cove
The Friends of Ed website says, "This book is written especially for artists, designers, and other creative professionals and students exploring code art, graphics programming, and computational aesthetics. The book provides a solid and comprehensive foundation in programming, including object-oriented principles, and introduces you to the easy-to-grasp Processing language, so no previous coding experience is necessary. The book then goes through using Processing to code lines, curves, shapes, and motion, continuing to the point where you'll have mastered Processing and can really start to unleash your creativity with realistic physics, interactivity, and 3D! In the final chapter, you'll even learn how to extend your Processing skills by working directly with the powerful Java programming language, the language Processing itself is built with." (Quote from the Friends of Ed website)
-
+
-
-
-
+ The O'Reilly website says, "Make cool stuff. If you're a designer or artist without a lot of programming experience, this book will teach you to work with 2D and 3D graphics, sound, physical interaction, and electronic circuitry to create all sorts of interesting and compelling experiences -- online and off. Programming Interactivity explains programming and electrical engineering basics, and introduces three freely available tools created specifically for artists and designers: Processing, Arduino, and OpenFrameworks."
+
+
+
+
- 
Programming Interactivity
+ Programming Interactivity
-
Joshua Noble.
Published January 2012, O'Reilly. 728 pages. Paperback.
» Order from Amazon.com
- The O'Reilly website says, "Make cool stuff. If you're a designer or artist without a lot of programming experience, this book will teach you to work with 2D and 3D graphics, sound, physical interaction, and electronic circuitry to create all sorts of interesting and compelling experiences -- online and off. Programming Interactivity explains programming and electrical engineering basics, and introduces three freely available tools created specifically for artists and designers: Processing, Arduino, and OpenFrameworks."
-
@@ -274,10 +372,12 @@ Books. Processing books cove
-
- 
Generative Art
+
+
+
+
+
+
+
+
+ Generative Art
-
Matt Pearson.
Published March 2011, Manning Publications. 300 pages. Paperback.
» Order from Amazon.com
@@ -290,8 +390,9 @@
Books. Processing books cove
@@ -300,21 +401,44 @@
- Books. Processing books cove
-
- 
Algorithms for Visual Design Using the Processing Language
+
- Kostas Terzidis.
- Published May 2009, Wiley. 384 Pages. Hardcover.
- » Order from Amazon.com
-
- The Wiley website says, "this book offers a series of generic procedures that can function as building blocks and encourages you to then use those building blocks to experiment, explore, and channel your thoughts, ideas, and principles into potential solutions. The book covers such topics as structured shapes, solid geometry, networking and databases, physical computing, image processing, graphic user interfaces, and more."
+
-
+
+
+
+
+ Algorithms for Visual Design Using the Processing Language
+ Kostas Terzidis.
+ Published May 2009, Wiley. 384 Pages. Hardcover.
+ » Order from Amazon.com
+
+ The Wiley website says, "this book offers a series of generic procedures that can function as building blocks and encourages you to then use those building blocks to experiment, explore, and channel your thoughts, ideas, and principles into potential solutions. The book covers such topics as structured shapes, solid geometry, networking and databases, physical computing, image processing, graphic user interfaces, and more."
+
-
+
+
+
+
+
-
+
+
+
+ Data-driven Graphic Design: Creative Coding for Visual Communication
+
+ Andrew Richardson.
+ Published January 2016, Bloomsbury. 224 Pages. Paperback.
+ » Order from Amazon.com
+
+ The book description reads, "Data-driven Graphic Design introduces the creative potential of computational data and how it can be used to inform and create everything from typography, print and moving graphics to interactive design and physical installations. Using code as a creative environment allows designers to step outside the boundaries of commercial software tools, and create a set of unique, digitally informed pieces of work. The use of code offers a new way of thinking about and creating design for the digital environment."
+
+
@@ -360,7 +484,7 @@ Books. Processing books cove
-
+
@@ -422,20 +546,65 @@ Books. Processing books cove
+
+
+
+ 
+
+
A Holistic Guide
+ Penny de Byl
+ Published May 2017, CreateSpace Independent Publishing Platform, 386 pages. Paperback
+ » Order Print/eBook from Amazon
+ » Order from iBooks
+
+ This book started as a set of tutorials for university level multimedia students to introduce them to computer programming through the development of artworks. It's therefore presented in a non-threatening way that will ease the reader into programming and has been written for absolute beginners who want to learn to program. It approaches coding through a unique combination of teaching programming while keeping in mind the principles of design and mathematics.
+
+ The chapters are organised to weave together programming functionality and design principles presenting one concept at a time, with multiple hands on exercises in each chapter.
+
+
+ Additional information available at http://holistic3d.com/creating-procedural-artworks/
+ Experience an example of the artworks created at http://holistic3d.com/processing
+
+
-
+
+
+
+
+
+
+
+ 
O Código Transcendente: Uma Introdução Prática à Programação e Arte Gerativa
+
+ Mateus Berruezo.
+ Published December 2019. 270 pages. PDF, Web.
+ Text in Portuguese.
+ » Download
+ » Read online
+
+
+ Este livro é um guia de programação com enfoque prático considerando o contexto da arte gerativa e do pensamento computacional. Ele conta com explicações e exemplos visuais cuidadosamente projetados para serem de valor tanto para programadores quanto artistas. As aplicações e estudos de caso foram direcionados para a linguagem Processing cuja própria filosofia segue o princípio da exploração do artístico através do código.
+
+
+
+
+
@@ -453,7 +622,7 @@ 
Einführung ins Programmieren mit Processing
- Matthias Wolf.
- Published August 2013. 178 pages. PDF, Paperback.
- » Order Print/EBook from lulu.com
-
-
+ Published August 2013. 178 pages. PDF, Paperback.
+ Text in German.
+ » Order Print/EBook from lulu.com
+
+ Books. Processing books cove
Text in German.
The OReilly.de site writes, "Processing ist eine auf Grafik, Simulation und Animation spezialisierte objektorientierte Programmiersprache, die besonders für Menschen mit wenig Programmiererfahrung geeignet ist. Deshalb eignet sie sich vor allem für Künstler, Bastler und Programmiereinsteiger. Die aus Java abgeleitete Sprache wurde geschaffen, um schnell und effektiv mit relativ wenig Aufwand zu beeindruckenden Ergebnissen zu kommen. Processing führt den Leser zügig in die Programmieressentials ein und geht dann unmittelbar zur Programmierung grafisch anspruchsvoller Anwendungen über. Spielerisch wird dem Leser die 2D- und 3D-Programierung, Textrendering, die Bildbearbeitung und sogar die Videomanipulation nahe gebracht."
-
+
@@ -472,6 +641,7 @@ Books. Processing books cove
Processing - eine Einführung in die Programmierung
Andres Wanner (Chapters by Hans Peter Wyss, Roland Broennimann and Roman Schnyder).
Version 1.1, Published May 2010, Lulu Press. 83 pages. Softcover.
+ Text in German.
Order from lulu.com
Book website
@@ -512,59 +682,69 @@ Books. Processing books cove
+
+
+
+
+
+ 
+ Il Codice dei Cibernetici: Introduzione alla Computer Art con Processing
+
+ Antonio Rollo
+ Published December 2015, Oistros Edizioni. 320 pages. Softcover.
+ Text in Italian.
+
+ During the 50‘s ”era of cybernetics“, computer entered into the history of art simultaneously in different parts of the world. Art and science were in great turmoil. Science, with its theories and experiments, was approaching artificially mimicking both natural phenomena, such as light and sound, and the human phenomena of language and communication. Art, with its aesthetic and exhibitions, had transcended the boundaries of the avant-garde. Now, with the computer, it was confronting a reality that challenged ”the where“ and ”the how“ of doing art and the very meaning of ”masterpiece“. Antonio Rollo takes us on a tour of these seminal works from his unique perspective of the artist, through the code!
+
+
+ There's additional information on the publisher's website.
+
+
+
+
+
+
+
+
+

Built with Processing
+ There's additional information on the publisher's website.
+
Published March 2007, BNN. 232 pages. Softcover.
- Text in Japanese
+ Text in Japanese.
Note from Casey: "I received a copy of this book from the authors on a recent trip to Japan. It's a beautifully produced full-color book with sections introducing Processing, featuring work created with Processing (many are from the Exhibition section of the Processing website), and introducing programming through progressively complicated examples. The majority of the book is an introduction to programming. There are many good examples and the code is color-coded like in the Processing Environment. This book is less comprehensive than the Greenberg and Reas/Fry books, but it appears to be a good, brief introduction."
- There's additional information on the publisher's website.
+
+
-
+ Итак, представляю вашему вниманию книгу “Программирование для дизайнеров”. Книга вышла на русском языке при поддержке Европейского Союза, организации Темпус по проекту 544083 “Enhancement of Russian creative education: new Master program in Digital Arts in line with EU standards [ENMDA]”. Ее можно найти в библиотеках страны и несколько копий будет находиться в библиотеке политехнического университета. Выражаю благодарность кафедре инженерной графики и дизайна за помощь в издании, некоторые страницы печатного издания цветные, что приятно."
+
+
+
-
- Processing is also discussed through examples and projects in the following books:
-
-
-
-
-
- 10 PRINT CHR$(205.5+RND(1)); : GOTO 10By Nick Montfort, Patsy Baudoin, John Bell, Ian Bogost, Jeremy Douglass, Mark C. Marino, Michael Mateas, Casey Reas, Mark Sample, Noah Vawter. Examples use Processing to explore a modern interpretation of a 1982 Commodore 64 program.
-
-
-
- Make: Getting Started with Arduino
By Massimo Banzi. Examples use Processing to communicate with an Arduino board.
-
-
-
- Building Wireless Sensor Networks: with ZigBee, XBee, Arduino, and Processing
By Robert Faludi. Network examples use Processing.
-
-
-
- Physical Computing: Sensing and Controlling the Physical World with Computers
- By Dan O'Sullivan and Tom Igoe. Examples using Processing for RS-232 communication and
- computer vision.
-
+
+
+
+
+ Programming for Artists
-
+ Pavel A. Orlov.
+ Published 2015. 248 Pages. PDF.
+ Text in Russian.
+ » Download the book
-
- Aesthetic Computing.
- Edited by Paul Fishwick. Casey Reas and Ben Fry contributed a chapter entitled
- "Processing Code: Programming within the Context of Visual Art and Design."
-
+ The author's website reads, "Летом 2015 года мне удалось подготовить к выходу в свет новую книгу, посвященную программированию для художников и дизайнеров. Книга рассматривает среду Processing как одну из самых простых и доступных в освоении. Я акцентировал внимание на том, что каждый человек, знакомый с азами математики, может научиться использовать программирование для своих творческих задач. Конечно, я говорю про активных дизайнеров, которые не боятся использовать и изучать новые для себя инструменты.
-
- Hacking Roomba: ExtremeTech
By Tod E. Kurt. Processing is introduced and used to design an application to control a Roomba (a robot vacuum cleaner).
-
+ Часто я слышу вопросы: “Зачем художнику нужно программировать? Почему нельзя просто взять и нарисовать от руки? А что, фотошоп отменили? Неужели у художников есть математическая логика?” Мне эти вопросы кажутся замечательными и напоминают художника в момент появления фотографии, когда художники спорили с фотографами примерно теми же словами, разве что слова фотошоп еще не было. И сейчас у нас развивается искусство фотографии бурным потоком. Более развернутый ответ вы можете найти во вступительной статье.
- Analog In, Digital Out
By Brendan Dawes. Numerous projects created with Processing are illustrated and discussed.
Download Processing. Processing is available for Linux, Mac OS X, and Windows. Select your choice to download the software below.
+
+
+
+
+
+ Stable Releases
+ Pre-Releases
+
+ Donate
-
-
-
-
diff --git a/content/static/foundation-site/fellowships.html b/content/static/foundation-site/fellowships.html
deleted file mode 100644
index 8359f116c..000000000
--- a/content/static/foundation-site/fellowships.html
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
- Fellowships
-
-
-
-
diff --git a/content/static/foundation-site/imgs/JH_bio.png b/content/static/foundation-site/imgs/JH_bio.png
deleted file mode 100644
index 1bc2b1b1a..000000000
Binary files a/content/static/foundation-site/imgs/JH_bio.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/ben_worksample_sm.png b/content/static/foundation-site/imgs/ben_worksample_sm.png
deleted file mode 100644
index 23d723fe3..000000000
Binary files a/content/static/foundation-site/imgs/ben_worksample_sm.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/dan_worksample_sm.png b/content/static/foundation-site/imgs/dan_worksample_sm.png
deleted file mode 100644
index a29e3dba9..000000000
Binary files a/content/static/foundation-site/imgs/dan_worksample_sm.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/greg_worksample1.png b/content/static/foundation-site/imgs/greg_worksample1.png
deleted file mode 100644
index 61ab8c712..000000000
Binary files a/content/static/foundation-site/imgs/greg_worksample1.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/greg_worksample2.png b/content/static/foundation-site/imgs/greg_worksample2.png
deleted file mode 100644
index d1411648b..000000000
Binary files a/content/static/foundation-site/imgs/greg_worksample2.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/greg_worksample3.png b/content/static/foundation-site/imgs/greg_worksample3.png
deleted file mode 100644
index fb5a1e0ae..000000000
Binary files a/content/static/foundation-site/imgs/greg_worksample3.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/john_worksample_sm.png b/content/static/foundation-site/imgs/john_worksample_sm.png
deleted file mode 100644
index 21c3ad277..000000000
Binary files a/content/static/foundation-site/imgs/john_worksample_sm.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/lauren_worksample1.png b/content/static/foundation-site/imgs/lauren_worksample1.png
deleted file mode 100644
index c6aed5299..000000000
Binary files a/content/static/foundation-site/imgs/lauren_worksample1.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/lauren_worksample2.png b/content/static/foundation-site/imgs/lauren_worksample2.png
deleted file mode 100644
index 71a59024e..000000000
Binary files a/content/static/foundation-site/imgs/lauren_worksample2.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/lauren_worksample3.png b/content/static/foundation-site/imgs/lauren_worksample3.png
deleted file mode 100644
index dd32868d8..000000000
Binary files a/content/static/foundation-site/imgs/lauren_worksample3.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/lauren_worksample_sm.png b/content/static/foundation-site/imgs/lauren_worksample_sm.png
deleted file mode 100644
index 50e7fee7b..000000000
Binary files a/content/static/foundation-site/imgs/lauren_worksample_sm.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/processing-foundation-logo.svg b/content/static/foundation-site/imgs/processing-foundation-logo.svg
deleted file mode 100644
index 76b2e09a2..000000000
--- a/content/static/foundation-site/imgs/processing-foundation-logo.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/content/static/foundation-site/imgs/processing-logo.svg b/content/static/foundation-site/imgs/processing-logo.svg
deleted file mode 100644
index 6eaebe60a..000000000
--- a/content/static/foundation-site/imgs/processing-logo.svg
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
diff --git a/content/static/foundation-site/imgs/processing-site.png b/content/static/foundation-site/imgs/processing-site.png
deleted file mode 100644
index 615c4b9c0..000000000
Binary files a/content/static/foundation-site/imgs/processing-site.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/reas_worksample_sm.png b/content/static/foundation-site/imgs/reas_worksample_sm.png
deleted file mode 100644
index cbf6befe7..000000000
Binary files a/content/static/foundation-site/imgs/reas_worksample_sm.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/search-f.svg b/content/static/foundation-site/imgs/search-f.svg
deleted file mode 100644
index 8066b89ab..000000000
--- a/content/static/foundation-site/imgs/search-f.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
diff --git a/content/static/foundation-site/imgs/wilm_worksample1.png b/content/static/foundation-site/imgs/wilm_worksample1.png
deleted file mode 100644
index 74514bb21..000000000
Binary files a/content/static/foundation-site/imgs/wilm_worksample1.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/wilm_worksample2.png b/content/static/foundation-site/imgs/wilm_worksample2.png
deleted file mode 100644
index 33a021566..000000000
Binary files a/content/static/foundation-site/imgs/wilm_worksample2.png and /dev/null differ
diff --git a/content/static/foundation-site/imgs/wilm_worksample3.png b/content/static/foundation-site/imgs/wilm_worksample3.png
deleted file mode 100644
index f009d61fe..000000000
Binary files a/content/static/foundation-site/imgs/wilm_worksample3.png and /dev/null differ
diff --git a/content/static/foundation-site/mission.html b/content/static/foundation-site/mission.html
deleted file mode 100644
index b26fe4bd7..000000000
--- a/content/static/foundation-site/mission.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
- 

-
-
-
-
-Wilm Thoben is a sound artist and researcher. He is currently working on his dissertation about the 1960s art and technology group E.A.T. His work deals with perception and definition of space or the abstraction of everyday life. See more of Thoben's work at wilmthoben.com.
-
-

-
-
-
-
-Lauren McCarthy is an artist and programmer based in Brooklyn, NY. She is adjunct faculty at RISD and NYU ITP, a researcher in residence at ITP, and recently a resident at Eyebeam. She holds an MFA from UCLA and a BS Computer Science and BS Art and Design from MIT. Her work explores the structures and systems of social interactions, identity, and self-representation, and the potential for technology to mediate, manipulate, and evolve these interactions. She is fascinated by the slightly uncomfortable moments when patterns are shifted, expectations are broken, and participants become aware of the system. See more of McCarthy's work at lauren-mccarthy.com.
-
-
-

-
-
-
-
-Greg Borenstein is an artist, technologist, and teacher. He creates illusions for humans and machines. His work explores computer vision, machine learning, game design, visual effects, and drawing as media for storytelling and design. Greg is a graduate of the NYU Interactive Telecommunications Program and has worked for firms such as Makerbot and Berg London. He is the author of a book for O'Reilly about the Microsoft Kinect, titled: Making Things See: 3D vision with Kinect, Processing, Arduino, and MakerBot. He's currently a researcher in the Playful Systems Group at the MIT Media Lab. See more of Borenstein's work at gregborenstein.com.
- Mission
-
-
-
-
diff --git a/content/static/foundation-site/overview.html b/content/static/foundation-site/overview.html
deleted file mode 100644
index a7addf80c..000000000
--- a/content/static/foundation-site/overview.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
diff --git a/content/static/foundation-site/patrons.html b/content/static/foundation-site/patrons.html
deleted file mode 100644
index da4035913..000000000
--- a/content/static/foundation-site/patrons.html
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
- Patrons
-
-
-
-
diff --git a/content/static/foundation-site/people.html b/content/static/foundation-site/people.html
deleted file mode 100644
index 67311af77..000000000
--- a/content/static/foundation-site/people.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Board of Directors
-
-
-
-
-
-
-
-
-
-
-
- Ben Fry is principal of Fathom, a design and software consultancy located in Boston. He received his doctoral degree from the Aesthetics + Computation Group at the MIT Media Laboratory, where his research focused on combining fields such as computer science, statistics, graphic design, and data visualization as a means for understanding information. After completing his thesis, he spent time developing tools for visualization of genetic data as a postdoc with Eric Lander at the Eli and Edythe L. Broad Institute of MIT and Harvard. During the 2006-2007 school year, Ben was the Nierenberg Chair of Design for the Carnegie Mellon School of Design. In 2011, he won the National Design Award for Interaction Design from the Cooper-Hewitt. With Casey Reas, Fry initiated Processing in 2001.
-
-
-
-
-
-
-
-
- Daniel Shiffman works as an Associate Arts Professor at the Interactive Telecommunications Program at NYU's Tisch School of the Arts. Originally from Baltimore, Daniel received a BA in Mathematics and Philosophy from Yale University and a Master's Degree from the Interactive Telecommunications Program. He works on developing tutorials, examples, and libraries for Processing, the open source programming language and environment created by Casey Reas and Ben Fry. He is the author of Learning Processing: A Beginner's Guide to Programming Images, Animation, and Interaction and The Nature of Code (self-published via Kickstarter), an open source book about simulating natural phenomenon in Processing.
-
-
-
-
-
-
-
-
- Lauren McCarthy is an artist based in Brooklyn, NY. She is full-time faculty at NYU ITP, and recently a resident at CMU STUDIO for Creative Inquiry and Eyebeam. She holds an MFA from UCLA and a BS Computer Science and BS Art and Design from MIT. Her work explores current systems and structures for being a person and interacting with other people.
-
-
-
-
-
-
-
-
- Casey Reas is an artist and educator based in Los Angeles. He has exhibited, screened, and performed his work internationally in galleries and museums around the world. Reas is a professor at the University of California, Los Angeles. He holds a masters degree from the Massachusetts Institute of Technology in Media Arts and Sciences as well as a bachelors degree from the School of Design, Architecture, Art, and Planning at the University of Cincinnati. With Ben Fry, Reas initiated Processing in 2001.
-
- Assistant Director
-
-
-
-
-
-
-
-
-
-
-
-
-
- Johanna Hedva is an artist and writer whose practice manifests in a wide range of projects, from performances of Ancient Greek plays rewritten to respond to feminist and queer political discourse, to poetry, novels, criticism, and theory. She's got an MA in Aesthetics and Politics, and an MFA in Art, from California Institute of the Arts, and has been an artist-in-residence at Headlands Center for the Arts, and writer-in-residence at the Armory Center for the Arts. Her work with the Processing Foundation is motivated by her political and social commitments to gender and racial diversity in technology and the arts; open-source philosophy and practice; and promoting the attenuation of the boundaries between creative and thought-making disciplines of all kinds.
-
- Advisor
-
-
-
-
diff --git a/content/static/foundation-site/projects.html b/content/static/foundation-site/projects.html
deleted file mode 100644
index 926060e62..000000000
--- a/content/static/foundation-site/projects.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
- John Maeda is currently a Design Partner at Kleiner Perkins Caufield & Byers. He was the President of the Rhode Island School of Design from 2008 to 2013, is a recipient of the National Design Award, and is represented in the permanent collection of the Museum of Modern Art. Beginning in 1996, lasting for 13 years, he was a Professor at MIT, where he served as an Associate Director of Research at the MIT Media Lab and was responsible for managing research relationships with 70+ industrial organizations. He received a Ph.D. in Design Science from the University of Tsukuba Institute of Art and Design in Japan. In May 2003, he received an Honorary Doctorate of Fine Arts from the Maryland Institute of Contemporary Art. He received an MBA from Arizona State University in May 2006.
-
- Projects
-
-
-
-
diff --git a/content/static/foundation-site/reports.html b/content/static/foundation-site/reports.html
deleted file mode 100644
index bd1dff641..000000000
--- a/content/static/foundation-site/reports.html
+++ /dev/null
@@ -1,176 +0,0 @@
-
-
-
-
-
- Processing
-
-
-
- p5.js
-
-
-
- Processing.py
-
- Annual Reports
-
-
-
-
diff --git a/content/static/foundation.html b/content/static/foundation.html
deleted file mode 100644
index caa4c380c..000000000
--- a/content/static/foundation.html
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
- 2013 Report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Google Summer of Code
-
- 2014 Report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-2013 Report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Foundation. The Processing Foundation is an organization that develops software tools for the visual arts.
-
-
-
-
diff --git a/content/static/handbook.html b/content/static/handbook.html
index e1fbca351..27ef76ed6 100644
--- a/content/static/handbook.html
+++ b/content/static/handbook.html
@@ -6,13 +6,13 @@
-
-
-
-
-
- Overview
-
- 2013 Report
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Patrons
-
- Processing: A Programming Handbook
Published December 2014, The MIT Press.
720 Pages. Hardcover.
- » Order from MIT Press
+ » Order from MIT Press
» Order from Amazon
» Download Examples
» Errata
- If you are an educator, you can request a desk/exam copy from the MIT Press website.
+ If you are an educator, you can request a desk/exam copy from the MIT Press website.
Processing: A Programming Handbook
Overview. A short introducti
Education
@@ -27,7 +24,7 @@ Education
Culture
@@ -45,21 +42,23 @@ Research
Foundation
History
People. Processing is a comm
diff --git a/content/static/support.html b/content/static/support.html
new file mode 100644
index 000000000..2a8f77f05
--- /dev/null
+++ b/content/static/support.html
@@ -0,0 +1,48 @@
+
+
+
+ Project Leads
Ben Fry and Casey Reas
started Processing in Spring 2001 and continue to obsessively work on it. In 2012, they started the Processing Foundation along with Dan Shiffman, who formally joined as a third project lead.
- Andres Colubri (Boston), OpenGL / Video
- Florian Jenett (Frankfurt), Forum
- Elie Zananiri (Montreal), Contributed Libraries / Tools
- Scott Murray (San Francisco), Website / Reference / UI
+ Developers
+ Andres Colubri (Boston), OpenGL / Video
+ Elie Zananiri (New York), Contributed Libraries / Tools
+ Samuel Pottinger (San Francisco), Processing Core
- The core Processing software is augmented by libraries and tools contributed through the community.
- These inventive extensions are a bright future for the project. We have a list of
- Contributed Libraries and
+ The core Processing software is augmented by libraries and tools contributed through
+ the community. These inventive extensions are a bright future for the project. We have a
+ list of Contributed Libraries and
Contributed Tools posted online.
- These contributions can't be underestimated. For example, see how
- Karsten Schmidt (London) has transformed Processing
- through the toxiclibs library and how
- Damien Di Fede (Austin) has extended the project
- into programming sound through his minim
- library.
-
- Lauren McCarthy (New York), Spring/Summer/Fall 2013
- Greg Borenstein (New York), Spring/Summer 2013
- Wilm Thoben (Los Angeles), Fall 2013/Winter 2014
+ These contributions can't be underestimated. For example, see how Karsten Schmidt (London) has
+ transformed Processing through the toxiclibs library and how Damien Di Fede (Austin) has extended
+ the project into programming sound through his minim library.
+ Alumni
+ Jakub Valtar (Brno), Processing Core
+ Scott Garner (New York), Hello Processing Website
+ Scott Murray (San Francisco), Website / Reference / UI
+ Gottfried Haider (Los Angeles), Processing for Pi
+ Florian Jenett (Frankfurt), Forum
+ Jamie Kosoy (San Francisco), Website
+ Manindra Moharana (San Diego), PDE / Core
+ James Grady (Boston), Visual Design
+
+
Patrick Hebron, Video Library (Summer 2011)
Peter Kalauskas, Library/Tool/Mode Install Utility (Summer, Fall 2011)
Andreas Schlegel, Libraries (Winter 2008 - Summer 2011)
Harshani Nawarathna, Processing Development Environment (Summer 2011)
Cindy Chi, Reference Editing (Summer 2011)
- Jonathan Feinberg, Parsing & Android Hacking (Spring 2011)
+ Jonathan Feinberg, Parsing & Android Hacking (Spring 2011)
Chris Lonnen, Processing Development Environment (Summer 2011)
Eric Jordan, Graphics Weapon (2007 - 2009)
Tom Carden, Processing Hacks Director (Summer 2005 - Fall 2008)
@@ -132,13 +111,9 @@ People. Processing is a comm
Burak Arikan, Turkish
-
If you're interested in buying a book about Processing,
Learning Processing, Second Edition: A Beginner's Guide to Programming Images, Animation, and Interaction
Daniel Shiffman
» More info
- » Order from Amazon.com
+ » Order from Amazon.com
+ We need your help! Please support Processing by making a donation to the Processing Foundation. Your donation contributes to software development, education resources like code examples and tutorials, Fellowships, and community events.
+
+
+
+
+
+
+
+
+
+
+
+ The Processing Foundation was established in 2012 after more than a decade of work with the Processing software. The Foundation’s mission is to promote software literacy within the visual arts, and visual literacy within technology-related fields — and to make these fields accessible to diverse communities. Our goal is to empower people of all interests and backgrounds to learn how to program and make creative work with code, especially those who might not otherwise have access to these tools and resources. You can read more about the history of Processing in the short essay "A Modern Prometheus."
+
diff --git a/content/static/tutorials/anatomy/index.html b/content/static/tutorials/anatomy/index.html
index 39423e74e..6fe27c928 100644
--- a/content/static/tutorials/anatomy/index.html
+++ b/content/static/tutorials/anatomy/index.html
@@ -61,7 +61,7 @@ Step 2: Some basic trigonometry
So, if you have a line of length r starting at (0,0) at an angle theta (θ), what are its coordinates in terms of x and y? If you know a little bit of
trigonometry, the answer is that the endpoint of the line is at (r cos θ, r sin θ). If you don’t
know trigonometry, take a look at this tutorial (a general and very light introduction to
- trigonometry), this tutorial (oriented towards Processing), and this example from chapter 13 of Learning Processing. In the following diagram, angles are drawn clockwise, which is how they are measured in Processing.
+ trigonometry), this tutorial (oriented towards Processing), and this example from chapter 13 of Learning Processing. In the following diagram, angles are drawn clockwise, which is how they are measured in Processing.
diff --git a/content/static/tutorials/android/index.html b/content/static/tutorials/android/index.html
index f339fd9ba..75a355092 100644
--- a/content/static/tutorials/android/index.html
+++ b/content/static/tutorials/android/index.html
@@ -121,7 +121,7 @@ Step Three: Running the App on a Device
Daniel Shiffman
In the digital world, when we want to talk about a color, precision is required. Saying "Hey, can you make that circle bluish-green?" will not do. Color, rather, is defined as a range of numbers. Let's start with the simplest case: black & white or grayscale. 0 means black, 255 means white. In between, every other number—50, 87, 162, 209, and so on—is a shade of gray ranging from black to white.
-
+
@@ -40,7 +40,7 @@ Daniel Shiffman
In addition, if we draw two shapes, Processing will always use the most recently specified stroke and fill, reading the code from top to bottom.
-
+
@@ -66,7 +66,7 @@
RGB Color
-
+ Example: RGB color
background(255);
@@ -109,7 +109,7 @@
Color Transparency
-
+ Example: Alpha transparency
size(200,200);
diff --git a/content/static/tutorials/data/imgs/data_03_table.png b/content/static/tutorials/data/imgs/data_03_table.png
index d0ff43b2d..961ac434c 100644
Binary files a/content/static/tutorials/data/imgs/data_03_table.png and b/content/static/tutorials/data/imgs/data_03_table.png differ
diff --git a/content/static/tutorials/data/imgs/data_04_excel.jpg b/content/static/tutorials/data/imgs/data_04_excel.jpg
index 1406af987..c004098da 100755
Binary files a/content/static/tutorials/data/imgs/data_04_excel.jpg and b/content/static/tutorials/data/imgs/data_04_excel.jpg differ
diff --git a/content/static/tutorials/data/imgs/data_06_xml.jpg b/content/static/tutorials/data/imgs/data_06_xml.jpg
index 7a1a18035..10cadd588 100755
Binary files a/content/static/tutorials/data/imgs/data_06_xml.jpg and b/content/static/tutorials/data/imgs/data_06_xml.jpg differ
diff --git a/content/static/tutorials/data/imgs/data_07_weatherxml.jpg b/content/static/tutorials/data/imgs/data_07_weatherxml.jpg
index bc65c1042..e0de2e503 100755
Binary files a/content/static/tutorials/data/imgs/data_07_weatherxml.jpg and b/content/static/tutorials/data/imgs/data_07_weatherxml.jpg differ
diff --git a/content/static/tutorials/data/imgs/fig_18_01_user_input.png b/content/static/tutorials/data/imgs/fig_18_01_user_input.png
new file mode 100755
index 000000000..e4b8f4797
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_01_user_input.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_02_filetxt.png b/content/static/tutorials/data/imgs/fig_18_02_filetxt.png
new file mode 100755
index 000000000..2e82a2f1d
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_02_filetxt.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_03_datatxt.png b/content/static/tutorials/data/imgs/fig_18_03_datatxt.png
new file mode 100755
index 000000000..33a877bcb
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_03_datatxt.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_04_bargraph.png b/content/static/tutorials/data/imgs/fig_18_04_bargraph.png
new file mode 100755
index 000000000..ef797f982
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_04_bargraph.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_05_datacsv.png b/content/static/tutorials/data/imgs/fig_18_05_datacsv.png
new file mode 100755
index 000000000..6c75a3c9c
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_05_datacsv.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_06_datacsv_grid.png b/content/static/tutorials/data/imgs/fig_18_06_datacsv_grid.png
new file mode 100755
index 000000000..77de335e7
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_06_datacsv_grid.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_07_tablebubbles.png b/content/static/tutorials/data/imgs/fig_18_07_tablebubbles.png
new file mode 100755
index 000000000..64a8e5f79
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_07_tablebubbles.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_08_rollover.png b/content/static/tutorials/data/imgs/fig_18_08_rollover.png
new file mode 100644
index 000000000..7b823a954
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_08_rollover.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_09_shaunsheep.png b/content/static/tutorials/data/imgs/fig_18_09_shaunsheep.png
new file mode 100755
index 000000000..8d5398cf2
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_09_shaunsheep.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_10_shaunsheep_sourc.png b/content/static/tutorials/data/imgs/fig_18_10_shaunsheep_sourc.png
new file mode 100755
index 000000000..b4456ba92
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_10_shaunsheep_sourc.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_11_parsing_imdb.png b/content/static/tutorials/data/imgs/fig_18_11_parsing_imdb.png
new file mode 100755
index 000000000..61acef65d
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_11_parsing_imdb.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_12_traditional_arra.png b/content/static/tutorials/data/imgs/fig_18_12_traditional_arra.png
new file mode 100644
index 000000000..402f9e213
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_12_traditional_arra.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_13_associative_arra.png b/content/static/tutorials/data/imgs/fig_18_13_associative_arra.png
new file mode 100644
index 000000000..82fe0b68f
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_13_associative_arra.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_14_concordance_viz.png b/content/static/tutorials/data/imgs/fig_18_14_concordance_viz.png
new file mode 100755
index 000000000..f60db5375
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_14_concordance_viz.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_15_xml_tree.png b/content/static/tutorials/data/imgs/fig_18_15_xml_tree.png
new file mode 100755
index 000000000..8535f1b6e
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_15_xml_tree.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_16_rss.png b/content/static/tutorials/data/imgs/fig_18_16_rss.png
new file mode 100755
index 000000000..1bdb2d482
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_16_rss.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_17_weather.png b/content/static/tutorials/data/imgs/fig_18_17_weather.png
new file mode 100755
index 000000000..f379ab30f
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_17_weather.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_18_xmlbubbles.png b/content/static/tutorials/data/imgs/fig_18_18_xmlbubbles.png
new file mode 100755
index 000000000..b58ced2a2
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_18_xmlbubbles.png differ
diff --git a/content/static/tutorials/data/imgs/fig_18_19_thread.png b/content/static/tutorials/data/imgs/fig_18_19_thread.png
new file mode 100755
index 000000000..f79c43d28
Binary files /dev/null and b/content/static/tutorials/data/imgs/fig_18_19_thread.png differ
diff --git a/content/static/tutorials/data/index-old.html b/content/static/tutorials/data/index-old.html
new file mode 100644
index 000000000..6221a4a80
--- /dev/null
+++ b/content/static/tutorials/data/index-old.html
@@ -0,0 +1,527 @@
+
+
+
diff --git a/content/static/tutorials/data/index.html b/content/static/tutorials/data/index.html
index 0df744e1b..ebafcce92 100644
--- a/content/static/tutorials/data/index.html
+++ b/content/static/tutorials/data/index.html
@@ -3,7 +3,7 @@
+
+
+
+
+ Data
+ Daniel Shiffman
+
+
+ Manipulating Strings
+
+
+String search = "def";
+String toBeSearched = "abcdefghi";
+int index = toBeSearched.indexOf(search); // The value of index in this example is 3.
+
+
+
+String alphabet = "abcdefghi";
+String sub = alphabet.substring(3,6); // The String sub is now "def".
+
+
+Splitting and Joining Strings
+
+
+// Splitting a String based on spaces
+String spaceswords = "The quick brown fox jumps over the lazy dog.";
+String[] list = split(spaceswords, " ");
+for (int i = 0; i < list.length; i++) {
+ println(list[i] + " " + i);
+}
+
+
+
+// Splitting a String based on a multiple delimiters
+String stuff = "hats & apples, cars + phones % elephants dog.";
+String[] list = splitTokens(stuff, " &,+.");
+for (int i = 0; i < list.length; i++) {
+ println(list[i] + " " + i);
+}
+
+
+
+// Calculate sum of a list of numbers in a String
+String numbers = "8,67,5,309";
+// Converting the String array to an int array
+int[] list = int(split(numbers, ','));
+int sum = 0;
+for (int i = 0; i < list.length; i++) {
+ sum = sum + list[i];
+}
+println(sum);
+
+
+
+String[] lines = {"It", "was", "a", "dark", "and", "stormy", "night."};
+
+
+
+// Manual Concatenation
+String onelongstring = "";
+for (int i = 0; i < lines.length; i++) {
+ onelongstring = onelongstring + lines[i] + " ";
+}
+
+
+
+// Using Processing's join()
+String onelongstring = join(lines," ");
+
+
+Reading and Writing Text Files
+
+
+
+
+// This code will print all the lines from the source text file.
+String[] lines = loadStrings("file.txt");
+println("there are " + lines.length + " lines");
+println(lines);
+
+
+
+
+
+int[] data;
+
+void setup() {
+ size(200,200);
+ // Load text file as a string
+ String[] stuff = loadStrings("data.txt");
+ // Convert string into an array of integers using ',' as a delimiter
+ data = int(split(stuff[0],','));
+}
+
+void draw() {
+ background(255);
+ stroke(0);
+ for (int i = 0; i < data.length; i++) {
+ fill(data[i]);
+ rect(i*20,0,20,data[i]);
+ }
+}
+
+
+
+String words = "apple bear cat dog";
+String[] list = split(words, ' ');
+
+// Writes the strings to a file, each on a separate line
+saveStrings("nouns.txt", list);
+
+
+
+PrintWriter output;
+
+void setup() {
+ // Create a new file in the sketch directory
+ output = createWriter("positions.txt");
+}
+
+void draw() {
+ point(mouseX, mouseY);
+ output.println(mouseX); // Write the coordinate to the file
+}
+
+void keyPressed() {
+ output.flush(); // Writes the remaining data to the file
+ output.close(); // Finishes the file
+ exit(); // Stops the program
+}
+
+
+Tabular Data
+
+
+
+
+String[] stuff = loadStrings("data.csv");
+
+
+
+Table table = loadTable("data.csv");
+
+
+
+Table table = loadTable("data.csv","header");
+
+
+
+
+
+int val1 = table.getInt(2, 1); // val now has the value 235
+float val2 = table.getFloat(3, 2); // val2 now has the value 44.758068
+String s = table.getString(0, 3); // s now has the value "Happy"
+
+
+
+TableRow row = table.getRow(2); // Gets the third row (index 2)
+
+
+Note in the above line of code that a Table object refers to the entire table of data while a TableRow object handles an individual row of data within the Table.
+
+Once we have the TableRow object, we can ask for data from some or all of the columns.
+
+
+int x = row.getInt("x"); // x has the value 273
+int y = row.getInt("y"); // y has the value 235
+float d = row.getFloat("diameter"); // d has the value 61.14072
+String s = row.getString("name"); // s has the value "Joyous"
+
+
+The method getRow() returns a single row from the table. If you want to grab all the rows and iterate over them you can do so with the method rows().
+
+
+for (TableRow row : table.rows()) {
+ float x = row.getFloat("x");
+ float y = row.getFloat("y");
+ float d = row.getFloat("diameter");
+ String n = row.getString("name");
+ // Do something with the data of each row
+}
+
+
+If you want to search for a select number of rows within the table, you can do so with findRows() and matchRows().
+
+
+// Update the value of column "x" to mouseX in a given TableRow.
+row.setInt("x",mouseX);
+
+
+
+// Create a new row
+TableRow row = table.addRow();
+// Set the values of that row
+row.setFloat("x", mouseX);
+row.setFloat("y", mouseY);
+row.setFloat("diameter", random(40, 80));
+row.setString("name", "new label");
+
+
+
+// If the table has more than 10 rows
+if (table.getRowCount() > 10) {
+ // Delete the first row
+ table.removeRow(0);
+}
+
+
+XML Data
+
+
+<?xml version="1.0" encoding="UTF-8"?>
+<students>
+ <student>
+ <id>001</id>
+ <name>Daniel Shiffman</name>
+ <phone>555-555-5555</phone>
+ <email>daniel@shiffman.net</email>
+ <address>
+ <street>123 Processing Way</street>
+ <city>Loops</city>
+ <state>New York</state>
+ <zip>01234</zip>
+ </address>
+ </student>
+ <student>
+ <id>002</id>
+ <name>Zoog</name>
+ <phone>555-555-5555</phone>
+ <email>zoog@planetzoron.uni</email>
+ <address>
+ <street>45.3 Nebula 5</street>
+ <city>Boolean City</city>
+ <state&tt;Booles</state>
+ <zip>12358</zip>
+ </address>
+ </student>
+</students>
+
+
+
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0">
+ <channel>
+ <item>
+ <title>Conditions for New York, NY at 3:51 pm EST</title>
+ <geo:lat>40.67</geo:lat>
+ <geo:long>-73.94</geo:long>
+ <link>http://xml.weather.yahoo.com/forecast/USNY0996_f.html</link>
+ <pubDate>Mon, 20 Feb 2006 3:51 pm EST</pubDate>
+ <yweather:condition text="Fair" code="34" temp="35" date="Mon, 20 Feb 2006 3:51 pm EST"/>
+ <yweather:forecast day="Mon" date="20 Feb 2006" low="25" high="37" text="Clear" code="31"/>
+ </item>
+ </channel>
+</rss>
+
+
+
+<title>Conditions for New York, NY at 3:51 pm EST</title>
+
+
+
+<yweather:condition text="Fair" code="34" temp="35" date="Mon, 20 Feb 2006 3:51 pm EST"/>
+
+
+
+XML xml = loadXML("http://xml.weather.yahoo.com/forecastrss?p=10003");
+
+
+
+
+
+
+XML root = loadXML("http://xml.weather.yahoo.com/forecastrss?p=10003"); // Step 1
+XML channel = root.getChild("channel"); // Step 2
+XML item = channel.getChild("item"); // Step 3
+XML yweather = item.getChild("yweather:condition"); // Step 4
+int temperature = yweather.getInt("temp"); // Step 5
+
+
+
+XML root = loadXML(http://xml.weather.yahoo.com/forecastrss?p=10003); // Step 1
+XML forecast = root.getChild("channel").getChild("item").getChild("yweather:condition"); // Steps 2-4
+int temperature = forecast.getInt("temp"); // Step 5
+
+
+Finally, the second line of code above can be further condensed to:
+
+
+XML forecast = xml.getChild("channel/item/yweather:condition"); // Steps 2-4
+
+
+
+<?xml version="1.0" encoding="UTF-8"?>
+<bubbles>
+ <bubble>
+ <position x="160" y="103"/>
+ <diameter>43.19838</diameter>
+ <label>Happy</label>
+ </bubble>
+ <bubble>
+ <position x="372" y="137"/>
+ <diameter>52.42526</diameter>
+ <label>Sad</label>
+ </bubble>
+ <bubble>
+ <position x="273" y="235"/>
+ <diameter>61.14072</diameter>
+ <label>Joyous</label>
+ </bubble>
+ <bubble>
+ <position x="121" y="179"/>
+ <diameter>44.758068</diameter>
+ <label>Melancholy</label>
+ </bubble>
+</bubbles>
+
+
+
+// Load an XML document
+XML xml = loadXML("bubbles.xml");
+
+// Get all the child elements
+XML[] children = xml.getChildren("bubble");
+
+
+
+for (int i = 0; i < bubbles.length; i++) {
+
+ // The position element has two attributes: x and y
+ XML positionElement = children[i].getChild("position");
+ // Note how with attributes we can get an integer or float via getInt() and getFloat()
+ float x = positionElement.getInt("x");
+ float y = positionElement.getInt("y");
+
+ // The diameter is the content of the child named "diamater"
+ XML diameterElement = children[i].getChild("diameter");
+ // Note how with the content of an XML node, we retrieve via getIntContent() and getFloatContent()
+ float diameter = diameterElement.getFloatContent();
+
+ // The label is the content of the child named "label"
+ XML labelElement = children[i].getChild("label");
+ String label = labelElement.getContent();
+}
+
+
+Threads
+
+
+void setup() {
+ size(200,200);
+ thread("someFunction");
+}
+
+void draw() {
+
+}
+
+void someFunction() {
+ // This function will run as a thread when called via
+ // thread("someFunction") as it was in setup!
+}
+
+
+
+boolean loading = false;
+
+
+
+void loadData() {
+ loading = true;
+
+ ///////////////////////////////////
+ // All of the data retrival code //
+ ///////////////////////////////////
+
+ loading = false;
+}
+
+
+
+void draw() {
+ if (loading) {
+ // Draw something to indicate loading
+ }
+}
+
+
+
+
-
-
+
+
diff --git a/content/static/tutorials/drawing/imgs/A94665D2BBAE05CF._t_ b/content/static/tutorials/drawing/imgs/A94665D2BBAE05CF._t_
new file mode 100644
index 000000000..fb0b3bb08
--- /dev/null
+++ b/content/static/tutorials/drawing/imgs/A94665D2BBAE05CF._t_
@@ -0,0 +1,147 @@
+
+
+
+
diff --git a/content/static/tutorials/drawing/imgs/A94665DD9FEE952C._t_ b/content/static/tutorials/drawing/imgs/A94665DD9FEE952C._t_
new file mode 100644
index 000000000..914fa8f46
--- /dev/null
+++ b/content/static/tutorials/drawing/imgs/A94665DD9FEE952C._t_
@@ -0,0 +1,150 @@
+
+
+
+
diff --git a/content/static/tutorials/drawing/imgs/A94665F3686FB3E6._t_ b/content/static/tutorials/drawing/imgs/A94665F3686FB3E6._t_
new file mode 100644
index 000000000..011a3cd80
--- /dev/null
+++ b/content/static/tutorials/drawing/imgs/A94665F3686FB3E6._t_
@@ -0,0 +1,101 @@
+
+
+
+
diff --git a/content/static/tutorials/drawing/imgs/drawing-01.svg b/content/static/tutorials/drawing/imgs/drawing-01.svg
index 21f5e8796..bd50213f1 100644
--- a/content/static/tutorials/drawing/imgs/drawing-01.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-01.svg
@@ -2,63 +2,146 @@
diff --git a/content/static/tutorials/drawing/imgs/drawing-02.svg b/content/static/tutorials/drawing/imgs/drawing-02.svg
index 53c5804ec..beb9935ab 100644
--- a/content/static/tutorials/drawing/imgs/drawing-02.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-02.svg
@@ -2,34 +2,148 @@
diff --git a/content/static/tutorials/drawing/imgs/drawing-03.svg b/content/static/tutorials/drawing/imgs/drawing-03.svg
index cf20e2076..b3c97fe3f 100644
--- a/content/static/tutorials/drawing/imgs/drawing-03.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-03.svg
@@ -1,101 +1,300 @@
-
+
diff --git a/content/static/tutorials/drawing/imgs/drawing-04.svg b/content/static/tutorials/drawing/imgs/drawing-04.svg
index e8e78fca4..a819634e0 100644
--- a/content/static/tutorials/drawing/imgs/drawing-04.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-04.svg
@@ -2,21 +2,100 @@
diff --git a/content/static/tutorials/drawing/imgs/drawing-05.svg b/content/static/tutorials/drawing/imgs/drawing-05.svg
index 76a79bf47..44653c110 100644
--- a/content/static/tutorials/drawing/imgs/drawing-05.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-05.svg
@@ -1,64 +1,210 @@
-
-
-
-
+
+
+
diff --git a/content/static/tutorials/drawing/imgs/drawing-06.svg b/content/static/tutorials/drawing/imgs/drawing-06.svg
index 6c0dbeefa..b60a7c33e 100644
--- a/content/static/tutorials/drawing/imgs/drawing-06.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-06.svg
@@ -2,70 +2,273 @@
diff --git a/content/static/tutorials/drawing/imgs/drawing-07.svg b/content/static/tutorials/drawing/imgs/drawing-07.svg
index 8f112e8ab..fe9206917 100644
--- a/content/static/tutorials/drawing/imgs/drawing-07.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-07.svg
@@ -2,77 +2,291 @@
diff --git a/content/static/tutorials/drawing/imgs/drawing-08.svg b/content/static/tutorials/drawing/imgs/drawing-08.svg
index c921208ee..f6b9defe9 100644
--- a/content/static/tutorials/drawing/imgs/drawing-08.svg
+++ b/content/static/tutorials/drawing/imgs/drawing-08.svg
@@ -1,1583 +1,297 @@
-
-
-
-
-
-
-
-
-]>
-Data
@@ -17,281 +17,771 @@ Daniel Shiffman
Manipulating Strings
+ Let's take a closer look at the following two String functions: indexOf() and substring().
+ indexOf() locates a sequence of characters within a string. It takes one argument — a search string — and returns a numeric value that corresponds to the first occurrence of the search string inside of the String object being searched.
String search = "def";
String toBeSearched = "abcdefghi";
int index = toBeSearched.indexOf(search); // The value of index in this example is 3.
-
+ After finding a search phrase within a string, we might want to separate out part of the string, saving it in a different variable. A part of a string is known as a substring and substrings are made with the substring() function which takes two arguments, a start index and an end index. substring() returns the substring in between the two indices.
+
String alphabet = "abcdefghi";
-String sub = alphabet.substring(3,6); // The String sub is now "def".
+String sub = alphabet.substring(3, 6); // The String sub is now "def".
-
-Splitting and Joining Strings
-
+
+
+PFont f;
+
+// Variable to store text currently being typed
+String typing = "";
+// Variable to store saved text when return is hit
+String saved = "";
+
+void setup() {
+ size(300, 200);
+ f = createFont("Arial", 16);
+}
+
+void draw() {
+ background(255);
+ int indent = 25;
+
+ // Set the font and fill for text
+ textFont(f);
+ fill(0);
+
+ // Display everything
+ text("Click in this sketch and type. \nHit return to save what you typed.", indent, 40);
+ text(typing, indent, 90);
+ text(saved, indent, 130);
+}
+
+void keyPressed() {
+ // If the return key is pressed, save the String and clear it
+ if (key == '\n') {
+ saved = typing;
+ typing = "";
+ // Otherwise, concatenate the String
+ } else {
+ typing = typing + key;
+ }
+}
+
+ Processing has two additional functions that make joining strings (or the reverse, splitting them up) easy. In sketches that involve parsing data from a file or the web, you might get hold of that data in the form of an array of strings or as one long string. Depending on what you want to accomplish, it’s useful to know how to switch between these two modes of storage. This is where these two new functions, split() and join(), will come in handy.
+
+
+ "one long string or array of strings" ←→ {"one", "long", "string", "or" ,"array", "of", "strings"}
+
+
-// Splitting a String based on spaces
+// Splitting a string based on spaces
String spaceswords = "The quick brown fox jumps over the lazy dog.";
String[] list = split(spaceswords, " ");
-for (int i = 0; i < list.length; i++) {
- println(list[i] + " " + i);
-}
+printArray(list);
-
-
-// Splitting a String based on a multiple delimiters
-String stuff = "hats & apples, cars + phones % elephants dog.";
-String[] list = splitTokens(stuff, " &,+.");
-for (int i = 0; i < list.length; i++) {
- println(list[i] + " " + i);
-}
+// Splitting a string based on commas
+String commaswords = "The,quick,brown,fox,jumps,over,the,lazy,dog.";
+String[] list = split(commaswords, ",");
+printArray(list);
-
-
+
+// Splitting a String based on multiple delimiters
+String stuff = "hats & apples, cars + phones % elephants dog.";
+String[] list = splitTokens(stuff, " &,+." );
+printArray(list);
+
+ If you are splitting numbers in a string, the resulting array can be converted into an integer array with Processing’s int() function. Numbers in a string are not numbers and cannot be used in mathematical operations unless you convert them first.
// Calculate sum of a list of numbers in a String
String numbers = "8,67,5,309";
// Converting the String array to an int array
-int[] list = int(split(numbers, ','));
+int[] list = int(split(numbers, ','));
int sum = 0;
-for (int i = 0; i < list.length; i++) {
+for (int i = 0; i<list.length; i++ ) {
sum = sum + list[i];
}
-println(sum);
+println(sum);
-
-
String[] lines = {"It", "was", "a", "dark", "and", "stormy", "night."};
-
-for loop, you can join a string together as follows:
// Manual Concatenation
String onelongstring = "";
for (int i = 0; i < lines.length; i++) {
- onelongstring = onelongstring + lines[i] + " ";
+ onelongstring = onelongstring + lines[i] + " ";
}
-
-
// Using Processing's join()
-String onelongstring = join(lines," ");
+String onelongstring = join(lines, " ");
+
-Reading and Writing Text Files
+Dealing with Data
-
+
+
+import flowers.*;
+void setup() {
+ FlowerDatabase fdb = new FlowerDatabase();
+ Flower sunflower = fdb.findFlower("sunflower");
+ float h = sunflower.getAverageHeight();
+}
+
+ In this case, someone else has done all the work for you. They've gathered data about flowers and built a Processing library with a set of functions that hands you the data in an easy-to-understand format. This library, sadly, does not exist (not yet), but there are some that do. For example, YahooWeather is a library by Marcel Schwittlick that grabs weather data from Yahoo for you, allowing you to write code like weather.getWindSpeed() or weather.getSunrise() and more. There is still plenty of work to do in the case of using a library.
+
+
+ Working with Text Files
+
+
+
// This code will print all the lines from the source text file.
String[] lines = loadStrings("file.txt");
-println("there are " + lines.length + " lines");
-println(lines);
+println("There are " + lines.length + " lines.");
+printArray(lines);
-
-
-
-
Text from a file can be used to generate a simple visualization. Take the following data file.
+
+ 
+
+The results of visualizing this data are shown below.
+
+
+
int[] data;
void setup() {
- size(200,200);
- // Load text file as a string
- String[] stuff = loadStrings("data.txt");
+ size(200, 200);
+ // Load text file as a String
+ String[] stuff = loadStrings("data.csv");
// Convert string into an array of integers using ',' as a delimiter
- data = int(split(stuff[0],','));
+ data = int(split(stuff[0], ','));
}
void draw() {
background(255);
stroke(0);
- for (int i = 0; i < data.length; i++) {
- fill(data[i]);
- rect(i*20,0,20,data[i]);
+ for (int i = 0; i<data.length; i++) {
+ // Use array of ints to set the color and height of each rectangle.
+ rect(i*20, 0, 20, data[i]);
}
+ noLoop();
}
+ Looking at how to parse a csv file with split() was a nice learning exercise. In truth, dealing with csv files (which can easily be generated from spreadsheet software such as Google docs) is such a common activity that Processing has an entire built-in class called Table to handle the parsing for you.
+
+
+Tabular Data
-
+
+
+
+
+String[] stuff = loadStrings("data.csv");
+
+ We can now say:
+
+Table table = loadTable("data.csv");
+
+ Now I've missed an important detail. Take a look again at the data.csv text file above. Notice how the first line of text is not the data itself, but rather a header row. This row includes labels that describe the data included in each subsequent row. The good news is that Processing can automatically interpret and store the headers for you, if you pass in the option "header" when loading the table. (In addition to "header", there are other options you can specify. For example, if your file is called data.txt but is comma separated data you can pass in the option "csv". If it also has a header row, then you can specifiy both options like so: "header,csv"). A full list of options can be found on the loadTable() documentation page.
+
+Table table = loadTable("data.csv", "header");
+
+ Now that the table is loaded, I can show how you grab individual pieces of data or iterate over the entire table. Let's look at the data visualized as a grid.
+
+
+
+ In the above grid you can see that the data is organized in terms of rows and columns. One way to access the data, therefore, would be to request a value by its numeric row and column location (with zero being the first row or first column). This is similar to accessing a pixel color at a given (x,y) location, though in this case the y position (row) comes first. The following code requests a piece of data at a given (row, column) location.
+
+int val1 = table.getInt(2, 1); // val now has the value 235
+float val2 = table.getFloat(3, 2); // val2 now has the value 44.758068
+
+String s = table.getString(0, 3); // s now has the value “Happy”
+
+ While the numeric index is sometimes useful, it’s generally going to be more convenient to access each piece of data by the column name. For example, I could pull out a specific row from the Table.
+
+TableRow row = table.getRow(2); // Gets the third row (index 2)
+
+ Note in the above line of code that a Table object refers to the entire table of data while a TableRow object handles an individual row of data within the Table.
+
+
+
-String words = "apple bear cat dog";
-String[] list = split(words, ' ');
+int x = row.getInt("x"); // // x has the value 273
+
+int y = row.getInt("y"); // y has the value 235
+
+float d = row.getFloat("diameter"); // d has the value 61.14072
-// Writes the strings to a file, each on a separate line
-saveStrings("nouns.txt", list);
+String s = row.getString("name"); // s has the value “Joyous”
+ The method getRow() returns a single row from the table. If you want to grab all the rows and iterate over them you can do so in a loop with a counter accessing each row one at a time. The total number of available rows can be retrieved with getRowCount().
+
+for (int i = 0; i<table.getRowCount(); i++) {
-
+ If you want to search for a select number of rows within the table, you can do so with findRows() and matchRows().
+
+
+
+
+row.setInt("x", mouseX); // Update the value of column "x" to mouseX in a given TableRow.
+
+ To add a new row to a Table, simply call the method addRow() and set the values of each column.
+
+//Create a new row.
+TableRow row = table.addRow();
+//Set the values of all columns in that row.
+row.setFloat("x", mouseX);
+row.setFloat("y", mouseY);
+row.setFloat("diameter", random(40, 80));
+row.setString("name", "new label");
+
+ To delete a row, simply call the method removeRow() and pass in the numeric index of the row you would like removed. For example, the following code removes the first row whenever the size of the table is greater than ten rows.
-PrintWriter output;
+// If the table has more than 10 rows
+if (table.getRowCount()>10) {
+
+//Delete the first row (index 0).
+ table.removeRow(0);
+}
+
+ The following example puts all of the above code together. Notice how each row of the table contains the data for a Bubble object.
+
+
+
+Loading and Saving Tabular Data
+
+
+
+
+
+// The data from the Table object will fill the array of Bubble objects
+Table table;
+Bubble[] bubbles;
void setup() {
- // Create a new file in the sketch directory
- output = createWriter("positions.txt");
+ size(480, 360);
+ loadData();
}
void draw() {
- point(mouseX, mouseY);
- output.println(mouseX); // Write the coordinate to the file
+ background(255);
+ // Display all bubbles
+ for (int i = 0; i<bubbles.length; i++) {
+ bubbles[i].display();
+ }
}
-void keyPressed() {
- output.flush(); // Writes the remaining data to the file
- output.close(); // Finishes the file
- exit(); // Stops the program
+void loadData() {
+ // "header" indicates the file has header row. The size of the array
+ // is then determined by the number of rows in the table.
+ table = loadTable("data.csv", "header");
+ bubbles = new Bubble[table.getRowCount()];
+
+
+ for (int i = 0; i<table.getRowCount(); i++) {
+ // Iterate over all the rows in a table.
+ TableRow row = table.getRow(i);
+
+
+ // Access the fields via their column name (or index).
+ float x = row.getFloat("x");
+ float y = row.getFloat("y");
+ float d = row.getFloat("diameter");
+ String n = row.getString("name");
+ // Make a Bubble object out of the data from each row.
+ bubbles[i] = new Bubble(x, y, d, n);
+ }
}
-
-Tabular Data
-
+ // If the table has more than 10 rows, delete the oldest row.
+ if (table.getRowCount()>10) {
+ table.removeRow(0);
+ }
-
-String[] stuff = loadStrings("data.csv");
+// This simple Bubble class draws a circle to the window
+// and displays a text label when the mouse hovers.
+class Bubble {
+ float x, y;
+ float diameter;
+ String name;
+
+ boolean over = false;
+
+ // Create the Bubble
+ Bubble(float tempX, float tempY, float tempD, String s) {
+ x = tempX;
+ y = tempY;
+ diameter = tempD;
+ name = s;
+ }
+
+ // Checking if mouse is over the bubble
+ void rollover(float px, float py) {
+ float d = dist(px, py, x, y);
+ if (d<diameter/2) {
+ over = true;
+ } else {
+ over = false;
+ }
+ }
+
+ // Display the Bubble
+ void display() {
+ stroke(0);
+ strokeWeight(2);
+ noFill();
+ ellipse(x, y, diameter, diameter);
+ if (over) {
+ fill(0);
+ textAlign(CENTER);
+ text(name, x, y+diameter/2+20);
+ }
+ }
+}
-
-
+
+
+
-Table table = loadTable("data.csv");
+boolean rollover(int mx, int my) {
+ if (dist(mx, my, x, y)<diameter/2) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Data that is not in a Standardized Format
-
-Table table = loadTable("data.csv","header");
+String[] lines = loadStrings("http://www.yahoo.com");
+ When you send a URL path into loadStrings(), you get back the raw HTML (Hypertext Markup Language) source of the requested web page. It’s the same stuff that appears upon selecting “View Source” from a browser’s menu options. You don’t need to be an HTML expert to follow this section, but if you are not familiar at all with HTML, you might want to read http://en.wikipedia.org/wiki/HTML.
+
+
+
+
+String onelongstring = join(lines, " ");
+
+ When pulling raw HTML from a web page, it’s likely you do not want all of the source, but just a small piece of it. Perhaps you’re looking for weather information, a stock quote, or a news headline. You can take advantage of the text manipulation functions you learned — indexOf(), substring(), and length() — to find pieces of data within a large block of text. Take, for example, the following String object:
+
+String stuff = "Number of apples:62. Boy, do I like apples or what!";
+
+Let’s say I want to pull out the number of apples from the above text. My algorithm would be as follows:
+
+
+
+
+
+
+int start = stuff.indexOf("apples:" ) + 7; // STEP 1
+// The index where a string ends can be found by
+// searching for that string and adding its length (here, 8).
+int end = stuff.indexOf(".", start); // STEP 2
+String apples = stuff.substring(start, end); // STEP 3
+int apple_no = int(apples); // STEP 4
+
+ The above code will do the trick, but I should be a bit more careful to make sure I don’t run into any errors if I do not find the string I am searching for. I can add some error checking and generalize the code into a function:
+
+// A function that returns a substring between two substrings.
+// If the beginning of end "tag" is not found, the function returns an empty string.
+String giveMeTextBetween(String s, String startTag, String endTag) {
+ // Find the index of the beginning tag
+ int startIndex = s.indexOf(startTag);
+ // If I don't find anything
+ if (startIndex == -1) {
+ return "";
+ }
+ // Move to the end of the beginning tag
+ startIndex += startTag.length();
-
+ With this technique, you are ready to connect to a website from within Processing and grab data to use in your sketches. For example, you could read the HTML source from nytimes.com and look for today’s headlines, search finance.yahoo.com for stock quotes, count how many times the word “flower” appears on your favorite blog, and so on. However, HTML is an ugly, scary place with inconsistently formatted pages that are difficult to reverse engineer and parse effectively. Not to mention the fact that companies change the source code of web pages rather often, so any example that I might make while I am writing this paragraph might break by the time you read this paragraph.
+
+
+
-
-
+
+
+
+
-int val1 = table.getInt(2, 1); // val now has the value 235
-float val2 = table.getFloat(3, 2); // val2 now has the value 44.758068
-String s = table.getString(0, 3); // s now has the value "Happy"
+<div class="txt-block">
+ <h4 class="inline">Runtime:</h4>
+ <time itemprop="duration" datetime="PT139M">139 min</time>
+</div>
+ For any given movie, the running time itself will be variable, but the HTML structure of the page will stay the same. I can therefore deduce that running time will always appear in between:
+
+<time itemprop="duration" datetime="PT139M">
+
+ and:
+
+</time>
+
+ Knowing where the data starts and ends, I can use giveMeTextBetween() to pull out the running time. A quote in Java marks the beginning or end of a string. So how do you include an actual quote in a String object? The answer is via an “escape” sequence. A quote can be included using a backward slash, followed by a quote. For example: String q = "This String has a quote \"in it";
+
+String url = "http://www.imdb.com/title/tt0058331";
+String[] lines = loadStrings(url);
+// Get rid of the array in order to search the whole page
+String html = join(lines, " ");
-
+ The following code retrieves both the running time and movie poster iamge from IMDb and displays it onscreen.
+
+
+ Parsing IMDb Manually
+
+
+
+String runningtime;
+PImage poster;
-Note in the above line of code that a Table object refers to the entire table of data while a TableRow object handles an individual row of data within the Table.
+void setup() {
+ size(300, 350);
+ loadData();
+}
-Once we have the TableRow object, we can ask for data from some or all of the columns.
+void draw() {
+ // Display all the stuff I want to display
+ background(255);
+ image(poster, 10, 10, 164, 250);
+ fill(0);
+ text("Shaun the Sheep", 10, 300);
+ text(runningtime, 10, 320);
+}
-
-int x = row.getInt("x"); // x has the value 273
-int y = row.getInt("y"); // y has the value 235
-float d = row.getFloat("diameter"); // d has the value 61.14072
-String s = row.getString("name"); // s has the value "Joyous"
-
+void loadData() {
+ String url = "http://www.imdb.com/title/tt2872750/";
+
+ // Get the raw HTML source into an array of strings (each line is one element in the array).
+ // The next step is to turn array into one long string with join().
+ String[] lines = loadStrings(url);
+ String html = join(lines, "");
+
+ String start = "";
+ runningtime = giveMeTextBetween(html, start, end);Searching for running time.
+
+ start = "";
+ // Search for the URL of the poster image.
+ String imgUrl = giveMeTextBetween(html, start, end);
+ // Now, load that image!
+ poster = loadImage(imgUrl);
+}
-The method getRow() returns a single row from the table. If you want to grab all the rows and iterate over them you can do so with the method rows().
+String giveMeTextBetween(String s, String before, String after) {
-
-for (TableRow row : table.rows()) {
- float x = row.getFloat("x");
- float y = row.getFloat("y");
- float d = row.getFloat("diameter");
- String n = row.getString("name");
- // Do something with the data of each row
+ // This function returns a substring between two substrings (before and after).
+ // If it can’t find anything it returns an empty string.
+ String found = "";
+
+ // Find the index of before
+ int start = s.indexOf(before);
+ if (start == -1) {
+ return "";
+ }
+
+ // Move to the end of the beginning tag
+ // and find the index of the "after" String
+ start += before.length();
+ int end = s.indexOf(after, start);
+ if (end == -1) {
+ return "";
+ }
+
+ // Return the text in between
+ return s.substring(start, end);
}
-If you want to search for a select number of rows within the table, you can do so with findRows() and matchRows().
-
-Text Analysis
+
+
+
+
-// Update the value of column "x" to mouseX in a given TableRow.
-row.setInt("x",mouseX);
+IntDict inventory = new IntDict();
-
-
-// Create a new row
-TableRow row = table.addRow();
-// Set the values of that row
-row.setFloat("x", mouseX);
-row.setFloat("y", mouseY);
-row.setFloat("diameter", random(40, 80));
-row.setString("name", "new label");
+// set() assigns an integer to a String.
+inventory.set("pencils", 10);
+inventory.set("paper clips", 128);
+inventory.set("pens, 16");
+
+ There are a variety of other methods that can be called to change the value associated with a particular key. For example, if you wanted to add five pencils, you can use add().
+
+inventory.add("pencils", 5); // The value of “pencils” is now 15.
-
-// If the table has more than 10 rows
-if (table.getRowCount() > 10) {
- // Delete the first row
- table.removeRow(0);
-}
+inventory.increment("pens"); // The value of “pencils” is now 16.
+ To retrieve a value associated with a particular key, the get() method is used.
+
+int num = inventory.get("pencils"); // The value of num is 16.
+
+ Finally, dictionaries can be sorted by their keys (alphabetical) or values (smallest to largest or the reverse) with the methods sortKeys(), sortKeysReverse(), sortValues(), and sortValuesReverse().
+
+
+
+
+
+String[] allwords;
-
+ XML Data
+IntDict concordance;
-
+
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version = "1.0" encoding = "UTF-8 "?>
<students>
<student>
<id>001</id>
@@ -313,94 +803,177 @@
-
-XML Data
<address>
<street>45.3 Nebula 5</street>
<city>Boolean City</city>
- <state&tt;Booles</state>
+ <state>Booles</state>
<zip>12358</zip>
</address>
</student>
</students>
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0">
<channel>
<item>
- <title>Conditions for New York, NY at 3:51 pm EST</title>
+ <title>Conditions for New York, NY at 12:49 pm EDT</title>
<geo:lat>40.67</geo:lat>
<geo:long>-73.94</geo:long>
- <link>http://xml.weather.yahoo.com/forecast/USNY0996_f.html</link>
- <pubDate>Mon, 20 Feb 2006 3:51 pm EST</pubDate>
- <yweather:condition text="Fair" code="34" temp="35" date="Mon, 20 Feb 2006 3:51 pm EST"/>
- <yweather:forecast day="Mon" date="20 Feb 2006" low="25" high="37" text="Clear" code="31"/>
+ <link>http://us.rd.yahoo.com/dailynews/rss/weather/New_York__NY//link>
+ <pubDate>Thu, 24 Jul 2014 12:49 pm EDT</pubDate>
+ <yweather:condition text="Partly Cloudy" code="30" temp="76"/>
+ <yweather:forecast day="Thu" low="65" high="82" text="Partly Cloudy"/>
</item>
</channel>
</rss>
-
-
+
-<title>Conditions for New York, NY at 3:51 pm EST</title>
+<title>Conditions for New York, NY at 12:49 pm EDT</title>
-
-
-<yweather:condition text="Fair" code="34" temp="35" date="Mon, 20 Feb 2006 3:51 pm EST"/>
+<yweather:forecast day="Thu" low="65" high="82" text="Partly Cloudy"/>
+
-Using the Processing XML Class
+
XML xml = loadXML("http://xml.weather.yahoo.com/forecastrss?p=10003");
+ Here, instead of loadStrings() or loadTable(), I'm now calling loadXML() and passing in the address (URL or local file) of the XML document. An XML object represents one element of an XML tree. When a document is first loaded, that XML object is always the root element. Referring back to XML tree diagram from Yahoo Weather, I find the current temperature via the following path:
+
+
+
+
+
+
+
+// Accessing the “channel” child element of the root element -->
+XML channel = xml.getChild("channel");
+
+ The content of an element itself is retrieved with one of the following methods: getContent(), getIntContent(), or getFloatcContent(). getContent() is for generic use and will always give you the content as a String. If you intend to use the content as a number, Processing will convert it for you with either getIntContent() or getFloatcContent(). Attributes can also be read as either numbers — getInt(), getFloat() — or text — getString().
+
-
-
+
+
+XML root = loadXML("http://xml.weather.yahoo.com/forecastrss?p=10003"); // Step 1
-
-XML root = loadXML("http://xml.weather.yahoo.com/forecastrss?p=10003"); // Step 1
-XML channel = root.getChild("channel"); // Step 2
-XML item = channel.getChild("item"); // Step 3
-XML yweather = item.getChild("yweather:condition"); // Step 4
-int temperature = yweather.getInt("temp"); // Step 5
-
+XML item = channel.getChild("item"); // Step 3
-
-XML root = loadXML(http://xml.weather.yahoo.com/forecastrss?p=10003); // Step 1
-XML forecast = root.getChild("channel").getChild("item").getChild("yweather:condition"); // Steps 2-4
-int temperature = forecast.getInt("temp"); // Step 5
+int temperature = yweather.getInt("temp"); // Step 5
+ However, this is a bit long-winded and so can be compressed down into one (or three, as below) lines of code.
+
+XML root = loadXML(http://xml.weather.yahoo.com/forecastrss?p=10003);
-Finally, the second line of code above can be further condensed to:
-
+XML forecast =
+ root.getChild("channel").getChild("item").getChild("yweather:condition"); // Steps 2-4
+int temperature = forecast.getInt("temp");
+
+ Finally, the second line of code above can be further condensed to:
XML forecast = xml.getChild("channel/item/yweather:condition"); // Steps 2-4
+ Following is the above code put together in an example that retrieves weather data for multiple zip codes by parsing Yahoo's XML feed.
+
+
+
+int temperature = 0;Temperature is stored as a number and the description of the weather as a string.
+String weather = "";
+
+
+// The zip code
+String zip = "10003";
+
+void setup() {
+ size(200, 200);
+
+ // The URL for the XML document
+ String url = "http://xml.weather.yahoo.com/forecastrss?p=" + zip;
-
+ Other useful XML functions are:
+
+
+
+
+
+
+
<?xml version="1.0" encoding="UTF-8"?>
<bubbles>
@@ -426,52 +999,321 @@
+ I can use getChildren() to retrieve the array of <bubble> elements and make a Bubble object from each one. Here is the example which uses the identical Bubble class from earlier (not included below). The new code is in bold.
+
+
+XML Data
</bubble>
</bubbles>
+
+// An Array of Bubble objects
+Bubble[] bubbles;
+// An XML object
+XML xml;
+
+void setup() {
+ size(480, 360);
+ loadData();
+}
-
+ In addition to loadXML(), Processing also includes a saveXML() function for writing XML files to your sketch folder. You can modify the XML tree itself by adding or removing elements with addChild() or removeChild(), as well as modify the content of elements or attributes with setContent(), setIntContent(), setFloatContent(), setString(), setInt(), and setFloat().
+
+
+Bubble array is determined by the total XML elements named “bubble.”
+
+ for (int i = 0; i < bubbles.length; i++) {
+
+ XML positionElement = children[i].getChild("position");
+ // The position element has two attributes: “x” and “y”.
+ // Attributes can be accessed as an integer or float via getInt() and getFloat().
+ float x = positionElement.getInt("x");
+ float y = positionElement.getInt("y");
+
+ // The diameter is the content of the child named "diameter"
+ XML diameterElement = children[i].getChild("diameter");
+ float diameter = diameterElement.getFloatContent();
+ // Notice, however, with the content of an XML node,
+ // I retrieve via getIntContent() and getFloatContent().
+
+ // The label is the content of the child named "label"
+ XML labelElement = children[i].getChild("label");
+ String label = labelElement.getContent();
+
+ // Make a Bubble object out of the data read
+ bubbles[i] = new Bubble(x, y, diameter, label);
+ }
+}
+
+void draw() {
+ background(255);
+ // Display all bubbles
+ for (int i = 0; i < bubbles.length; i++) {
+ bubbles[i].display();
+ bubbles[i].rollover(mouseX, mouseY);
+ }
+}
+JSON
+
+
+
+{
+ "name":"Olympia",
+ // Each name/value pair is separated by a comma.
+ "age":3,
+ "height":96.5,
+ "state":"giggling"
+}
+Notice how this maps closely to classes in Processing.
+
+class Person {
+ String name;
+ int age;
+ float height;
+ String state;
+}
+
+ There are no classes in JSON, only the object literals themselves. Also an object can contain, as part of itself, another object.
+
+{
+ "name":"Olympia",
+ "age":3,
+ "height":96.5,
+ "state":"giggling",
+ // The value of “brother” is an object containing two name/value pairs.
+ "brother":{
+ "name":"Elias",
+ "age":6
+ }
+}
+ In XML, the preceding JSON data would look like the following (for simplicity I'm avoiding the use of XML attributes).
+
+<xml version="1.0" encoding="UTF-8"?>
+<person>
+ <name>Olympia</name>
+ <age>3</age>
+ <height>96.5</height>
+ <state>giggling</state>
+ <brother>
+ <name>Elias</name>
+ <age>6</age>
+ </brother>
+</person>
+
+ Multiple JSON objects can appear in the data as an array. Just like the arrays you use in Processing, a JSON array is simply a list of values (primitives or objects). The syntax, however, is different with square brackets indicating the use of an array rather than curly ones. Here is a simple JSON array of integers:
+
+[1, 7, 8, 9, 10, 13, 15]
+
+ You might find an array as part of an object.
+
+{
+ "name":"Olympia",
+ // The value of “favorite colors” is an array of strings.
+ "favorite colors":[
+ "purple",
+ "blue",
+ "pink"
+ ]
+}
+
+ Or an array of objects themselves. For example, here is what the bubbles would look like in JSON. Notice how this JSON data is organized as a single JSON object "bubbles," which contains a JSON array of JSON objects, the bubbles. Flip back to compare to the CSV and XML versions of the same data.
+
+{
+ "bubbles":[
+ {
+ "position":{
+ "x":160,
+ "y":103
+ },
+ "diameter":43.19838,
+ "label":"Happy"
+ },
+ {
+ "position":{
+ "x":372,
+ "y":137
+ },
+ "diameter":52.42526,
+ "label":"Sad"
+ },
+ {
+ "position":{
+ "x":273,
+ "y":235
+ },
+ "diameter":61.14072,
+ "label":"Joyous"
+ }
+ ]
+}
+
+
+JSONObject and JSONArray
+
+
+
+[
+ {
+ "name":"Elias"
+ },
+ {
+ "name":"Olympia"
+ }
+]
+
+ Sample 2:
-// Load an XML document
-XML xml = loadXML("bubbles.xml");
+{
+ "names":[
+ {
+ "name":"Elias"
+ },
+ {
+ "name":"Olympia"
+ }
+ ]
+}
+
+ Look how similar the above two samples look. They both contain exactly the same data, two names "Elias" and "Olympia." There is one, very key difference, however, to how the data is formatted: the very first character. Is it a "[" or a "{"? The answer will determine whether you’re loading an array ("[") or an object("{"). JSON objects start with a curly bracket, while JSON arrays start with a square bracket.
+
+JSONObject json = loadJSONObject("file.json");
-// Get all the child elements
-XML[] children = xml.getChildren("bubble");
+JSONArray json = JSONArray("file.json");
+ Typically, even if the data is ultimately organized as an array of objects (such as the array of "bubble" objects), the root element of the JSON data will be an object that contains that array. Let's look at the bubble data one more time.
+
+{
+ "bubbles":[
+ {
+ "position":{
+ "x":160,
+ "y":103
+ },
+ "diameter":43.19838,
+ "label":"Happy"
+ },
+ {
+ "position":{
+ "x":372,
+ "y":137
+ },
+ "diameter":52.42526,
+ "label":"Sad"
+ }
+ ]
+}
+
+ With the above, I first load an object and then pull the array out of that object.
+
+JSONObject json = loadJSONObject("data.json");
+JSONArray bubbleData = json.getJSONArray("bubbles");
+
+ Just as with XML, the data from an element is accessed via its name, in this case "bubbles." With a JSONArray, however, each element of the array is retrieved via its numeric index. The following code iterates over a JSONArray.
+
+for (int i = 0; i < bubbleData.size(); i++) {
+ JSONObject bubble = bubbleData.getJSONObject(i);
+ }
+
+ And when you're looking for a specific piece of data from a JSONObject, such as an integer or string, the functions are identical to those of XML attributes. The following code gets the position object from the bubble object, then gets x and y as integers from the position object. The diameter and label are then available directly from the Bubble object.
+
+ JSONObject position = bubble.getJSONObject("position");
-
-for (int i = 0; i < bubbles.length; i++) {
-
- // The position element has two attributes: x and y
- XML positionElement = children[i].getChild("position");
- // Note how with attributes we can get an integer or float via getInt() and getFloat()
- float x = positionElement.getInt("x");
- float y = positionElement.getInt("y");
-
- // The diameter is the content of the child named "diamater"
- XML diameterElement = children[i].getChild("diameter");
- // Note how with the content of an XML node, we retrieve via getIntContent() and getFloatContent()
- float diameter = diameterElement.getFloatContent();
+ int x = position.getInt("x");
+ int y = position.getInt("y");
- // The label is the content of the child named "label"
- XML labelElement = children[i].getChild("label");
- String label = labelElement.getContent();
-}
+ float diameter = bubble.getFloat("diameter");
+ String label = bubble.getString("label");
+ Putting this all together, I can now make a JSON version of the bubbles example (leaving out the draw() function and Bubble class which haven't changed.)
+
+
+
+
+// An Array of Bubble objects
+Bubble[] bubbles;
-
+
+Threads
+ // The size of the array of Bubble objects is determined by the length of the JSON array.
+ bubbles = new Bubble[bubbleData.size()];
+
+
+ for (int i = 0; i<bubbleData.size(); i++) {
+
+ // Iterate through the array, grabbing each JSON object one at a time.
+ JSONObject bubble = bubbleData.getJSONObject(i);
-Threads
+
void setup() {
- size(200,200);
thread("someFunction");
}
@@ -484,44 +1326,201 @@
+ The thread() function receives a string as an argument. The string should match the name of the function you want to run as a thread. In the above example it’s "someFunction".
+
+
+ Threads
// thread("someFunction") as it was in setup!
}
+
+void draw() {
+ // The code will stop here and wait to receive the data before moving on.
+ JSONObject json = loadJSONObject("http://time.jsontest.com/");
+ String time = json.getString("time");
+ text(time, 40, 100);
+}
+
+ This would give me the current time every cycle through draw(). If I examine the frame rate, however, I'll notice that the sketch is running incredibly slowly (and all it needs to do is draw a single string!). This is where calling the parsing code as a separate thread will help a lot.
+
+String time = "";
-
-boolean loading = false;
+void requestData() {
+ JSONObject json = loadJSONObject("http://time.jsontest.com/");
+ time = json.getString("time");
+}
+ The logic is identical, only I am not requesting the data directly in draw(), but executing that request as a separate thread. Notice that I am not doing any drawing in requestData(). This is key as executing drawing functions in code that runs on a separate thread can cause conflicts with the main animation thread (i.e., draw()) resulting in strange behavior and errors.
+
-
+
+
-void loadData() {
- loading = true;
+Timer timer = new Timer(1000);
+String time = "";
- ///////////////////////////////////
- // All of the data retrival code //
- ///////////////////////////////////
+void setup() {
+ size(200, 200);
+ // Start by requesting the data asynchronously in a thread.
+ thread("retrieveData");
+ timer.start();
+}
+
+void draw() {
+ background(255);
+ // Every one second, make a new request.
+ if (timer.isFinished()) {
+ retrieveData();
- loading = false;
+ // And restart the timer.
+ timer.start();
+ }
+
+ fill(0);
+ text(time, 40, 100);
+
+ translate(20, 100);
+ stroke(0);
+ //Draw a little animation to demonstrate that the draw() loop never pauses.
+ rotate(frameCount*0.04);
+ for (int i = 0; i<10; i++) {
+ rotate(radians(36));
+ line(5, 0, 10, 0);
+ }
+}
+
+// get the data
+void retrieveData() {
+ JSONObject json = loadJSONObject("http://time.jsontest.com/");
+ time = json.getString("time");
+}
+
+
+class Timer {
+
+ int savedTime;
+ boolean running = false;
+ int totalTime;
+
+ Timer(int tempTotalTime) {
+ totalTime = tempTotalTime;
+ }
+
+ void start() {
+ running = true;
+ savedTime = millis();
+ }
+
+ boolean isFinished() {
+ int passedTime = millis() - savedTime;
+ if (running && passedTime > totalTime) {
+ running = false;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
}
-APIs
+
+
+
+
+
+
+// This is not a real key
+String apiKey = "40e2es0b3ca44563f9c62aeded4431dc:12:51913116";
+
+ You also need to know what the URL is for the API itself. This information is documented for you on the developer site, but here it is for simplicity:
+
+String url = "http://api.nytimes.com/svc/search/v2/articlesearch.json";
+
+ Finally, you have to tell the API what it is you are looking for. This is done with a “query string,” a sequence of name value pairs describing the parameters of the query joined with an ampersand. This functions similarly to how you pass arguments to a function in Processing. If you wanted to search for the term "processing" from a search() function you might say:
+
+search("processing");
+
+ Here, the API acts as the function call, and you send it the arguments via the query string. Here is a simple example asking for a list of the oldest articles that contain the term "processing" (the oldest of which turns out to be May 12th, 1852).
+
+// The name/value pairs that configure the API query are: (q,processing) and (sort,oldest)
+String query = "?q=processing&sort=oldest";
+
+ This isn't just guesswork. Figuring out how to put together a query string requires reading through the API's documentation. For The New York Times, it’s all outlined on the Times' developer website. Once you have your query you can join all the pieces together and pass it to loadJSONObject(). Here is a tiny example that simply displays the most recent headline.
+
+
-void draw() {
- if (loading) {
- // Draw something to indicate loading
- }
+void setup() {
+ size(200, 200);
+
+ String apiKey = "40e2ea0b3ca44563f9c62aeded0431dc:18:51513116";
+ String url = "http://api.nytimes.com/svc/search/v2/articlesearch.json";
+ String query = "?q=processing&sort=newest";
+
+ // Make the API query
+ // Here, I format the call to the API by joing the URL with the API key with the query string.
+ JSONObject json = loadJSONObject(url+query+"&api-key="+apiKey);
+
+ String headline = json.getJSONObject("response").getJSONArray("docs").
+ // Grabbing a single headline from the results.
+ getJSONObject(0).getJSONObject("headline").getString("main");
+ background(255);
+ fill(0);
+ text(headline, 10, 10, 180, 190);
}
+ Some APIs require a deeper level of authentication beyond an API access key. Twitter, for example, uses an authentication protocol known as “OAuth” to provide access to its data. Writing an OAuth application requires more than just passing a String into a request and is beyond the scope of this tutorial. However, in these cases, if you’re lucky, you can find a Processing library that handles all of the authentication for you. There are several APIs that can be used directly with Processing via a library, and you can find a list of them in the “Data / Protocols” section of the libraires reference page for some ideas. Temboo, for example, offers a Processing library that handles OAuth for you and provides direct access to many APIs (including Twitter) in Processing. With Temboo, you can write code that looks like:
+
+
+// Temboo acts as a go-between you and Twitter, so first you just authenticate with Temboo.
+TembooSession session = new TembooSession("ACCOUNT_NAME", "APP_NAME", "APP_KEY");
-
Video Tutorials. Links to vi
@@ -286,14 +286,37 @@
-
Hello Processing
+
+
Hello Processing
by Daniel Shiffman et al.Text Tutorials. A collection
-
-
diff --git a/content/static/tutorials/p3d/index.html b/content/static/tutorials/p3d/index.html
index 8b5667019..22bfd8eb1 100644
--- a/content/static/tutorials/p3d/index.html
+++ b/content/static/tutorials/p3d/index.html
@@ -10,7 +10,7 @@
+
+
-
Anatomy of a Program
- by J David Eisenberg
+
Video
+ by Daniel Shiffman
+
+
+
+
Anatomy of a Program
+ by J David Eisenberg
+
+
+
+// Example: Two Car objects
Car myCar1;
Car myCar2; // Two objects!
@@ -384,7 +384,7 @@ Objects are data types too!
If you were programming the Space Invaders game, for example, you might create a Spaceship class, an Enemy class, and a Bullet class, using an object for each entity in your game.
-In addition, although not primitive, classes are data types just like integers and floats. And since classes are made up of data, an object can therefore contain other objects! For example, let's assume you had just finished programming a Fork and Spoon class. Moving on to a PlaceSetting class, you would likely include variables for both a Fork object and a Spoon object inside that class itself. This is perfectly reasonable and quite common in object-oriented programming.
+In addition, although not primitive, classes are data types, just like integers and floats. And since classes are made up of data, an object can therefore contain other objects! For example, let's assume you had just finished programming a Fork and Spoon class. Moving on to a PlaceSetting class, you would likely include variables for both a Fork object and a Spoon object inside that class itself. This is perfectly reasonable and quite common in object-oriented programming.
@@ -413,11 +413,10 @@
Objects are data types too!
-When a primitive value (integer, float, etc.) is passed in a function, a copy is made. With objects, this is not the case, and the result is a bit more intuitive. If changes are made to an object after it is passed into a function, those changes will affect that object used anywhere else throughout the sketch. This is known as pass by reference since instead of a copy, a reference to the actual object itself is passed into the function.
+When a primitive value (integer, float, etc.) is passed in a function, a copy is made. With objects, this is not the case, and the result is a bit more intuitive. If changes are made to an object after it is passed into a function, those changes will affect that object used anywhere else throughout the sketch. This is known as pass by reference since, instead of a copy, a reference to the actual object itself is passed into the function.
P3D
Daniel Shiffman
@@ -28,8 +28,8 @@
Daniel Shiffman
@@ -41,7 +41,7 @@ 3D Transformations

Lighting
- Perspective
float cameraZ = (height/2.0) / tan(fov/2.0);
perspective(fov, float(width)/float(height), cameraZ/2.0, cameraZ*2.0);
} else {
- ortho(0, width, 0, height);
+ ortho(-width/2, width/2, -height/2, height/2);
}
translate(width/2, height/2, 0);
rotateX(-PI/6);
diff --git a/content/static/tutorials/pixels/index.html b/content/static/tutorials/pixels/index.html
index 114693e0d..126d87c9d 100644
--- a/content/static/tutorials/pixels/index.html
+++ b/content/static/tutorials/pixels/index.html
@@ -202,7 +202,7 @@ Pixels, pixels, and more pixels
Take the following simple example. This program sets each pixel in a window to a random grayscale value. The pixels array is just like an other array, the only difference is that we don't have to declare it since it is a Processing built-in variable.
-
+Example: Setting Pixels
size(200, 200);
@@ -256,7 +256,7 @@
Pixels, pixels, and more pixels
Let's look at how it is done.
-
+Example: Setting Pixels according to their 2D location
size(200, 200);
@@ -305,7 +305,7 @@
Intro To Image Processing
Access to these fields allows us to loop through all the pixels of an image and display them onscreen.
-
+Example: Displaying the pixels of an image
PImage img;
@@ -361,7 +361,7 @@
Our second image filter, making our own "tint"
Just a few paragraphs ago, we were enjoying a relaxing coding session, colorizing images and adding alpha transparency with the friendly tint() method. For basic filtering, this method did the trick. The pixel by pixel method, however, will allow us to develop custom algorithms for mathematically altering the colors of an image. Consider brightness—brighter colors have higher values for their red, green, and blue components. It follows naturally that we can alter the brightness of an image by increasing or decreasing the color components of each pixel. In the next example, we dynamically increase or decrease those values based on the mouse's horizontal location. (Note, the next two examples include only the image processing loop itself, the rest of the code is assumed.)
-
+Example: Adjusting image brightness
for (int x = 0; x < img.width; x++) {
@@ -394,7 +394,7 @@ Our second image filter, making our own "tint"
-
+Example: Adjusting image brightness based on pixel location
for (int x = 0; x < img.width; x++) {
@@ -438,7 +438,7 @@ Writing to another PImage object's pixels
-
+Example: Brightness Threshold
PImage source; // Source image
@@ -538,7 +538,7 @@
Level II: Pixel Group Processing
-
+Example: Pixel neighbor differences (edges)
// Since we are looking at left neighbors
@@ -600,7 +600,7 @@
Level II: Pixel Group Processing
-
+Example: Sharpen with Convolution
PImage img;
@@ -695,7 +695,7 @@
Visualizing the Image
-
+Example: "Pointillism"
PImage img;
@@ -739,7 +739,7 @@
Visualizing the Image
-
+Example: 2D image mapped to 3D
PImage img; // The source image
diff --git a/content/static/tutorials/pshader/imgs/pipeline.png b/content/static/tutorials/pshader/imgs/pipeline.png
index 389e0b840..12132bf4e 100644
Binary files a/content/static/tutorials/pshader/imgs/pipeline.png and b/content/static/tutorials/pshader/imgs/pipeline.png differ
diff --git a/content/static/tutorials/pshader/index.html b/content/static/tutorials/pshader/index.html
index 64be71338..5ac13895c 100644
--- a/content/static/tutorials/pshader/index.html
+++ b/content/static/tutorials/pshader/index.html
@@ -31,7 +31,7 @@
Andres Colubri
Writing shaders requires an understanding of the individual stages involved in the rendering a scene with the GPU, and how we can use GLSL to program them. The sequence of these stages is called the "graphical pipeline" in the technical parlance of computer graphics, and we will now take a look at the main stages in the pipeline from the perspective of a Processing sketch.
-Andres Colubri
void setup() {
size(400, 400, P3D);
- noStroke();
+ noStroke();
}
void draw() {
background(0);
-
camera(width/2, height/2, 300, width/2, height/2, 0, 0, 1, 0);
- pointLight(200, 200, 200, width/2, height/2, 200);
+
+ pointLight(200, 200, 200, width/2, height/2, -200);
translate(width/2, height/2);
rotateY(angle);
@@ -63,7 +63,7 @@ Andres Colubri
fill(200, 50, 50);
vertex(+100, -100);
vertex(-100, -100);
- endShape();
+ endShape();
angle += 0.01;
}
@@ -88,7 +88,7 @@ Andres Colubri
Andres Colubri
function vertexShader(vertex) {
projPos = projection * modelview * vertex.position;
- litColor = lightColor * dot(vertex.normal, lightDirection);
+ litColor = lightColor * dot(vertex.normal, lightDirection);
return (projPos, litColor);
}
@@ -134,11 +134,11 @@ Andres Colubri
The PShader class
@@ -167,7 +167,7 @@ The PShader class
void draw() {
shader(toon);
- background(0);
+ background(0);
float dirY = (mouseY / float(height) - 0.5) * 2;
float dirX = (mouseX / float(width) - 0.5) * 2;
directionalLight(204, 204, 204, -dirX, -dirY, -1);
@@ -181,7 +181,7 @@ The PShader class
uniform mat3 normalMatrix;
uniform vec3 lightNormal;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
@@ -190,7 +190,7 @@ The PShader class
varying vec3 vertLightDir;
void main() {
- gl_Position = transform * vertex;
+ gl_Position = transform * position;
vertColor = color;
vertNormal = normalize(normalMatrix * normal);
vertLightDir = -lightNormal;
@@ -203,15 +203,13 @@ The PShader class
precision mediump int;
#endif
-#define PROCESSING_LIGHT_SHADER
-
uniform float fraction;
varying vec4 vertColor;
varying vec3 vertNormal;
varying vec3 vertLightDir;
-void main() {
+void main() {
float intensity;
vec4 color;
intensity = max(0.0, dot(vertLightDir, vertNormal));
@@ -226,14 +224,14 @@ The PShader class
color = vec4(vec3(0.2), 1.0);
}
- gl_FragColor = color * vertColor;
+ gl_FragColor = color * vertColor;
}
The PShader class
Types of shaders in Processing
Types of shaders in Processing
-
void draw() {
shader(pointShader, POINTS);
shader(lineShader, LINES);
- shader(polyShader); // same as shader(polyShader, TRIANGLE);
+ shader(polyShader); // Processing will autodetect
stroke(255);
beginShape(POLYGON);
@@ -282,7 +280,7 @@
Types of shaders in Processing
Types of shaders in Processing
Types of shaders in Processing
-shader(simpleShader);
-noLights();
-fill(180);
-rect(0, 0, 100, 100);
-
-
-
-shader(simpleShader);
-lights();
-fill(180);
-rect(0, 0, 100, 100);
-
-
-
-
-Color shaders
Color shaders
can = createCan(100, 200, 32);
}
-void draw() {
+void draw() {
background(0);
translate(width/2, height/2);
- rotateY(angle);
- shape(can);
+ rotateY(angle);
+ shape(can);
angle += 0.01;
}
@@ -399,9 +364,9 @@ Color shaders
float u = float(i) / detail;
sh.normal(x, 0, z);
sh.vertex(x * r, -h/2, z * r, u, 0);
- sh.vertex(x * r, +h/2, z * r, u, 1);
+ sh.vertex(x * r, +h/2, z * r, u, 1);
}
- sh.endShape();
+ sh.endShape();
return sh;
}
@@ -422,17 +387,15 @@ Color shaders
colorvert.glsl:
-#define PROCESSING_COLOR_SHADER
-
uniform mat4 transform;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
varying vec4 vertColor;
void main() {
- gl_Position = transform * vertex;
+ gl_Position = transform * position;
vertColor = color;
}
@@ -456,7 +419,7 @@ Color shaders
Now, we need to make two changes to our main program to make use of our new shader. At the end of our setup function we need to add
- colorShader = loadShader("colorfrag.glsl", "colorvert.glsl");
+ colorShader = loadShader("colorfrag.glsl", "colorvert.glsl");
Color shaders
Texture shaders
PShader texShader;
void setup() {
- size(640, 360, P3D);
+ size(640, 360, P3D);
label = loadImage("lachoy.jpg");
can = createCan(100, 200, 32, label);
texShader = loadShader("texfrag.glsl", "texvert.glsl");
}
-void draw() {
+void draw() {
background(0);
- shader(texShader);
+ shader(texShader);
translate(width/2, height/2);
- rotateY(angle);
- shape(can);
+ rotateY(angle);
+ shape(can);
angle += 0.01;
}
@@ -529,20 +492,18 @@ Texture shaders
float u = float(i) / detail;
sh.normal(x, 0, z);
sh.vertex(x * r, -h/2, z * r, u, 0);
- sh.vertex(x * r, +h/2, z * r, u, 1);
+ sh.vertex(x * r, +h/2, z * r, u, 1);
}
- sh.endShape();
+ sh.endShape();
return sh;
}
texvert.glsl:
-#define PROCESSING_TEXTURE_SHADER
-
uniform mat4 transform;
uniform mat4 texMatrix;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
@@ -550,8 +511,8 @@ Texture shaders
varying vec4 vertTexCoord;
void main() {
- gl_Position = transform * vertex;
-
+ gl_Position = transform * position;
+
vertColor = color;
vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
}
@@ -588,7 +549,7 @@ Texture shaders
void main() {
int si = int(vertTexCoord.s * 50.0);
- int sj = int(vertTexCoord.t * 50.0);
+ int sj = int(vertTexCoord.t * 50.0);
gl_FragColor = texture2D(texture, vec2(float(si) / 50.0, float(sj) / 50.0)) * vertColor;
}
@@ -626,7 +587,7 @@ Light shaders
lightShader = loadShader("lightfrag.glsl", "lightvert.glsl");
}
-void draw() {
+void draw() {
background(0);
shader(lightShader);
@@ -634,35 +595,33 @@ Light shaders
pointLight(255, 255, 255, width/2, height, 200);
translate(width/2, height/2);
- rotateY(angle);
- shape(can);
+ rotateY(angle);
+ shape(can);
angle += 0.01;
}
lightvert.glsl:
-#define PROCESSING_LIGHT_SHADER
-
uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;
uniform vec4 lightPosition;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
varying vec4 vertColor;
void main() {
- gl_Position = transform * vertex;
- vec3 ecVertex = vec3(modelview * vertex);
+ gl_Position = transform * position;
+ vec3 ecPosition = vec3(modelview * position);
vec3 ecNormal = normalize(normalMatrix * normal);
- vec3 direction = normalize(lightPosition.xyz - ecVertex);
+ vec3 direction = normalize(lightPosition.xyz - ecPosition);
float intensity = max(0.0, dot(direction, ecNormal));
- vertColor = vec4(intensity, intensity, intensity, 1) * color;
+ vertColor = vec4(intensity, intensity, intensity, 1) * color;
}
lightfrag.glsl:
@@ -682,7 +641,7 @@ Light shaders
Light shaders
Light shaders
pixlightvert.glsl:
-#define PROCESSING_LIGHT_SHADER
-
uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;
@@ -723,7 +680,7 @@
Light shaders
uniform vec4 lightPosition;
uniform vec3 lightNormal;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
@@ -732,11 +689,11 @@ Light shaders
varying vec3 lightDir;
void main() {
- gl_Position = transform * vertex;
- vec3 ecVertex = vec3(modelview * vertex);
-
+ gl_Position = transform * position;
+ vec3 ecPosition = vec3(modelview * position);
+
ecNormal = normalize(normalMatrix * normal);
- lightDir = normalize(lightPosition.xyz - ecVertex);
+ lightDir = normalize(lightPosition.xyz - ecPosition);
vertColor = color;
}
@@ -751,7 +708,7 @@ Light shaders
varying vec3 ecNormal;
varying vec3 lightDir;
-void main() {
+void main() {
vec3 direction = normalize(lightDir);
vec3 normal = normalize(ecNormal);
float intensity = max(0.0, dot(direction, normal));
@@ -792,29 +749,27 @@ Texture-light shaders
PShader texlightShader;
void setup() {
- size(640, 360, P3D);
+ size(640, 360, P3D);
label = loadImage("lachoy.jpg");
can = createCan(100, 200, 32, label);
texlightShader = loadShader("texlightfrag.glsl", "texlightvert.glsl");
}
-void draw() {
+void draw() {
background(0);
shader(texlightShader);
- pointLight(255, 255, 255, width/2, height, 200);
+ pointLight(255, 255, 255, width/2, height, 200);
translate(width/2, height/2);
- rotateY(angle);
- shape(can);
+ rotateY(angle);
+ shape(can);
angle += 0.01;
}
texlightvert.glsl:
-#define PROCESSING_TEXLIGHT_SHADER
-
uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;
@@ -822,7 +777,7 @@ Texture-light shaders
uniform vec4 lightPosition;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
attribute vec2 texCoord;
@@ -831,15 +786,15 @@ Texture-light shaders
varying vec4 vertTexCoord;
void main() {
- gl_Position = transform * vertex;
- vec3 ecVertex = vec3(modelview * vertex);
+ gl_Position = transform * position;
+ vec3 ecPosition = vec3(modelview * position);
vec3 ecNormal = normalize(normalMatrix * normal);
- vec3 direction = normalize(lightPosition.xyz - ecVertex);
+ vec3 direction = normalize(lightPosition.xyz - ecPosition);
float intensity = max(0.0, dot(direction, ecNormal));
- vertColor = vec4(intensity, intensity, intensity, 1) * color;
-
- vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
+ vertColor = vec4(intensity, intensity, intensity, 1) * color;
+
+ vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
}
texlightfrag.glsl:
@@ -871,8 +826,6 @@ Texture-light shaders
pixlightxvert.glsl:
-#define PROCESSING_TEXLIGHT_SHADER
-
uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;
@@ -880,7 +833,7 @@
Texture-light shaders
uniform vec4 lightPosition;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;
attribute vec2 texCoord;
@@ -891,14 +844,14 @@ Texture-light shaders
varying vec4 vertTexCoord;
void main() {
- gl_Position = transform * vertex;
- vec3 ecVertex = vec3(modelview * vertex);
-
- ecNormal = normalize(normalMatrix * normal);
- lightDir = normalize(lightPosition.xyz - ecVertex);
- vertColor = color;
-
- vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
+ gl_Position = transform * position;
+ vec3 ecPosition = vec3(modelview * position);
+
+ ecNormal = normalize(normalMatrix * normal);
+ lightDir = normalize(lightPosition.xyz - ecPosition);
+ vertColor = color;
+
+ vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0);
}
pixlightxfrag.glsl:
@@ -930,6 +883,19 @@ Texture-light shaders
Note that a texlight cannot be used to render a scene only with textures or only with lights, in those cases either a texture or light shader will be needed.
+Aliases for uniforms and attributes
+
+
+
+
+
Image post-processing effects
Image post-processing effects
precision mediump int;
#endif
-#define PROCESSING_TEXTURE_SHADER
-
uniform sampler2D texture;
varying vec4 vertColor;
@@ -958,7 +922,7 @@ Image post-processing effects
gl_FragColor = vertColor;
} else {
gl_FragColor = vec4(0, 0, 0, 1);
- }
+ }
}
@@ -977,20 +941,20 @@ Image post-processing effects
PShader bwShader;
void setup() {
- size(640, 360, P3D);
+ size(640, 360, P3D);
label = loadImage("lachoy.jpg");
can = createCan(100, 200, 32, label);
bwShader = loadShader("bwfrag.glsl");
}
-void draw() {
+void draw() {
background(0);
shader(bwShader);
translate(width/2, height/2);
- rotateY(angle);
- shape(can);
+ rotateY(angle);
+ shape(can);
angle += 0.01;
}
@@ -998,7 +962,7 @@ Image post-processing effects
Image post-processing effects
precision mediump int;
#endif
-#define PROCESSING_TEXTURE_SHADER
-
uniform sampler2D texture;
uniform vec2 texOffset;
@@ -1034,7 +996,7 @@ Image post-processing effects
vec2 tc6 = vertTexCoord.st + vec2(-texOffset.s, +texOffset.t);
vec2 tc7 = vertTexCoord.st + vec2( 0.0, +texOffset.t);
vec2 tc8 = vertTexCoord.st + vec2(+texOffset.s, +texOffset.t);
-
+
vec4 col0 = texture2D(texture, tc0);
vec4 col1 = texture2D(texture, tc1);
vec4 col2 = texture2D(texture, tc2);
@@ -1045,8 +1007,8 @@ Image post-processing effects
vec4 col7 = texture2D(texture, tc7);
vec4 col8 = texture2D(texture, tc8);
- vec4 sum = 8.0 * col4 - (col0 + col1 + col2 + col3 + col5 + col6 + col7 + col8);
- gl_FragColor = vec4(sum.rgb, 1.0) * vertColor;
+ vec4 sum = 8.0 * col4 - (col0 + col1 + col2 + col3 + col5 + col6 + col7 + col8);
+ gl_FragColor = vec4(sum.rgb, 1.0) * vertColor;
}
@@ -1061,8 +1023,6 @@ Image post-processing effects
precision mediump int;
#endif
-#define PROCESSING_TEXTURE_SHADER
-
uniform sampler2D texture;
uniform vec2 texOffset;
@@ -1078,7 +1038,7 @@ Image post-processing effects
vec2 tc3 = vertTexCoord.st + vec2(+texOffset.s, 0.0);
vec2 tc4 = vertTexCoord.st + vec2( 0.0, +texOffset.t);
vec2 tc5 = vertTexCoord.st + vec2(+texOffset.s, +texOffset.t);
-
+
vec4 col0 = texture2D(texture, tc0);
vec4 col1 = texture2D(texture, tc1);
vec4 col2 = texture2D(texture, tc2);
@@ -1088,7 +1048,7 @@ Image post-processing effects
vec4 sum = vec4(0.5) + (col0 + col1 + col2) - (col3 + col4 + col5);
float lum = dot(sum, lumcoeff);
- gl_FragColor = vec4(lum, lum, lum, 1.0) * vertColor;
+ gl_FragColor = vec4(lum, lum, lum, 1.0) * vertColor;
}
@@ -1133,13 +1093,13 @@ Putting all together
PShader embossShader;
void setup() {
- size(480, 480, P3D);
+ size(480, 480, P3D);
label = loadImage("lachoy.jpg");
can = createCan(canSize, 2 * canSize, 32, label);
cap = createCap(canSize, 32);
colorShader = loadShader("colorfrag.glsl", "colorvert.glsl");
- lightShader = loadShader("lightfrag.glsl", "lightvert.glsl");
+ lightShader = loadShader("lightfrag.glsl", "lightvert.glsl");
texShader = loadShader("texfrag.glsl", "texvert.glsl");
texlightShader = loadShader("texlightfrag.glsl", "texlightvert.glsl");
@@ -1153,10 +1113,10 @@ Putting all together
selShader = texlightShader;
useLight = true;
useTexture = true;
- println("Vertex lights, texture shading");
+ println("Vertex lights, texture shading");
}
-void draw() {
+void draw() {
background(0);
float x = 1.88 * canSize;
@@ -1181,7 +1141,7 @@ Putting all together
if (useLight) {
pointLight(255, 255, 255, centerx, centery, 200);
}
- shader(selShader);
+ shader(selShader);
translate(centerx, centery, 65);
rotateY(rotAngle);
@@ -1193,15 +1153,15 @@ Putting all together
shape(can);
noLights();
- resetShader();
+ resetShader();
pushMatrix();
- translate(0, canSize - 5, 0);
+ translate(0, canSize - 5, 0);
shape(cap);
popMatrix();
pushMatrix();
- translate(0, -canSize + 5, 0);
+ translate(0, -canSize + 5, 0);
shape(cap);
popMatrix();
@@ -1221,9 +1181,9 @@ Putting all together
float u = float(i) / detail;
sh.normal(x, 0, z);
sh.vertex(x * r, -h/2, z * r, u, 0);
- sh.vertex(x * r, +h/2, z * r, u, 1);
+ sh.vertex(x * r, +h/2, z * r, u, 1);
}
- sh.endShape();
+ sh.endShape();
return sh;
}
@@ -1240,7 +1200,7 @@ Putting all together
sh.vertex(x * r, 0, z * r);
}
sh.endShape();
- return sh;
+ return sh;
}
void keyPressed() {
@@ -1248,47 +1208,47 @@ Putting all together
println("No lights, no texture shading");
selShader = colorShader;
useLight = false;
- useTexture = false;
+ useTexture = false;
} else if (key == '2') {
println("Vertex lights, no texture shading");
selShader = lightShader;
useLight = true;
- useTexture = false;
+ useTexture = false;
} else if (key == '3') {
println("No lights, texture shading");
selShader = texShader;
useLight = false;
- useTexture = true;
+ useTexture = true;
} else if (key == '4') {
println("Vertex lights, texture shading");
selShader = texlightShader;
useLight = true;
- useTexture = true;
+ useTexture = true;
} else if (key == '5') {
println("Pixel lights, no texture shading");
selShader = pixlightShader;
useLight = true;
- useTexture = false;
+ useTexture = false;
} else if (key == '6') {
println("Pixel lights, texture shading");
selShader = texlightxShader;
useLight = true;
- useTexture = true;
+ useTexture = true;
} else if (key == '7') {
println("Black&white texture filtering");
selShader = bwShader;
useLight = false;
- useTexture = true;
+ useTexture = true;
} else if (key == '8') {
println("Edge detection filtering");
selShader = edgesShader;
useLight = false;
- useTexture = true;
+ useTexture = true;
} else if (key == '9') {
println("Emboss filtering");
selShader = embossShader;
useLight = false;
- useTexture = true;
+ useTexture = true;
}
}
@@ -1343,32 +1303,30 @@ 10. Point and line shaders
background(0);
}
-void draw() {
+void draw() {
shader(pointShader, POINTS);
- if (mousePressed) {
+ if (mousePressed) {
point(mouseX, mouseY);
}
}
pointvert.glsl:
-#define PROCESSING_POINT_SHADER
-
uniform mat4 projection;
uniform mat4 modelview;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec2 offset;
varying vec4 vertColor;
void main() {
- vec4 pos = modelview * vertex;
+ vec4 pos = modelview * position;
vec4 clip = projection * pos;
-
+
gl_Position = clip + projection * vec4(offset, 0, 0);
-
+
vertColor = color;
}
@@ -1381,7 +1339,7 @@ 10. Point and line shaders
varying vec4 vertColor;
-void main() {
+void main() {
gl_FragColor = vertColor;
}
@@ -1414,7 +1372,7 @@ 10. Point and line shaders
pointShader.set("weight", weight);
cloud1 = loadImage("cloud1.png");
cloud2 = loadImage("cloud2.png");
- cloud3 = loadImage("cloud3.png");
+ cloud3 = loadImage("cloud3.png");
pointShader.set("sprite", cloud1);
strokeWeight(weight);
@@ -1424,9 +1382,9 @@ 10. Point and line shaders
background(0);
}
-void draw() {
+void draw() {
shader(pointShader, POINTS);
- if (mousePressed) {
+ if (mousePressed) {
point(mouseX, mouseY);
}
}
@@ -1443,14 +1401,12 @@ 10. Point and line shaders
spritevert.glsl:
-#define PROCESSING_POINT_SHADER
-
uniform mat4 projection;
uniform mat4 modelview;
uniform float weight;
-
-attribute vec4 vertex;
+
+attribute vec4 position;
attribute vec4 color;
attribute vec2 offset;
@@ -1458,13 +1414,13 @@ 10. Point and line shaders
varying vec2 texCoord;
void main() {
- vec4 pos = modelview * vertex;
+ vec4 pos = modelview * position;
vec4 clip = projection * pos;
-
+
gl_Position = clip + projection * vec4(offset, 0, 0);
-
+
texCoord = (vec2(0.5) + offset / weight);
-
+
vertColor = color;
}
@@ -1480,7 +1436,7 @@ 10. Point and line shaders
varying vec4 vertColor;
varying vec2 texCoord;
-void main() {
+void main() {
gl_FragColor = texture2D(sprite, texCoord) * vertColor;
}
@@ -1500,7 +1456,7 @@ 10. Point and line shaders
![]()
10. Point and line shaders
void setup() {
size(640, 360, P3D);
- pointShader = loadShader("pointfrag.glsl", "pointvert.glsl");
+ pointShader = loadShader("pointfrag.glsl", "pointvert.glsl");
pointShader.set("sharpness", 0.9);
strokeCap(SQUARE);
- background(0);
+ background(0);
}
void draw() {
@@ -1531,19 +1487,17 @@ 10. Point and line shaders
pointShader.set("weight", w);
strokeWeight(w);
- stroke(random(255), random(255), random(255));
+ stroke(random(255), random(255), random(255));
point(mouseX, mouseY);
}
}
pointvert.glsl:
-#define PROCESSING_POINT_SHADER
-
uniform mat4 projection;
uniform mat4 transform;
-
-attribute vec4 vertex;
+
+attribute vec4 position;
attribute vec4 color;
attribute vec2 offset;
@@ -1552,9 +1506,9 @@ 10. Point and line shaders
varying vec2 pos;
void main() {
- vec4 clip = transform * vertex;
+ vec4 clip = transform * position;
gl_Position = clip + projection * vec4(offset, 0, 0);
-
+
vertColor = color;
center = clip.xy;
pos = offset;
@@ -1574,12 +1528,12 @@ 10. Point and line shaders
varying vec2 center;
varying vec2 pos;
-void main() {
+void main() {
float len = weight/2.0 - length(pos);
vec4 color = vec4(1.0, 1.0, 1.0, len);
- color = mix(vec4(0.0), color, sharpness);
- color = clamp(color, 0.0, 1.0);
- gl_FragColor = color * vertColor;
+ color = mix(vec4(0.0), color, sharpness);
+ color = clamp(color, 0.0, 1.0);
+ gl_FragColor = color * vertColor;
}
@@ -1631,37 +1585,35 @@ 10. Point and line shaders
linevert.glsl:
-#define PROCESSING_LINE_SHADER
-
uniform mat4 transform;
uniform vec4 viewport;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec4 direction;
varying vec4 vertColor;
-
+
vec3 clipToWindow(vec4 clip, vec4 viewport) {
vec3 dclip = clip.xyz / clip.w;
vec2 xypos = (dclip.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw;
return vec3(xypos, dclip.z * 0.5 + 0.5);
}
-
+
void main() {
- vec4 clip0 = transform * vertex;
+ vec4 clip0 = transform * position;
vec4 clip1 = clip0 + transform * vec4(direction.xyz, 0);
float thickness = direction.w;
-
- vec3 win0 = clipToWindow(clip0, viewport);
- vec3 win1 = clipToWindow(clip1, viewport);
+
+ vec3 win0 = clipToWindow(clip0, viewport);
+ vec3 win1 = clipToWindow(clip1, viewport);
vec2 tangent = win1.xy - win0.xy;
-
+
vec2 normal = normalize(vec2(-tangent.y, tangent.x));
vec2 offset = normal * thickness;
gl_Position.xy = clip0.xy + offset.xy;
gl_Position.zw = clip0.zw;
- vertColor = color;
+ vertColor = color;
}
linefrag.glsl:
@@ -1733,40 +1685,38 @@ 10. Point and line shaders
linevert.glsl:
-#define PROCESSING_LINE_SHADER
-
uniform mat4 transform;
uniform vec4 viewport;
-attribute vec4 vertex;
+attribute vec4 position;
attribute vec4 color;
attribute vec4 direction;
varying vec2 center;
varying vec2 normal;
varying vec4 vertColor;
-
+
vec3 clipToWindow(vec4 clip, vec4 viewport) {
vec3 dclip = clip.xyz / clip.w;
vec2 xypos = (dclip.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw;
return vec3(xypos, dclip.z * 0.5 + 0.5);
}
-
+
void main() {
- vec4 clip0 = transform * vertex;
+ vec4 clip0 = transform * position;
vec4 clip1 = clip0 + transform * vec4(direction.xyz, 0);
float thickness = direction.w;
-
- vec3 win0 = clipToWindow(clip0, viewport);
- vec3 win1 = clipToWindow(clip1, viewport);
+
+ vec3 win0 = clipToWindow(clip0, viewport);
+ vec3 win1 = clipToWindow(clip1, viewport);
vec2 tangent = win1.xy - win0.xy;
-
+
normal = normalize(vec2(-tangent.y, tangent.x));
vec2 offset = normal * thickness;
gl_Position.xy = clip0.xy + offset.xy;
gl_Position.zw = clip0.zw;
- vertColor = color;
-
+ vertColor = color;
+
center = (win0.xy + win1.xy) / 2.0;
}
@@ -1785,14 +1735,14 @@ 10. Point and line shaders
void main() {
vec2 v = gl_FragCoord.xy - center;
- float alpha = 1.0 - abs(2.0 * dot(normalize(normal), v) / weight);
+ float alpha = 1.0 - abs(2.0 * dot(normalize(normal), v) / weight);
gl_FragColor = vec4(vertColor.rgb, alpha);
}
-10. Point and line shaders
-
diff --git a/content/static/tutorials/pvector/imgs/add.svg b/content/static/tutorials/pvector/imgs/add.svg
index ce3a5376e..0a398a332 100644
--- a/content/static/tutorials/pvector/imgs/add.svg
+++ b/content/static/tutorials/pvector/imgs/add.svg
@@ -1,38 +1,74 @@
-
+
Daniel Shiffman
Vectors: You Complete Me
@@ -410,7 +410,7 @@ Vectors: More Algebra
w = (-9, 21)
-
+
The function inside the PVector class therefore is written as:
diff --git a/content/static/tutorials/sound/index.html b/content/static/tutorials/sound/index.html
index 4fecd9535..e1fada6b0 100644
--- a/content/static/tutorials/sound/index.html
+++ b/content/static/tutorials/sound/index.html
@@ -80,10 +80,6 @@
Sound and musical informatics
This representation of sound, as a discrete “frame” of frequencies and amplitudes independent of time, is more akin to the way in which we perceive our sonic environment than the raw pressure wave of the time domain. Jean-Baptiste-Joseph Fourier, a nineteenth-century French mathematician, developed the equations that allow us to translate a sound pressure wave (no matter how complex) into its constituent frequencies and amplitudes. This Fourier transform is an important tool in working with sound in the computer.
- Tools for sound programming
Example 1, 2: Synthesizer
-/**
- * Processing Sound Library, Example 1
- *
- * Five sine waves are layered to construct a cluster of frequencies.
- * This method is called additive synthesis. Use the mouse position
- * inside the display window to detune the cluster.
- */
-
-import processing.sound.*;
-
-SinOsc[] sineWaves; // Array of sines
-float[] sineFreq; // Array of frequencies
-int numSines = 5; // Number of oscillators to use
-
-void setup() {
- size(640, 360);
- background(255);
-
- sineWaves = new SinOsc[numSines]; // Initialize the oscillators
- sineFreq = new float[numSines]; // Initialize array for Frequencies
-
- for (int i = 0; i < numSines; i++) {
- // Calculate the amplitude for each oscillator
- float sineVolume = (1.0 / numSines) / (i + 1);
- // Create the oscillators
- sineWaves[i] = new SinOsc(this);
- // Start Oscillators
- sineWaves[i].play();
- // Set the amplitudes for all oscillators
- sineWaves[i].amp(sineVolume);
- }
+/**
+ * Processing Sound Library, Example 1
+ *
+ * Five sine waves are layered to construct a cluster of frequencies.
+ * This method is called additive synthesis. Use the mouse position
+ * inside the display window to detune the cluster.
+ */
+
+import processing.sound.*;
+
+SinOsc[] sineWaves; // Array of sines
+float[] sineFreq; // Array of frequencies
+int numSines = 5; // Number of oscillators to use
+
+void setup() {
+ size(640, 360);
+ background(255);
+
+ sineWaves = new SinOsc[numSines]; // Initialize the oscillators
+ sineFreq = new float[numSines]; // Initialize array for Frequencies
+
+ for (int i = 0; i < numSines; i++) {
+ // Calculate the amplitude for each oscillator
+ float sineVolume = (1.0 / numSines) / (i + 1);
+ // Create the oscillators
+ sineWaves[i] = new SinOsc(this);
+ // Start Oscillators
+ sineWaves[i].play();
+ // Set the amplitudes for all oscillators
+ sineWaves[i].amp(sineVolume);
+ }
}
-void draw() {
- //Map mouseY from 0 to 1
- float yoffset = map(mouseY, 0, height, 0, 1);
- //Map mouseY logarithmically to 150 - 1150 to create a base frequency range
- float frequency = pow(1000, yoffset) + 150;
- //Use mouseX mapped from -0.5 to 0.5 as a detune argument
- float detune = map(mouseX, 0, width, -0.5, 0.5);
-
- for (int i = 0; i < numSines; i++) {
- sineFreq[i] = frequency * (i + 1 * detune);
- // Set the frequencies for all oscillators
- sineWaves[i].freq(sineFreq[i]);
- }
+void draw() {
+ //Map mouseY from 0 to 1
+ float yoffset = map(mouseY, 0, height, 0, 1);
+ //Map mouseY logarithmically to 150 - 1150 to create a base frequency range
+ float frequency = pow(1000, yoffset) + 150;
+ //Use mouseX mapped from -0.5 to 0.5 as a detune argument
+ float detune = map(mouseX, 0, width, -0.5, 0.5);
+
+ for (int i = 0; i < numSines; i++) {
+ sineFreq[i] = frequency * (i + 1 * detune);
+ // Set the frequencies for all oscillators
+ sineWaves[i].freq(sineFreq[i]);
+ }
}
-/**
- * Processing Sound Library, Example 2
- *
- * This sketch shows how to use envelopes and oscillators.
- * Envelopes describe to course of amplitude over time.
- * The Sound library provides an ASR envelope which stands for
- * attack, sustain, release.
- *
- * .________
- * . ---
- * . ---
- * . ---
- * A S R
- */
-
-import processing.sound.*;
-
-// Oscillator and envelope
-TriOsc triOsc;
-Env env;
-
-// Times and levels for the ASR envelope
-float attackTime = 0.001;
-float sustainTime = 0.004;
-float sustainLevel = 0.2;
-float releaseTime = 0.2;
-
-// This is an octave in MIDI notes.
-int[] midiSequence = {
- 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72
-};
-
-// Set the duration between the notes
-int duration = 200;
-// Set the note trigger
-int trigger = 0;
-
-// An index to count up the notes
-int note = 0;
-
-void setup() {
- size(640, 360);
- background(255);
-
- // Create triangle wave and envelope
- triOsc = new TriOsc(this);
- env = new Env(this);
+/**
+ * Processing Sound Library, Example 2
+ *
+ * This sketch shows how to use envelopes and oscillators.
+ * Envelopes describe to course of amplitude over time.
+ * The Sound library provides an ASR envelope which stands for
+ * attack, sustain, release.
+ *
+ * .________
+ * . ---
+ * . ---
+ * . ---
+ * A S R
+ */
+
+import processing.sound.*;
+
+TriOsc triOsc;
+Env env;
+
+// Times and levels for the ASR envelope
+float attackTime = 0.001;
+float sustainTime = 0.004;
+float sustainLevel = 0.3;
+float releaseTime = 0.2;
+
+// This is an octave in MIDI notes.
+int[] midiSequence = { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72 };
+
+// Play a new note every 200ms
+int duration = 200;
+
+// This variable stores the point in time when the next note should be triggered
+int trigger = millis();
+
+// An index to count up the notes
+int note = 0;
+
+void setup() {
+ size(640, 360);
+ background(255);
+
+ // Create triangle wave and start it
+ triOsc = new TriOsc(this);
+
+ // Create the envelope
+ env = new Env(this);
}
-void draw() {
+void draw() {
- // If value of trigger is equal to the computer clock and if not all
- // notes have been played yet, the next note gets triggered.
- if ((millis() > trigger) && (note<midiSequence.length)) {
+ // If the determined trigger moment in time matches up with the computer clock and
+ // the sequence of notes hasn't been finished yet, the next note gets played.
+ if ((millis() > trigger) && (note<midiSequence.length)) {
- // midiToFreq transforms the MIDI value into a frequency in Hz which we use
- //to control the triangle oscillator with an amplitute of 0.8
- triOsc.play(midiToFreq(midiSequence[note]), 0.8);
+ // midiToFreq transforms the MIDI value into a frequency in Hz which we use to
+ // control the triangle oscillator with an amplitute of 0.5
+ triOsc.play(midiToFreq(midiSequence[note]), 0.5);
- // The envelope gets triggered with the oscillator as input and the times and
- // levels we defined earlier
- env.play(triOsc, attackTime, sustainTime, sustainLevel, releaseTime);
+ // The envelope gets triggered with the oscillator as input and the times and
+ // levels we defined earlier
+ env.play(triOsc, attackTime, sustainTime, sustainLevel, releaseTime);
- // Create the new trigger according to predefined durations and speed
- trigger = millis() + duration;
+ // Create the new trigger according to predefined duration
+ trigger = millis() + duration;
- // Advance by one note in the midiSequence;
- note++;
+ // Advance by one note in the midiSequence;
+ note++;
- // Loop the sequence
- if (note == 12) {
- note = 0;
- }
- }
-}
+ // Loop the sequence, notice the jitter
+ if (note == 12) {
+ note = 0;
+ }
+ }
+}
-// This function calculates the respective frequency of a MIDI note
-float midiToFreq(int note) {
- return (pow(2, ((note-69)/12.0)))*440;
+// This helper function calculates the respective frequency of a MIDI note
+float midiToFreq(int note) {
+ return (pow(2, ((note-69)/12.0))) * 440;
}
-
+
@@ -384,97 +380,96 @@ Example 3, 4: Sample playback
-/**
- * Processing Sound Library, Example 3
- *
- * This example shows how to make a simple sampler and sequencer
- * with the Sound library. In this sketch, five different samples are
- * loaded and played back at different pitches, in this case five
- * different octaves. The sequencer triggers an event every 200-1000
- * milliseconds randomly. Each time a sound is played a colored
- * rect with a random color is displayed.
- */
-
-import processing.sound.*;
-
-SoundFile[] files;
-
-// Create an array of values which represent the octaves.
-// 1.0 is playback at normal speed, 0.5 is half and therefore
-// one octave down. 2.0 is double so one octave up.
-float[] octave = {
- 0.25, 0.5, 1.0, 2.0, 4.0
-};
-
-// The playSound array is defining how many samples will be
-// played at each trigger event
-int[] playSound = {
- 1, 1, 1, 1, 1
-};
-
-// The trigger is an integer number in milliseconds so we
-// can schedule new events in the draw loop
-int trigger=0;
-
-// This array holds the pixel positions of the rectangles
-// that are drawn each event
-int[] posx = {
- 0, 128, 256, 384, 512
-};
-
-
-void setup() {
- size(640, 360);
- background(255);
-
- // Create an array of 5 empty soundfiles
- files = new SoundFile[5];
-
- // Load 5 soundfiles from a folder in a for loop. By naming
- // the files 1., 2., 3., [...], n.aif it is easy to iterate
- // through the folder and load all files in one line of code.
- for (int i = 0; i < files.length; i++) {
- files[i] = new SoundFile(this, (i+1) + ".aif");
- }
+/**
+ * Processing Sound Library, Example 3
+ *
+ * This example shows how to make a simple sampler and sequencer
+ * with the Sound library. In this sketch, five different samples are
+ * loaded and played back at different pitches, in this case five
+ * different octaves. The sequencer triggers an event every 200-1000
+ * milliseconds randomly. Each time a sound is played a colored
+ * rect with a random color is displayed.
+ *
+ * Load this example with included sound files from the Processing Editor:
+ * Examples > Libraries > Sound > Soundfile > Sampler
+ */
+
+import processing.sound.*;
+
+SoundFile[] file;
+
+// Define the number of samples
+int numsounds = 5;
+
+// Create an array of values which represent the octaves.
+// 1.0 is playback at normal speed, 0.5 is half and
+// therefore one octave down. 2.0 is double so one octave up.
+float[] octave = {0.25, 0.5, 1.0, 2.0, 4.0};
+
+// The playSound array is defining how many samples will
+// be played at each trigger event
+int[] playSound = {1, 1, 1, 1, 1};
+
+// The trigger is an integer number in milliseconds so we
+// can schedule new events in the draw loop
+int trigger;
+
+// This array holds the pixel positions of the rectangles
+// which are drawn each event
+int[] posx = {0, 128, 256, 384, 512};
+
+
+void setup() {
+ size(640, 360);
+ background(255);
+
+ // Create an array of empty soundfiles
+ file = new SoundFile[numsounds];
+
+ // Load 5 soundfiles from a folder in a for loop.
+ // By naming the files 1., 2., 3., n.aif it is easy to iterate
+ // through the folder and load all files in one line of code.
+ for (int i = 0; i < numsounds; i++) {
+ file[i] = new SoundFile(this, (i+1) + ".aif");
+ }
+
+ // Create a trigger which will be the basis for our random sequencer.
+ trigger = millis();
}
-void draw() {
-
- // If the determined trigger moment in time matches up with
- // the computer clock events get triggered.
- if (millis() > trigger) {
-
- // Redraw the background every time to erase old rects
- background(255);
-
- // By iterating through the playSound array we check for
- // 1 or 0, 1 plays a sound and draws a rect, for 0 nothing happens
-
- for (int i = 0; i < files.length; i++) {
- // Check which indexes are 1 and 0.
- if (playSound[i] == 1) {
- float rate;
- // Choose a random color and get set to noStroke()
- fill(int(random(255)), int(random(255)), int(random(255)));
- noStroke();
- // Draw the rect in the positions we defined earlier in posx
- rect(posx[i], 50, 128, 260);
- // Choose a random index of the octave array
- rate = octave[int(random(0, 5))];
- // Play the soundfile from the array with the respective
- // rate and loop set to false
- files[i].play(rate, 1.0);
- }
-
- // Renew the indexes of playSound so that at the next event
- // the order is different and randomized.
- playSound[i] = int(random(0, 2));
- }
-
- // Create a new triggertime in the future, with a random offset
- // between 200 and 1000 milliseconds
- trigger = millis() + int(random(200, 1000));
- }
+void draw() {
+
+ // If the determined trigger moment in time matches up with the
+ // computer clock events get triggered.
+ if (millis() > trigger) {
+ // Redraw the background every time to erase old rects
+ background(255);
+
+ // By iterating through the playSound array we check for 1 or 0,
+ // 1 plays a sound and draws a rect, for 0 nothing happens.
+
+ for (int i = 0; i < numsounds; i++) {
+ // Check which indexes are 1 and 0.
+ if (playSound[i] == 1) {
+ float rate;
+ // Choose a random color and get set to noStroke()
+ fill(int(random(255)), int(random(255)), int(random(255)));
+ noStroke();
+ // Draw the rect in the positions we defined earlier in posx
+ rect(posx[i], 50, 128, 260);
+ // Choose a random index of the octave array
+ rate = octave[int(random(0, 5))];
+ // Play the soundfile from the array with the respective rate and loop set to false
+ file[i].play(rate, 1.0);
+ }
+
+ // Renew the indexes of playSound so that at the next event the order is different and randomized.
+ playSound[i] = int(random(0, 2));
+ }
+
+ // Create a new triggertime in the future, with a random offset between 200 and 1000 milliseconds
+ trigger = millis() + int(random(200, 1000));
+ }
}
@@ -482,81 +477,150 @@ Example 3, 4: Sample playback
-/**
- * Processing Sound Library, Example 4
- *
- * Five soundfiles are mapped to the numbers on the keyboard.
- * Numbers 1-5 are played back an octave lower and numbers
- * 6-0 an octave higher.
- */
-
-import processing.sound.*;
-
-AudioDevice device;
-SoundFile[] file;
-
-int red, green, blue;
-
-void setup() {
- size(640, 360);
- background(255);
-
- // Create an AudioDevice with low buffer size
- // and create an array containing 5 empty soundfiles
- device = new AudioDevice(this, 48000, 32);
- file = new SoundFile[5];
-
- // Load 5 soundfiles from a folder in a for loop.
- for (int i = 0; i < file.length; i++) {
- file[i] = new SoundFile(this, (i+1) + ".aif");
- }
+/**
+ * Processing Sound Library, Example 4
+ *
+ * This example shows how to make a simple keyboard-triggered sampler with the Sound
+ * library. In this sketch 5 different short samples are loaded and played back at
+ * different speeds, which also changes their perceived pitch by one or two octaves.
+ *
+ * Load this example with included sound files from the Processing Editor:
+ * Examples > Libraries > Sound > Soundfile > Keyboard
+ */
+
+import processing.sound.*;
+
+SoundFile[] file;
+
+// Define the number of samples
+int numsounds = 5;
+
+// Define a variable to store the randomly generated background color in
+int backgroundColor[] = {255, 255, 255};
+
+void setup() {
+ size(640, 360);
+
+ // Create a Sound renderer and an array of empty soundfiles
+ file = new SoundFile[numsounds];
+
+ // Load 5 soundfiles from a folder in a for loop. By naming
+ // the files 1.aif, 2.aif, 3.aif, ..., n.aif it is easy to iterate
+ // through the folder and load all files in one line of code.
+ for (int i = 0; i < numsounds; i++) {
+ file[i] = new SoundFile(this, (i+1) + ".aif");
+ }
}
-void draw() {
- background(red, green, blue);
+void draw() {
+ background(backgroundColor[0], backgroundColor[1], backgroundColor[2]);
}
-void keyPressed() {
- // Set a random background color each time you hit then number keys
- red=int(random(255));
- green=int(random(255));
- blue=int(random(255));
-
- // Assign a sound to each number on your keyboard. 1-5 play at
- // an octave below the original pitch of the file, 6-0 play at
- // an octave above.
- switch(key) {
- case '1':
- file[0].play(0.5, 1.0);
- break;
- case '2':
- file[1].play(0.5, 1.0);
- break;
- case '3':
- file[2].play(0.5, 1.0);
- break;
- case '4':
- file[3].play(0.5, 1.0);
- break;
- case '5':
- file[4].play(0.5, 1.0);
- break;
- case '6':
- file[0].play(2.0, 1.0);
- break;
- case '7':
- file[1].play(2.0, 1.0);
- break;
- case '8':
- file[2].play(2.0, 1.0);
- break;
- case '9':
- file[3].play(2.0, 1.0);
- break;
- case '0':
- file[4].play(2.0, 1.0);
- break;
- }
+void keyPressed() {
+ // We use a boolean helper variable to determine whether one of the branches
+ // of the switch-statement was activated or not
+ boolean validKey = true;
+
+ switch(key) {
+ case 'a':
+ file[0].play(0.5, 1.0);
+ break;
+
+ case 's':
+ file[1].play(0.5, 1.0);
+ break;
+
+ case 'd':
+ file[2].play(0.5, 1.0);
+ break;
+
+ case 'f':
+ file[3].play(0.5, 1.0);
+ break;
+
+ case 'g':
+ file[4].play(0.5, 1.0);
+ break;
+
+ case 'h':
+ file[0].play(1.0, 1.0);
+ break;
+
+ case 'j':
+ file[1].play(1.0, 1.0);
+ break;
+
+ case 'k':
+ file[2].play(1.0, 1.0);
+ break;
+
+ case 'l':
+ file[3].play(1.0, 1.0);
+ break;
+
+ case ';':
+ file[4].play(1.0, 1.0);
+ break;
+
+ case '\'':
+ file[0].play(2.0, 1.0);
+ break;
+
+ case 'q':
+ file[1].play(2.0, 1.0);
+ break;
+
+ case 'w':
+ file[2].play(2.0, 1.0);
+ break;
+
+ case 'e':
+ file[3].play(2.0, 1.0);
+ break;
+
+ case 'r':
+ file[4].play(2.0, 1.0);
+ break;
+
+ case 't':
+ file[0].play(3.0, 1.0);
+ break;
+
+ case 'y':
+ file[1].play(3.0, 1.0);
+ break;
+
+ case 'u':
+ file[2].play(3.0, 1.0);
+ break;
+
+ case 'i':
+ file[3].play(3.0, 1.0);
+ break;
+
+ case 'o':
+ file[4].play(3.0, 1.0);
+ break;
+
+ case 'p':
+ file[0].play(4.0, 1.0);
+ break;
+
+ case '[':
+ file[1].play(4.0, 1.0);
+ break;
+
+ // no valid key was pressed, store that information
+ default:
+ validKey = false;
+ }
+
+ // If a new sample playback was triggered, change the background color
+ if (validKey) {
+ for (int i = 0; i < 3; i++) {
+ backgroundColor[i] = int(random(255));
+ }
+ }
}
@@ -577,130 +641,134 @@ Example 5, 6: Audio analysis
-/**
- * Processing Sound Library, Example 5
- *
- * This sketch shows how to use the FFT class to analyze a stream
- * of sound. Change the variable bands to get more or less
- * spectral bands to work with. The smooth_factor variable determines
- * how much the signal will be smoothed on a scale form 0-1.
- */
-
-import processing.sound.*;
-
-// Declare the processing sound variables
-SoundFile sample;
-FFT fft;
-AudioDevice device;
-
-// Declare a scaling factor
-int scale = 5;
-
-// Define how many FFT bands we want
-int bands = 128;
-
-// declare a drawing variable for calculating rect width
-float r_width;
-
-// Create a smoothing vector
-float[] sum = new float[bands];
-
-// Create a smoothing factor
-float smooth_factor = 0.2;
-
-void setup() {
- size(640, 360);
- background(255);
-
- // If the Buffersize is larger than the FFT Size, the FFT will fail
- // so we set Buffersize equal to bands
- device = new AudioDevice(this, 44000, bands);
-
- // Calculate the width of the rects depending on how many bands we have
- r_width = width/float(bands);
-
- // Load and play a soundfile and loop it. This has to be called
- // before the FFT is created.
- sample = new SoundFile(this, "beat.aiff");
- sample.loop();
-
- // Create and patch the FFT analyzer
- fft = new FFT(this, bands);
- fft.input(sample);
-}
-
-void draw() {
- // Set background color, noStroke and fill color
- background(204);
- fill(0, 0, 255);
- noStroke();
-
- fft.analyze();
- for (int i = 0; i < bands; i++) {
- // Smooth the FFT data by smoothing factor
- sum[i] += (fft.spectrum[i] - sum[i]) * smooth_factor;
-
- // Draw the rects with a scale factor
- rect( i*r_width, height, r_width, -sum[i]*height*scale );
- }
+/**
+ * Processing Sound Library, Example 5
+ *
+ * This sketch shows how to use the FFT class to analyze a stream
+ * of sound. Change the number of bands to get more spectral bands
+ * (at the expense of more coarse-grained time resolution of the spectrum).
+ *
+ * Load this example with included sound files from the Processing Editor:
+ * Examples > Libraries > Sound > Analysis > FFTSpectrum
+ */
+
+import processing.sound.*;
+
+// Declare the sound source and FFT analyzer variables
+SoundFile sample;
+FFT fft;
+
+// Define how many FFT bands to use (this needs to be a power of two)
+int bands = 128;
+
+// Define a smoothing factor which determines how much the spectrums of consecutive
+// points in time should be combined to create a smoother visualisation of the spectrum.
+// A smoothing factor of 1.0 means no smoothing (only the data from the newest analysis
+// is rendered), decrease the factor down towards 0.0 to have the visualisation update
+// more slowly, which is easier on the eye.
+float smoothingFactor = 0.2;
+
+// Create a vector to store the smoothed spectrum data in
+float[] sum = new float[bands];
+
+// Variables for drawing the spectrum:
+// Declare a scaling factor for adjusting the height of the rectangles
+int scale = 5;
+// Declare a drawing variable for calculating the width of the
+float barWidth;
+
+public void setup() {
+ size(640, 360);
+ background(255);
+
+ // Calculate the width of the rects depending on how many bands we have
+ barWidth = width/float(bands);
+
+ // Load and play a soundfile and loop it.
+ sample = new SoundFile(this, "beat.aiff");
+ sample.loop();
+
+ // Create the FFT analyzer and connect the playing soundfile to it.
+ fft = new FFT(this, bands);
+ fft.input(sample);
}
-
-
-
-
-
-/**
- * Processing Sound Library, Example 6
- *
- * This sketch shows how to use the Amplitude class to analyze a
- * stream of sound. In this case a sample is analyzed. The smoothFactor
- * variable determines how much the signal will be smoothed on a scale
- * from 0 - 1.
- */
-
-import processing.sound.*;
-
-// Declare the processing sound variables
-SoundFile sample;
-Amplitude rms;
-
-// Declare a scaling factor
-float scale = 5.0;
-
-// Declare a smooth factor
-float smoothFactor = 0.25;
-
-// Used for smoothing
-float sum;
+public void draw() {
+ // Set background color, noStroke and fill color
+ background(125, 255, 125);
+ fill(255, 0, 150);
+ noStroke();
-void setup() {
- size(640, 360);
+ // Perform the analysis
+ fft.analyze();
- //Load and play a soundfile and loop it
- sample = new SoundFile(this, "beat.aiff");
- sample.loop();
+ for (int i = 0; i < bands; i++) {
+ // Smooth the FFT spectrum data by smoothing factor
+ sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor;
- // Create and patch the rms tracker
- rms = new Amplitude(this);
- rms.input(sample);
-}
-
-void draw() {
- // Set background color, noStroke and fill color
- background(0, 0, 255);
- noStroke();
- fill(255, 0, 150);
+ // Draw the rectangles, adjust their height using the scale factor
+ rect(i*barWidth, height, barWidth, -sum[i]*height*scale);
+ }
+}
- // Smooth the rms data by smoothing factor
- sum += (rms.analyze() - sum) * smoothFactor;
+
- // rms.analyze() return a value between 0 and 1. It's
- // scaled to height/2 and then multiplied by a scale factor
- float rmsScaled = sum * (height/2) * scale;
+
- // Draw an ellipse at a size based on the audio analysis
- ellipse(width/2, height/2, rmsScaled, rmsScaled);
+
+/**
+ * Processing Sound Library, Example 6
+ *
+ * This sketch shows how to use the Amplitude class to analyze the changing
+ * "loudness" of a stream of sound. In this case an audio sample is analyzed.
+ *
+ * Load this example with included sound files from the Processing Editor:
+ * Examples > Libraries > Sound > Analysis > PeakAmplitude
+ */
+
+import processing.sound.*;
+
+// Declare the processing sound variables
+SoundFile sample;
+Amplitude rms;
+
+// Declare a smooth factor to smooth out sudden changes in amplitude.
+// With a smooth factor of 1, only the last measured amplitude is used for the
+// visualisation, which can lead to very abrupt changes. As you decrease the
+// smooth factor towards 0, the measured amplitudes are averaged across frames,
+// leading to more pleasant gradual changes
+float smoothingFactor = 0.25;
+
+// Used for storing the smoothed amplitude value
+float sum;
+
+public void setup() {
+ size(640, 360);
+
+ //Load and play a soundfile and loop it
+ sample = new SoundFile(this, "beat.aiff");
+ sample.loop();
+
+ // Create and patch the rms tracker
+ rms = new Amplitude(this);
+ rms.input(sample);
+}
+
+public void draw() {
+ // Set background color, noStroke and fill color
+ background(125, 255, 125);
+ noStroke();
+ fill(255, 0, 150);
+
+ // smooth the rms data by smoothing factor
+ sum += (rms.analyze() - sum) * smoothingFactor;
+
+ // rms.analyze() return a value between 0 and 1. It's
+ // scaled to height/2 and then multiplied by a fixed scale factor
+ float rms_scaled = sum * (height/2) * 5;
+
+ // We draw a circle whose size is coupled to the audio analysis
+ ellipse(width/2, height/2, rms_scaled, rms_scaled);
}
diff --git a/content/static/tutorials/text/index.html b/content/static/tutorials/text/index.html
index a0415456f..4636aea5d 100644
--- a/content/static/tutorials/text/index.html
+++ b/content/static/tutorials/text/index.html
@@ -32,7 +32,7 @@ Where do we find documentation for the String class?
Animating Text
-
+Example Text Align
PFont f;
@@ -325,7 +325,7 @@
Animating Text
Here's the full example that displays a different headline each time the previous headline leaves the screen. The headlines are stored in a String array.
-
+Example Scrolling Headlines
// An array of news headlines
String[] headlines = {
@@ -374,7 +374,7 @@
Rotating text
-
+Example: Rotating Text
PFont f;
String message = "this text is spinning";
float theta;
@@ -496,7 +496,7 @@
Displaying text character by character
-
+Example Text breaking up
PFont f;
String message = "click mouse to shake it up";
// An array of Letter objects
@@ -575,7 +575,7 @@
Displaying text character by character
-
+Example Boxes along a curve
PFont f;
@@ -635,7 +635,7 @@
Displaying text character by character
-
+Example Characters along a curve
// The message to be displayed
String message = "text along a curve";
diff --git a/content/static/tutorials/transform2d/index.html b/content/static/tutorials/transform2d/index.html
index 115af7c22..5647b937f 100644
--- a/content/static/tutorials/transform2d/index.html
+++ b/content/static/tutorials/transform2d/index.html
@@ -118,7 +118,7 @@
What’s the Advantage?
is a lot more trouble than just adding to coordinates. For a simple example
like the rectangle, you are correct. But let’s take an example of
where translate() can make life easier. Here is some
-code that draws a row of houses. It uses a loop that calls
+code that draws a row of houses. It uses a loop that calls a
function named house(), which takes
the x and y location of the
house’s upper-left corner as its parameters.
@@ -410,7 +410,7 @@ The Transformation Matrix
Push and Pop
true
-
+
+-->
false
false
+ Draw text
Vector Fonts
diff --git a/content/static/tutorials/video/imgs/fig_16_01_capture.png b/content/static/tutorials/video/imgs/fig_16_01_capture.png
new file mode 100755
index 000000000..09bfc22ce
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_01_capture.png differ
diff --git a/content/static/tutorials/video/imgs/fig_16_02_tintvideo.png b/content/static/tutorials/video/imgs/fig_16_02_tintvideo.png
new file mode 100755
index 000000000..aa8c0cc35
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_02_tintvideo.png differ
diff --git a/content/static/tutorials/video/imgs/fig_16_03_flashlight.png b/content/static/tutorials/video/imgs/fig_16_03_flashlight.png
new file mode 100755
index 000000000..a395fa12c
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_03_flashlight.png differ
diff --git a/content/static/tutorials/video/imgs/fig_16_04_blankgrid.png b/content/static/tutorials/video/imgs/fig_16_04_blankgrid.png
new file mode 100755
index 000000000..75c47bd1d
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_04_blankgrid.png differ
diff --git a/content/static/tutorials/video/imgs/fig_16_05_pixelated.png b/content/static/tutorials/video/imgs/fig_16_05_pixelated.png
new file mode 100755
index 000000000..6e9c6b356
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_05_pixelated.png differ
diff --git a/content/static/tutorials/video/imgs/fig_16_06_mirror.png b/content/static/tutorials/video/imgs/fig_16_06_mirror.png
new file mode 100755
index 000000000..3af852ae3
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_06_mirror.png differ
diff --git a/content/static/tutorials/video/imgs/fig_16_07_blank_scribble.png b/content/static/tutorials/video/imgs/fig_16_07_blank_scribble.png
new file mode 100755
index 000000000..72fc30783
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_07_blank_scribble.png differ
diff --git a/content/static/tutorials/video/imgs/fig_16_08_scribblermirror.png b/content/static/tutorials/video/imgs/fig_16_08_scribblermirror.png
new file mode 100755
index 000000000..ecc48f703
Binary files /dev/null and b/content/static/tutorials/video/imgs/fig_16_08_scribblermirror.png differ
diff --git a/content/static/tutorials/video/index.html b/content/static/tutorials/video/index.html
new file mode 100644
index 000000000..22ccf759b
--- /dev/null
+++ b/content/static/tutorials/video/index.html
@@ -0,0 +1,575 @@
+
+
\ No newline at end of file
diff --git a/contrib_generate/broken.conf b/contrib_generate/broken.conf
index ba2c0c328..39f170b32 100644
--- a/contrib_generate/broken.conf
+++ b/contrib_generate/broken.conf
@@ -1,16 +1,12 @@
008
-009
-010
016
020
021
026
028
031
-032
033
047
-049
050
068
070
@@ -22,22 +18,13 @@
098
099
100
-105
-108
-109
110
-111
112
114
116
120
123
-126
129
-130
-132
136
141
-142
144
-146
\ No newline at end of file
diff --git a/contrib_generate/build_listing.py b/contrib_generate/build_listing.py
index f3509c067..2c4a43b22 100755
--- a/contrib_generate/build_listing.py
+++ b/contrib_generate/build_listing.py
@@ -139,7 +139,7 @@ def get_lib_locations(f):
contents = line.split('\\')
if len(contents) != 2:
- print 'Lines for contributions must be of the form "[Contribution ID] : [Contribution URL]"'
+ print 'Lines for contributions must be of the form "[Contribution ID] \ [Contribution URL]"'
print contents
continue
@@ -165,11 +165,11 @@ def missing_key(exports):
script = argv
conf = 'sources.conf'
fileout = 'contribs.txt'
- minrev = 0
+ minrev = 228
maxrev = 0
elif len(argv) == 3:
script, conf, fileout = argv
- minrev = 0
+ minrev = 228
maxrev = 0
elif len(argv) == 5:
script, conf, fileout, minrev, maxrev = argv
@@ -228,7 +228,7 @@ def missing_key(exports):
key = missing_key(exports)
if key:
- print 'Error reading', prop_url
+ print 'Error missing key', prop_url
print " No value for '%s'. Maybe it's a 404 page" % key
continue
# if no download is explicitly provided, use the default download url
diff --git a/contrib_generate/skipped.conf b/contrib_generate/skipped.conf
index 386563632..fb4891e7a 100644
--- a/contrib_generate/skipped.conf
+++ b/contrib_generate/skipped.conf
@@ -1,7 +1,7 @@
007
039
-041
050
051
052
+142
143
\ No newline at end of file
diff --git a/contrib_generate/sources.conf b/contrib_generate/sources.conf
index f0fbad2e7..8fc82f839 100644
--- a/contrib_generate/sources.conf
+++ b/contrib_generate/sources.conf
@@ -1,9 +1,10 @@
-# Next ID: 168
+# Next ID: 273
# Increment after assigning ID to new contribution
[Library : 3D]
-001 \ http://otrolado.info/proscene.txt
-009 \ http://hemesh.wblut.com/hemesh-latest.txt
+001 \ https://github.com/remixlab/proscene/releases/download/latest/proscene.txt
+006 \ http://www.die-seite.ch/colladaloader/colladaLoader.txt
+# 009 \ http://www.wblut.com/hemesh/hemesh.txt
017 \ http://mrfeinberg.com/peasycam/peasycam.txt
# 022 \ http://fluidforms.eu/processing/fluid-forms-libs/download/FluidFormsLibs.txt
032 \ http://n.clavaud.free.fr/processing/library/picking/download/Picking.txt
@@ -16,69 +17,108 @@
#404# 117 \ http://ccl.angusforbes.com/stereo.txt
120 \ https://simple-openni.googlecode.com/svn/trunk/SimpleOpenNI-2.0/dist/all/SimpleOpenNI.txt
123 \ http://igeo.jp/igeo.txt
-130 \ http://interfaze.info/libraries/planetarium/download/planetarium.txt
+130 \ https://github.com/codeanticode/planetarium/releases/download/latest/planetarium.txt
+174 \ https://ixora.io/downloads/camera3D/Camera3D.txt
+195 \ http://culebra.technology/culebra.txt
+196 \ https://github.com/jrc03c/queasycam/releases/download/latest/queasycam.txt
+215 \ http://maxlfarrell.gitlab.io/extruder/extruder.txt
+244 \ http://giftedapprentice.com/ewbIK/ewbIK.txt
+245 \ https://github.com/VisualComputing/nub/releases/download/latest/nub.txt
+252 \ http://www.bdhont.net/lunar.txt
[Library : Animation]
+001 \ https://github.com/remixlab/proscene/releases/download/latest/proscene.txt
003 \ http://www.looksgood.de/libraries/Ani/Ani-latest.txt
030 \ http://libraries.seltar.org/motion/motion.txt
033 \ http://ekeneijeoma.com/processing/ijeomamotion/download/ijeomamotion.txt
062 \ http://www.lagers.org.uk/processing/sprites/Sprites.txt
083 \ http://rdlester.github.com/hermes/downloads/hermes.txt
095 \ https://dl.dropbox.com/u/87680069/frames.txt
+219 \ https://teddavis.org/xyscope/download/XYscope.txt
+231 \ http://objectstothinkwith.com/tracer/tracer.txt
+244 \ http://giftedapprentice.com/ewbIK/ewbIK.txt
+245 \ https://github.com/VisualComputing/nub/releases/download/latest/nub.txt
+253 \ https://ztdp.ca/projects/school/Green/Green.txt
+272 \ https://fox-gieg.com/patches/processing/libraries/tiltProcessing/tiltProcessing.txt
[Library : Compilation]
004 \ http://staff.city.ac.uk/~jwo/giCentre/utils/gicentreUtils.txt
007 \ https://github.com/generative-design/GenerativeDesignLibrary2/releases/download/latest/generativedesign.txt
083 \ http://rdlester.github.com/hermes/downloads/hermes.txt
056 \ https://github.com/generative-design/GenerativeDesignLibrary3/releases/download/latest/generativedesign.txt
+200 \ http://shiffman.net/p5/libraries/processing3/toxiclibs/toxiclibs.txt
[Library : Data]
008 \ http://www.saint-clair.net/download/gml4u/GML4U.txt
-011 \ http://www.shiffman.net/p5/libraries/sftp/sftp.txt
+011 \ https://github.com/shiffman/SFTP-Processing/releases/download/latest/sftp.txt
012 \ http://www.shiffman.net/p5/libraries/qrcode/qrcodeprocessing.txt
040 \ http://r-s-g.org/carnivore/download/carnivore_p5lib.txt
# 042 \ http://wyldco.com/romefeeder/download/romefeeder.txt
044 \ http://www.reades.com/MapThing/MapThing.txt
-053 \ http://mrzl.net/yahooweather/YahooWeather.txt
+#053 \ http://mrzl.net/yahooweather/YahooWeather.txt
#404# 065 \ http://blog.stainpixels.com/public/share.txt
072 \ http://sojamo.de/libraries/oscp5/oscP5.txt
073 \ http://ubaa.net/shared/processing/udp/udp.txt
084 \ http://iddi.github.io/oocsi-processing/oocsi.txt
089 \ https://raw.githubusercontent.com/nok/soundcloud-processing/master/download/SoundCloud.txt
-#404# 103 \ http://hamzeen.github.io/ShortMessage/ShortMessage.txt
+103 \ http://hamzeen.github.io/ShortMessage/ShortMessage.txt
110 \ https://raw.github.com/fjenett/xlsreader-library-processing/latest/release/XlsReader.txt
-111 \ https://raw.github.com/fjenett/sql-library-processing/latest/release/BezierSQLib.txt
+111 \ https://github.com/benfry/sql-library-processing/raw/master/release/BezierSQLib.txt
115 \ http://s176381904.onlinehome.fr/processing/SignalFilter/download/signalFilter.txt
#404# 128 \ http://dasmithii.com/GNet.txt
133 \ https://raw.githubusercontent.com/nok/redis-processing/master/download/Redis.txt
135 \ https://temboo.com/files/temboo-processing.txt
-137 \ http://shiffman.net/p5/libraries/httprequests_processing/httprequests_processing.txt
+137 \ https://github.com/runemadsen/HTTP-Requests-for-Processing/releases/download/latest/httprequests_processing.txt
144 \ http://unfoldingmaps.org/Unfolding.txt
+175 \ https://github.com/alexandrainst/processing_websockets/releases/download/latest/webSockets.txt
+183 \ https://github.com/onlylemi/processing-android-capture/releases/download/latest/AndroidCaptureForProcessing.txt
+198 \ http://cagewebdev.com/zxing4p/zxing4p3.txt
+203 \ https://github.com/OliverColeman/hivis/releases/download/latest/HiVis.txt
+206 \ https://ap-sync.github.io/libs/AP_sync_processing/APsync.txt
+208 \ https://github.com/gohai/processing-simpletweet/releases/download/latest/processing-simpletweet.txt
+229 \ https://github.com/Shinhoo/Wooting-Keyboard-Library/releases/download/lastest/WootingKeyboard.txt
+230 \ https://github.com/cansik/artnet4j/releases/download/latest/artnet4j.txt
+241 \ http://agathelenclen.fr/downloads/Squarify.txt
+248 \ https://github.com/runwayml/processing-library/releases/download/latest/RunwayML.txt
+262 \ https://github.com/SamuelAl/SQuelized-for-Processing/releases/latest/download/SQuelized.txt
+267 \ https://github.com/cansik/deep-vision-processing/releases/download/contribution/deepvision.txt
+270 \ https://ronghaoliang.page/Weka4P/download/Weka4P.txt
[Library : Fabrication]
# 078 \ http://s373.net/code/marchingcubes/download/marchingcubes.txt
[Library : Geometry]
+001 \ https://github.com/remixlab/proscene/releases/download/latest/proscene.txt
038 \ http://www.ricardmarxer.com/geomerative/geomerative.txt
083 \ http://rdlester.github.com/hermes/downloads/hermes.txt
106 \ http://www.thecloudlab.org/processing/download/ComputationalGeometry.txt
113 \ http://sixthsensor.dk/code/p5/point2line/download/point2line.txt
+195 \ http://culebra.technology/culebra.txt
+204 \ https://github.com/thwegene/OCT/releases/download/latest/OCT.txt
+214 \ http://www.garciadelcastillo.es/dashedlines/dashedlines.txt
+231 \ http://objectstothinkwith.com/tracer/tracer.txt
+237 \ http://gicentre.org/handy/handy.txt
+241 \ http://agathelenclen.fr/downloads/Squarify.txt
[Library : GUI]
+001 \ https://github.com/remixlab/proscene/releases/download/latest/proscene.txt
046 \ http://www.lagers.org.uk/processing3/g4p/G4P.txt
051 \ http://www.lagers.org.uk/processing/g4p/G4P.txt
054 \ https://raw.github.com/fjenett/Guido/latest/releases/Guido.txt
058 \ http://www.sojamo.de/libraries/controlP5/controlP5.txt
# 061 \ https://dl.dropbox.com/u/87680069/piccolo2d.txt
+180 \ http://interfascia.berg.industries/download/interfascia.txt
+224 \ https://github.com/BillKujawa/meter/releases/download/latest/meter.txt
+237 \ http://gicentre.org/handy/handy.txt
+256 \ https://github.com/Milchreis/uibooster-for-processing/releases/latest/download/UiBooster.txt
[Library : Hardware]
-010 \ http://www.shiffman.net/p5/libraries/mpe/mpe.txt
015 \ http://www.shiffman.net/p5/libraries/sms/sms.txt
-024 \ http://playground.arduino.cc/uploads/Interfacing/processing2-arduino.txt
+024 \ https://github.com/firmata/processing/releases/download/latest/processing-arduino.txt
028 \ http://projects.formatlos.de/ambientlightsensor/download/AmbientLightSensor.txt
# 064 \ http://www.muvium.com/frappuccino/frappuccino.txt
-066 \ http://ketailibrary.org/ketai.txt
-071 \ http://cloud.github.com/downloads/hdavid/dmxP512/dmxP512.txt
+066 \ http://ketai.org/ketai.txt
+071 \ http://motscousus.com/stuff/2011-01_dmxP512/dmxP512.txt
090 \ https://dl.dropbox.com/u/87680069/LeapMotion.txt
# 102 \ http://s176381904.onlinehome.fr/processing/MoveLib/download/MoveLib.txt
104 \ http://arvydas.github.io/blinkstick-processing/download/BlinkStick.txt
@@ -86,29 +126,60 @@
145 \ http://www.heroicrobotics.com/software/PixelPusher.txt
155 \ https://raw.githubusercontent.com/nok/myo-processing/master/download/MyoForProcessing.txt
164 \ http://jorgecardoso.eu/processing/eyetribeprocessing/download/EyeTribeProcessing.txt
+188 \ http://developers.gausstoys.com/processing/GaussSense.txt
+189 \ http://ciaron.net/hpglgraphics/download/hpglgraphics.txt
+190 \ https://github.com/gohai/processing/releases/download/latest/io.txt
+# 197 \ https://github.com/sgeigers/Phidgets-For-Processing/releases/download/latest/PhidgetsForProcessing.txt
+211 \ https://github.com/diwi/PS3Eye/releases/download/latest/PS3Eye.txt
+218 \ https://github.com/cansik/sweep-processing/releases/download/latest/SweepProcessing.txt
+219 \ https://teddavis.org/xyscope/download/XYscope.txt
+224 \ https://github.com/BillKujawa/meter/releases/download/latest/meter.txt
+225 \ http://web.tecnico.ulisboa.pt/augusto.esteves/GazeTrack/GazeTrack.txt
+238 \ https://github.com/cansik/realsense-processing/releases/download/contributed/RealSenseProcessing.txt
+239 \ http://skweezee.net/processing/download/SkweezeeForProcessing.txt
+266 \ https://github.com/sgeigers/SimplePhidgets/releases/download/latest/SimplePhidgets.txt
+268 \ http://github.com/jaysonh/Dmx4Artists/releases/latest/download/Dmx4Artists.txt
[Library : I/O]
-006 \ http://www.die-seite.ch/colladaLoader.txt
+001 \ https://github.com/remixlab/proscene/releases/download/latest/proscene.txt
016 \ http://www.silentlycrashing.net/ezgestures/files/ezgestures.txt
025 \ http://jorgecardoso.eu/processing/NXTComm/NXTComm.txt
026 \ http://jorgecardoso.eu/processing/MindSetProcessing/download/MindsetProcessing.txt
-039 \ http://interfaze.info/libraries/tablet/download/v2/Tablet.txt
+039 \ https://github.com/codeanticode/tablet/releases/download/latestv2/Tablet.txt
060 \ https://dl.dropbox.com/u/87680069/gamepad.txt
067 \ http://www.graffitiresearchlab.de/wp-content/uploads/proJMS.txt
084 \ http://iddi.github.io/oocsi-processing/oocsi.txt
091 \ http://n-e-r-v-o-u-s.com/tools/obj/OBJExport.txt
-097 \ http://pif.github.com/android-select-file/download/SelectFile.txt
+097 \ https://andrusiv.com/android-select-file/download/SelectFile.txt
098 \ http://vialab.science.uoit.ca/smt/dl/SMT.txt
105 \ http://paulhertz.net/ignocodelib/download/IgnoCodeLib.txt
-121 \ http://interfaze.info/libraries/tablet/download/Tablet.txt
+121 \ https://github.com/codeanticode/tablet/releases/download/latest/Tablet.txt
136 \ http://www.extrapixel.ch/processing/gifAnimation/gifAnimation.txt
-139 \ http://erniejunior.github.io/VSync-for-Processing/download/VSync.txt
+139 \ http://ernestum.github.io/VSync-for-Processing/download/VSync.txt
143 \ http://www.lagers.org.uk/processing/gamecontrol/GameControlPlus.txt
167 \ http://www.lagers.org.uk/processing3/gamecontrol/GameControlPlus.txt
+168 \ http://transfluxus.github.io/SimpleHTTPServer/download/SimpleHTTPServer.txt
+171 \ https://github.com/gohai/processing-simpletouch/releases/download/latest/processing-simpletouch.txt
+172 \ http://transfluxus.github.io/drop/download/Drop.txt
+173 \ https://github.com/256dpi/processing-mqtt/releases/download/latest/mqtt.txt
+175 \ https://github.com/alexandrainst/processing_websockets/releases/download/latest/webSockets.txt
+177 \ https://github.com/keshrath/Console/releases/download/latest/Console.txt
+178 \ https://github.com/keshrath/ImageLoader/releases/download/latest/ImageLoader.txt
+179 \ https://github.com/keshrath/MuKCast/releases/download/latest/MuKCast.txt
+187 \ https://funprogramming.org/VideoExport-for-Processing/download/VideoExport.txt
+206 \ https://ap-sync.github.io/libs/AP_sync_processing/APsync.txt
+209 \ https://github.com/gohai/processing-simplereceiptprinter/releases/download/latest/processing-simplereceiptprinter.txt
+217 \ https://pierdr.github.io/Tramontana-for-Processing/tramontana.txt
+229 \ https://github.com/Shinhoo/Wooting-Keyboard-Library/releases/download/lastest/WootingKeyboard.txt
+232 \ https://github.com/haschdl/pLaunchController/releases/download/latest/pLaunchController.txt
+239 \ http://skweezee.net/processing/download/SkweezeeForProcessing.txt
+247 \ https://github.com/orgicus/image-sequence-player/releases/download/latest/ImageSequencePlayer.txt
+258 \ https://github.com/Transmedia-Gx/grab/releases/latest/download/Grab.txt
+269 \ http://augmenta-tech.com/libs/processing/Augmenta.txt
[Library : Language]
-063 \ http://www.rednoise.org/rita/RiTa.txt
-119 \ http://interfaze.info/libraries/eliza/download/Eliza.txt
+063 \ http://rednoise.org/rita/rita.txt
+119 \ https://github.com/codeanticode/eliza/releases/download/latest/Eliza.txt
[Library : Math]
021 \ http://www.gwoptics.org/processing/gwoptics_p5lib/download/gwoptics.txt
@@ -118,10 +189,14 @@
126 \ https://raw.github.com/jagracar/grafica/master/releases/grafica.txt
131 \ http://www.lagers.org.uk/processing/qscript/QScript.txt
156 \ http://www.lagers.org.uk/processing/jasmine/Jasmine.txt
+203 \ https://github.com/OliverColeman/hivis/releases/download/latest/HiVis.txt
+251 \ https://github.com/pallav12/matrixMath-for-processing/releases/download/latest/MatrixMath.txt
[Library : Other]
093 \ http://www.lagers.org.uk/processing/pathfinder/Path_Finder.txt
157 \ http://www.lagers.org.uk/processing/steganos/Steganos.txt
+185 \ http://softlab.pt/ptmx/ptmx.txt
+253 \ https://ztdp.ca/projects/school/Green/Green.txt
[Library : Simulation]
018 \ http://www.ricardmarxer.com/fisica/download/fisica.txt
@@ -137,6 +212,11 @@
107 \ https://dl.dropboxusercontent.com/u/6030446/punktiert/punktiert.txt
108 \ https://dl.dropboxusercontent.com/u/6030446/bRigid/bRigid.txt
127 \ http://www.lagers.org.uk/processing/ai4g/AI_for_2D_Games.txt
+195 \ http://culebra.technology/culebra.txt
+201 \ https://github.com/diwi/PixelFlow/releases/download/latest/PixelFlow.txt
+216 \ https://github.com/diwi/LiquidFunProcessing/releases/download/latest/LiquidFunProcessing.txt
+244 \ http://giftedapprentice.com/ewbIK/ewbIK.txt
+261 \ https://github.com/dennisppaul/teilchen/releases/latest/download/teilchen.txt
[Library : Sound]
153 \ https://github.com/processing/processing-sound/releases/download/latest/sound.txt
@@ -146,10 +226,18 @@
118 \ http://www.abstract-codex.net/tactu5/download/tactu5.txt
138 \ http://beadsproject.net/library/beads.txt
147 \ http://code.compartmental.net/minim/distro/minim_for_processing.txt
-151 \ https://chrisjr.github.io/loom/download/loom.txt
+151 \ https://corajr.github.io/loom/download/loom.txt
+170 \ https://github.com/shlomihod/cassette/releases/download/latest/cassette.txt
+219 \ https://teddavis.org/xyscope/download/XYscope.txt
+254 \ http://www.kramann.info/ComposingForEveryone.txt
+260 \ https://github.com/sphaero/procmod/releases/latest/download/procmod.txt
+264 \ https://github.com/dennisppaul/wellen/releases/latest/download/wellen.txt
+271 \ https://www.robertesler.com/software/Pd4P3.txt
[Library : Utilities]
+001 \ https://github.com/remixlab/proscene/releases/download/latest/proscene.txt
# 005 \ http://nootropicdesign.com/processing-layers/downloads/layers.txt
+010 \ http://shiffman.net/p5/libraries/mpe/mpe.txt
027 \ http://jorgecardoso.eu/processing/ID3/ID3.txt
# 029 \ http://libraries.seltar.org/unzipit/unzipit.txt
031 \ http://libraries.seltar.org/postToWeb/postToWeb.txt
@@ -165,36 +253,72 @@
094 \ https://dl.dropbox.com/u/87680069/executor.txt
129 \ https://github.com/onar3d/processing-mother/releases/download/latest/Mother.txt
140 \ https://raw.github.com/dhchoi/processing-countdowntimer/master/release/CountdownTimer.txt
-152 \ http://www.imaginary-institute.com/resources/AULibrary/AULib.txt
+152 \ https://imaginary-institute.com/resources/AULibrary/AULib.txt
158 \ http://josephtaylor.github.io/ColorScheme/ColorScheme.txt
159 \ http://josephtaylor.github.io/sketch-mapper/SketchMapper.txt
+180 \ http://interfascia.berg.industries/download/interfascia.txt
+192 \ https://github.com/barelief/freeTransform-processing/releases/download/latest/FreeTransform.txt
+193 \ http://shiffman.net/p5/libraries/processing3/mpe/mpe.txt
+201 \ https://github.com/diwi/PixelFlow/releases/download/latest/PixelFlow.txt
+202 \ https://ixora.io/downloads/colorblindness/ColorBlindness.txt
+207 \ https://github.com/Lord-of-the-Galaxy/Timing-Utilities/releases/download/latest/timing_utils.txt
+210 \ http://cagewebdev.com/colorharmony/colorharmony.txt
+212 \ https://github.com/cansik/processing-postfx/releases/download/latest/PostFX.txt
+213 \ https://github.com/AlexPoupakis/mouse2DTransformations/releases/download/latest/Mouse2DTransformations.txt
+217 \ https://pierdr.github.io/Tramontana-for-Processing/tramontana.txt
+229 \ https://github.com/Shinhoo/Wooting-Keyboard-Library/releases/download/lastest/WootingKeyboard.txt
+235 \ https://www.barkmin.eu/processing-library-scratch/download/scratch.txt
+240 \ https://commonpike.github.io/nl.kw.processing.portmods/dist/PortMods.txt
+245 \ https://github.com/VisualComputing/nub/releases/download/latest/nub.txt
+246 \ https://github.com/federico-pepe/nice-color-palettes/releases/download/latest/NiceColorPalettes.txt
+248 \ https://github.com/runwayml/processing-library/releases/download/latest/RunwayML.txt
+255 \ https://bdhont.net/LiveBrush.txt
+257 \ https://rect.dev/processing/infinidecimal/GRInfinidecimalCanvas.txt
+258 \ https://github.com/Transmedia-Gx/grab/releases/latest/download/Grab.txt
[Library : Typography]
038 \ http://www.ricardmarxer.com/geomerative/geomerative.txt
088 \ https://raw.github.com/andreaskoller/Fontastic/master/download/Fontastic.txt
-116 \ https://github.com/prisonerjohn/NextText/releases/download/latest/NextText.txt
+# 116 \ https://github.com/prisonerjohn/NextText/releases/download/latest/NextText.txt
[Library : Video & Vision]
150 \ https://github.com/processing/processing-video/releases/download/latest/video.txt
013 \ http://shiffman.net/p5/libraries/openkinect_processing/openkinect_processing.txt
023 \ http://www.v3ga.net/processing/BlobDetection/blobDetection.txt
-041 \ https://github.com/Syphon/Processing/releases/download/latestv2/Syphon.txt
+041 \ https://github.com/Syphon/Processing/releases/latest/download/Syphon.txt
# 059 \ http://thomasdiewald.at/processing/libraries/dLibs_freenect/download/dLibs_freenect.txt
# 077 \ http://s373.net/code/flob/download/flob.txt
# 081 \ http://ubaa.net/shared/processing/opencv/download/opencv.txt
-125 \ http://shiffman.net/p5/libraries/rekognition_processing/rekognition_processing.txt
+# 125 \ http://shiffman.net/p5/libraries/rekognition_processing/rekognition_processing.txt
132 \ https://github.com/atduskgreg/opencv-processing/releases/download/latest/opencv_processing.txt
-134 \ http://decoder.x10.mx/blobscanner/blobscanner.txt
+134 \ http://decoder.x10host.com/blobscanner/blobscanner.txt
146 \ http://boofcv.org/processing/boofcv_processing.txt
-148 \ https://github.com/Syphon/Processing/releases/download/latest/Syphon.txt
+# 148 \ https://github.com/Syphon/Processing/releases/download/latest/Syphon.txt
149 \ http://www.magicandlove.com/software/Kinect4WinSDK.txt
161 \ http://codigogenerativo.com/KinectPV2.txt
+176 \ http://www.stefanobaldan.com/projects/ipcapture/download/IPCapture.txt
+184 \ https://github.com/gohai/processing-glvideo/releases/download/latest/processing-glvideo.txt
+186 \ https://github.com/leadedge/SpoutProcessing/releases/download/latest/spout.txt
+201 \ https://github.com/diwi/PixelFlow/releases/download/latest/PixelFlow.txt
+211 \ https://github.com/diwi/PS3Eye/releases/download/latest/PS3Eye.txt
+222 \ https://pierdr.github.io/tramontanaCV/download/tramontanaCV.txt
+223 \ https://github.com/nyatla/NyARToolkit-for-Processing/releases/download/latest/nyar4psg.txt
+227 \ https://github.com/Milchreis/processing-imageprocessing/releases/download/latest/processing-imageprocessing.txt
+236 \ http://softlab.pt/VLCJVideo/VLCJVideo.txt
[Examples : Books]
154 \ http://shiffman.net/p5/examples/natureofcode.txt
163 \ http://shiffman.net/p5/examples/learningprocessing2.txt
165 \ https://processing.org/handbook/handbook_2e.txt
166 \ https://processing.org/books/gswp_2e.txt
+205 \ http://mad4j.github.io/book-mdpc/book-mdpc.txt
+265 \ https://codingart-book.github.io/examples/CodingArtBookExamples.txt
+
+[Examples : ]
+194 \ http://damellis.github.io/wovns-processing-examples/WOVNS.txt
+226 \ https://github.com/Apress/processing-for-android/releases/download/latest/processing-for-android-examples.txt
+243 \ https://coding-creative.dringtech.com/examples/coding-creative-examples.txt
+249 \ https://github.com/jeremydouglass/rosetta_examples_p5/releases/latest/download/rosetta_examples_p5.txt
[Tool : ]
020 \ https://dl.dropboxusercontent.com/u/69944346/ColorSelectorPlus/ColorSelectorPlusTool.txt
@@ -209,6 +333,15 @@
114 \ http://drifkin.net/processing/beziereditor/download/BezierEditorTool.txt
141 \ http://s3.staticvoidgames.com/JarMatey/JarMateyProcessingTool.txt
160 \ https://github.com/joelmoniz/Git-Manager/releases/download/latest/GitManager.txt
+181 \ https://github.com/joelmoniz/Shape-Sketch/releases/download/latest/ShapeSketch.txt
+182 \ https://github.com/rzats/font-highlighting-editor/releases/download/latest/FontHighlightingEditor.txt
+191 \ https://github.com/gohai/processing-uploadtopi/releases/download/latest/UploadToPiTool.txt
+221 \ http://jonathan.dahlberg.media/ecc/ecc.txt
+228 \ https://perceptualcolor.org/distribution/PerceptualColorPicker/download/PerceptualColorPicker.txt
+233 \ https://github.com/jaewhyun/GettingStarted/releases/download/latest/GettingStarted.txt
+234 \ https://github.com/jaewhyun/ReferenceTool/releases/download/latest/ReferenceTool.txt
+242 \ https://jwilder4690.github.io/tools/ArtStation/ArtStation.txt
+263 \ http://jonathan.dahlberg.media/processing2js/Processing2JSTool.txt
[Mode : ]
070 \ http://bezier.de/processing/modes/CoffeeScriptMode.txt
@@ -216,5 +349,9 @@
101 \ https://github.com/processing/processing-android/releases/download/latest/AndroidMode.txt
# 122 \ http://galsasson.com/tweakmode/tweakmode.txt
# 124 \ http://download.processing.org/pdeX.txt
-142 \ http://py.processing.org/PythonMode.txt
-162 \ https://github.com/joelmoniz/REPLmode/releases/download/latest/REPLMode.txt
\ No newline at end of file
+# 142 \ http://py.processing.org/PythonMode.txt
+162 \ https://github.com/joelmoniz/REPLmode/releases/download/latest/REPLMode.txt
+169 \ https://py.processing.org/3/PythonMode.txt
+199 \ https://github.com/fathominfo/processing-p5js-mode/releases/download/latest/p5jsMode.txt
+220 \ https://github.com/processing-r/Processing.R/releases/latest/download/RLangMode.txt
+250 \ https://github.com/Izza11/shader-mode/releases/download/latest/ShaderMode.txt
diff --git a/css/changes.css b/css/changes.css
index 0889836ed..07222aef0 100755
--- a/css/changes.css
+++ b/css/changes.css
@@ -60,7 +60,7 @@ dl.network dd { margin: 0; }
dl.network dd.date { color: #999966; margin-bottom: 1em; }
/*** Reference ***/
-.ref-notice { margin: 2.5em 0 2.5em 0; color: #006699}
+.ref-notice { margin: 2.5em 0 2.5em 0; color: #006699;}
#Language th { width: 100px; font-weight: normal; text-align: left; vertical-align: top; }
#Language td { vertical-align: top; padding-bottom: 2em; }
diff --git a/css/forms.css b/css/forms.css
index d26c72960..b3396a8de 100755
--- a/css/forms.css
+++ b/css/forms.css
@@ -5,59 +5,42 @@
*
*/
-table {
-}
-
-td
-{
- /*text-align: left;
- vertical-align: top;*/
-}
form
- {
+{
margin-bottom : 0px;
}
input,
select,
textarea
- {
+{
font-family : Verdana, Arial, Helvetica, sans-serif;
font-size : 10px;
-
vertical-align : middle;
}
select
- {
+{
width : 120px;
}
input
- {
+{
margin-right : 5px;
}
label
- {
+{
display : block;
- /*margin-left : -2px;
- margin-bottom : 7px;*/
- /* \*/
- /*margin-bottom : 3px;*/
- /* */
+
}
-select[multiple]
- {
- /*margin-left : -3px;*/
- }
input[type="text"],
input[type="password"],
input:not([type])
- {
+{
/*border : 2px solid !important;*/
-moz-border-top-colors : #7C7C7C #C3C3C3;
@@ -71,7 +54,7 @@ input[type="reset"],
input[type="button"],
input[type="submit"],
select:not([multiple])
- {
+{
/*border : 2px solid !important;
background-repeat : repeat-x !important;
background-position : bottom right !important;*/
@@ -90,7 +73,7 @@ input[type="reset"]:hover:active,
input[type="button"]:hover:active,
input[type="submit"]:hover:active,
select:not([multiple]):hover:active
- {
+{
/*border : 2px solid !important;*/
-moz-border-top-colors : #999999 #CECECE !important;
@@ -100,7 +83,7 @@ select:not([multiple]):hover:active
}
select > input[type="button"]
- {
+{
border-top : none !important;
border-right : none !important;
border-bottom : none !important;
@@ -116,7 +99,7 @@ input[type="password"]:focus,
input:not([type]):focus,
textarea:focus,
select[multiple]:focus
- {
+{
-moz-border-top-colors : -moz-mac-focusring -moz-mac-focusring !important;
-moz-border-right-colors : -moz-mac-focusring -moz-mac-focusring !important;
-moz-border-bottom-colors : -moz-mac-focusring -moz-mac-focusring !important;
@@ -141,7 +124,7 @@ textarea, select[multiple]
input[type="radio"]:not([class]):not([id]):not([style])
- {
+{
width: 13px !important;
height: 13px !important;
@@ -161,11 +144,6 @@ input[type="radio"]:not([class]):not([id]):not([style])
}
-input[type="radio"]:focus:not([class]):not([id]):not([style])
- {
-
- }
-
input[type="radio"]:checked:not([class]):not([id]):not([style])
{
diff --git a/css/processing_beta.css b/css/processing_beta.css
index c68a5b126..4213e5746 100644
--- a/css/processing_beta.css
+++ b/css/processing_beta.css
@@ -38,7 +38,7 @@ pre {
FONT-FAMILY: "Courier New", Courier, mono;
FONT-SIZE: 11px;
LINE-HEIGHT: normal;
- COLOR: #000000
+ COLOR: #000000;
}
.inputnav {
@@ -60,12 +60,12 @@ pre {
FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
FONT-SIZE: 19px;
FONT-WEIGHT: normal;
- COLOR: #5A5A46
+ COLOR: #5A5A46;
}
.caption {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
font-style: normal;
- font-weight: normal
+ font-weight: normal;
}
diff --git a/css/style.css b/css/style.css
index e1d72a629..65fd77ba4 100755
--- a/css/style.css
+++ b/css/style.css
@@ -7,12 +7,10 @@ Reworked by CR, 23 Sep 2011
Reworked by Jon Gacnik, 19 Feb 2013
Created: 2005.08.29 04:28PM
-Last Modified: 2014.11.15 by Scott Murray
+Last Modified: 2019.07.26 by Casey Reas to remove Foundation Site CSS "-f"
*/
-
-
@font-face {
font-family: 'theSerifItalic';
src: url(fonts/TheSerif_B4_Italic.eot),
@@ -54,7 +52,6 @@ Last Modified: 2014.11.15 by Scott Murray
}
-
/* ================ GLOBAL ================== */
body {
@@ -70,7 +67,7 @@ body {
-webkit-text-size-adjust: none;
font-size : 100%;
- font-size : 0.79em;
+ font-size : 0.85em; /* 0.79em; */
font-weight : normal;
line-height : 1.5em;
color : #252525;
@@ -79,6 +76,7 @@ body {
img { border: 0px solid #000000; }
a {
+ cursor: pointer;
text-decoration: none;
font-weight: normal;
color: #2c7bb5;
@@ -102,6 +100,7 @@ a.large-link:before {
content: '';
}
+
/* ================ COVER SLIDESHOW ================== */
#slideshow {
@@ -127,7 +126,6 @@ a.large-link:before {
}
-
/* ================ LAYOUT ================== */
#container {
@@ -137,7 +135,6 @@ a.large-link:before {
}
-
/* ================ RIBBON ================== */
#ribbon {
@@ -179,6 +176,8 @@ a.large-link:before {
border-right: 1px solid #1a1a1a;
}
+
+
#ribbon ul.right li {
float: right;
border-left: 1px solid #1a1a1a;
@@ -209,12 +208,48 @@ a.large-link:before {
font-weight: bold;
}
+#ribbon-announce {
+ text-align: center;
+ width: 900px;
+ height: auto;
+ background-color: #d1f94e;
+ background: linear-gradient(to bottom, #1d517e, #d1f94e);
+ margin-bottom: 30px; /* added when placed below the header */
+}
+
+#ribbon-announce ul {
+ display: inline-block;
+ margin: 0;
+ padding: 0;
+}
+
+#ribbon-announce ul.center {
+ float: center;
+}
+
+#ribbon-announce ul li {
+ display: inline-block;
+ margin: 0;
+ padding: 6px 10px 5px 10px;
+ list-style: none;
+}
+
+#ribbon-announce ul.center li {
+ float: center;
+}
+
+#ribbon-announce ul li a {
+ color: white;
+ font-weight: bold;
+}
+
/* ================ HEADER ================== */
+
#header {
width: 900px;
height: 106px;
- margin-bottom: 30px;
+ margin-bottom: 30px; /* was 30px, but changed to 0 when ribbon placed below header */
overflow: hidden;
background: #0c2033 url(../img/processing-web.png) center center no-repeat;
background-position: bottom;
@@ -222,16 +257,6 @@ a.large-link:before {
position: relative;
}
-#header-f {
- width: 900px;
- height: 106px;
- margin-bottom: 30px;
- overflow: hidden;
- background: #0c2033 url(/images/processing-site.png) center center no-repeat;
- background-size: 900px 106px;
- position: relative;
-}
-
#header .processing-logo {
width: 206px;
height: 38px;
@@ -243,17 +268,6 @@ a.large-link:before {
background-image: linear-gradient(transparent, transparent), url(../img/processing-logo.svg);
}
-#header-f .processing-logo {
- width: 370px;
- height: 38px;
- margin: 20px 0 0 30px;
- /* -- NEW FOUNDATION LOGO GOES HERE -- */
- background: transparent url(/images/processing-foundation-logo.svg) center center no-repeat;
- background-image: -webkit-linear-gradient(transparent, transparent), url(/images/processing-foundation-logo.svg);
- background-image: -moz-linear-gradient(transparent, transparent), url(/images/processing-foundation-logo.svg);
- background-image: linear-gradient(transparent, transparent), url(/images/processing-foundation-logo.svg);
-}
-
#header .processing-logo.no-cover:before {
position: relative;
top: 3px;
@@ -262,14 +276,6 @@ a.large-link:before {
content: '\2039';
}
-#header-f .processing-logo.no-cover:before {
- position: relative;
- top: 3px;
- left: -18px;
- font-size: 24px;
- content: '\2039';
-}
-
#Overview2 .processing-logo.no-cover:before {
position: relative;
top: 3px;
@@ -284,23 +290,11 @@ a.large-link:before {
color: white;
}
-#header-f a {
- font-family: 'theSerif', 'Enriqueta', georgia, times, sans-serif;
- text-decoration: none;
- border: none;
- color: white;
-}
-
#header h1 {
display: none;
float: left;
}
-#header-f h1 {
- display: none;
- float: left;
-}
-
#header form {
position: absolute;
top: 20px;
@@ -309,14 +303,6 @@ a.large-link:before {
color: #959595;
}
-#header-f form {
- position: absolute;
- top: 20px;
- right: 5px;
- width: 176px;
- color: #959595;
-}
-
#header form input {
float: left;
border: 1px solid #136796;
@@ -328,29 +314,12 @@ a.large-link:before {
color: #959595;
}
-#header-f form input {
- float: left;
- border: 1px solid #136796;
- outline: none;
- height: 18px;
- background: #fff;
- font-family: 'theSerif', 'Enriqueta', georgia, times, serif;
- font-size: 1em;
- color: #959595;
-}
-
#header form input[type="text"]{
padding-left: 3px;
width: 127px;
border-right: none;
}
-#header-f form input[type="text"]{
- padding-left: 3px;
- width: 127px;
- border-right: none;
-}
-
#header form input[type="submit"]{
height: 22px;
width: 22px;
@@ -362,21 +331,8 @@ a.large-link:before {
cursor: pointer;
}
-#header-f form input[type="submit"]{
- height: 22px;
- width: 22px;
- border-left: none;
- background: white url(/images/search-f.svg) center center no-repeat;
- background-image: -webkit-linear-gradient(transparent, transparent), url(/images/search-f.svg);
- background-image: -moz-linear-gradient(transparent, transparent), url(/images/search-f.svg);
- background-image: linear-gradient(transparent, transparent), url(/images/search-f.svg);
- cursor: pointer;
-}
-
#header form p { margin: 0; }
-#header-f form p { margin: 0; }
-
/* ================ NAVBAR ================== */
#navigation {
@@ -407,6 +363,7 @@ a.large-link:before {
position: relative;
}
+
/* ================ FOOTER ================== */
#footer {
@@ -428,26 +385,6 @@ a.large-link:before {
padding-top: 10px;
}
-/* === FOUNDATION FOOTER === */
-
-#footer-f {
- clear: both;
- padding: 100px 30px 20px 30px;
- line-height: 23px;
- color: #959595;
-}
-#footer-f a {
- color: #959595;
- border-bottom: 1px solid #CECECE;
-}
-#footer-f #copyright,
-#footer-f #colophon {
-
-}
-#footer-f #copyright {
- border-top: 1px solid #A6BCCF;
- padding-top: 10px;
-}
/* ================ TYPOGRAPHY ================== */
@@ -524,13 +461,12 @@ li {margin-bottom: 1em; }
.large-header .black { color: #000; }
.error { color: #f00; margin: 0; }
-/* ================ UI Elements ================== */
-
-
/* ================== RANDOM CLASSES =============== */
+
.clear { clear: both; }
+
/* ================== PAGE SPECIFIC CSS =============== */
/**************************************************************** Cover ***/
@@ -678,15 +614,8 @@ dl.network dt { font-style: normal; }
dl.network dd { margin: 0; }
dl.network dd.date { color: #999999; margin-bottom: 1em; }
-//p.network { margin: 0 23px 1em 0; width:200px; }
-//p.network span.date { color: #999999; }
-
p.exhibition-nav { margin-top: 20px; margin-bottom: 10px; }
-/**************************************************************** Foundation ***/
-
-.foundation-p { line-height: 0em; }
-
/**************************************************************** Reference ***/
@@ -694,8 +623,6 @@ p.exhibition-nav { margin-top: 20px; margin-bottom: 10px; }
#Language h5 a { float: left; margin-left: -30px; }
-
-
.skinny {
margin-left : 0px;
margin-right : 50px;
@@ -711,7 +638,7 @@ p.exhibition-nav { margin-top: 20px; margin-bottom: 10px; }
margin-bottom: 20px;
}
-.ref-notice { margin: 0 0 2.5em 0; color: #FF3399; clear: both; margin-right: 40px;}
+.ref-notice { margin: 0 0 2.5em 0; color: #666666; clear: both; margin-right: 40px;}
.ref-item { margin-bottom: 60px; }
.ref-item th { width: 100px; font-weight: bold; text-align: left; vertical-align: top; }
@@ -879,8 +806,6 @@ div.ref-col {
/**************************************************************** download ***/
-/* download */
-
#Download .download ul { list-style: none; margin: 0; padding: 0; }
#Download span.version-date { color: #959595; }
#Download h5 {
@@ -1059,16 +984,13 @@ div.ref-col {
/************************************************************** contribute ***/
-/*#Contribute h1 { margin-bottom: 0; }*/
#Contribute .message { margin-top: 0; margin-right: 40px; }
#Contribute .threecol { float: left; width: 210px; margin-right: 20px; }
#Contribute .threecol p { margin-bottom: 2em; }
-
/************************************************************** learning ***/
-/*#Learning h1 { margin-bottom: 0; margin-top: 0;}*/
#Learning .message { margin-top: 0; margin-right: 40px; }
#Learning .threecol { float: left; width: 200px; margin-right: 30px; margin-top: 0px;}
#Learning .threecol p { margin-bottom: 2em; }
@@ -1080,13 +1002,10 @@ div.ref-col {
.doc-float { margin-right: 40px;}
-
-
h2 { margin-bottom: 0; margin-top: 0;}
.example-notice { margin: -1.0em 0 2.5em 0; color: #FF3399; clear: both; margin-right: 40px;}
-
#Copyright p { margin-right: 20px; }
@@ -1097,37 +1016,6 @@ h2 { margin-bottom: 0; margin-top: 0;}
#Tutorials .colthree { width: 224px; float: left; margin-right: 20px; }
#Tutorials h2 { margin: 0 0 20px 0; font-size: 1em; }
-/*#Tutorials p {
- margin-top: 2.0em;
- margin-bottom: 2.0em;
- font-size : 1.0em;
- font-weight : normal;
- line-height : 2.0em;
- }*/
-
-/*#Tutorials h3 {
- font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
- font-size : 1.3em;
- font-weight : bold;
- margin-bottom : 0.4em;
- margin-top : 1.8em;
-}
-
-#Tutorials h5 {
- font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
- font-weight : bold;
- font-size : 1.0em;
- margin-bottom : 0.4em;
- margin-top : 1.4em;
-}*/
-
-/*#Tutorials h1 {
- font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
- font-size : 2.0em;
- font-weight : normal;
- font-style : normal;
-}*/
-
/*--------------------TUTORIAL HEADER SPACING------------------*/
.Tutorials { line-height: 0em; }
@@ -1176,6 +1064,7 @@ h2 { margin-bottom: 0; margin-top: 0;}
background-color: #eee;
}
+/*
#Tutorials p.txt {
margin-top: 0em;
margin-bottom: 2em;
@@ -1183,10 +1072,10 @@ h2 { margin-bottom: 0; margin-top: 0;}
font-weight: normal;
line-height: 200%;
}
+*/
/************************************************************** Books ***/
-/*#Books h1 { margin-bottom: 0; margin-top: 0;}*/
#Books td { vertical-align: top; font-size: 1.0em}
@@ -1210,9 +1099,6 @@ h2 { margin-bottom: 0; margin-top: 0;}
margin-top: 30px;
}
-
-
-
#Tools-index h5 { margin-bottom: 0; font-size: 1em; }
#Tools-index .twocol p { margin-top: 0; }
.lib-nav { display: block;
@@ -1231,7 +1117,6 @@ h2 { margin-bottom: 0; margin-top: 0;}
#Tools h4 { font-size: 1em; margin-bottom: .5em; }
#Tools h4 a {float:left; margin-left:-30px; martin-top:-5px; }
-
#Tools .threecol {
float: left;
width: 210px;
@@ -1241,10 +1126,8 @@ h2 { margin-bottom: 0; margin-top: 0;}
.threecol:nth-child(5) { margin: 0 !important; }
-
/************************************************************** Library Indices ***/
-
#Libraries .colone {
width: 300px;
float: left;
@@ -1266,10 +1149,8 @@ h2 { margin-bottom: 0; margin-top: 0;}
#Libraries .twocol-alt {
width: 330px;
float: left;
- //background: #cccccc;
}
-
#Libraries .twocol p { margin-top: 0; }
#Libraries .full {
@@ -1294,19 +1175,16 @@ h2 { margin-bottom: 0; margin-top: 0;}
margin-bottom: 2px;
}
-
-
#Libraries .lib-nav { display: block;
margin-bottom: 10px;
margin-left: -30px;
padding: 7px 0 3px 30px;
- background: url(/img/back_off.gif) no-repeat
+ background: url(/img/back_off.gif) no-repeat;
}
#Libraries pre { margin-left: 30px; margin-bottom: 30px; }
#Libraries h2 { margin-top: 2em; }
-/*#Libraries h3 { clear: both; margin-bottom: 0; }*/
#Libraries h3 { margin-top: 0; margin-bottom: 0;}
@@ -1329,13 +1207,13 @@ h2 { margin-bottom: 0; margin-top: 0;}
/************************************************************** environment ***/
-/*#Environment h1 { margin-top: 2em; }*/
-#Environment h5 { margin-top: 3em; }
+
+#Environment h5 { margin-top: 2em; margin-bottom: 1em; }
#Environment h6 { margin-bottom: 0em; }
#Environment h5 a { float: left; margin-left: -30px; }
ul.nostyle { margin: 0; padding: 0; list-style: none outside; }
#Environment td { padding-bottom: 1em; }
-#Environment .content p,
+/*#Environment .content p,*/
#Environment .content ul,
#Environment .content table {
width: 560px;
@@ -1343,31 +1221,22 @@ ul.nostyle { margin: 0; padding: 0; list-style: none outside; }
/************************************************************** overview ***/
+
#Overview .content p,
#Overview .content ul,
-#Overview .content table {
- width: 560px;
-}
+#Overview .content table { width: 560px; }
#Foundation .content p,
#Foundation .content ul,
-#Foundation .content table {
- width: 560px;
-}
-
+#Foundation .content table { width: 560px; }
#People .content p,
#People .content ul,
-#People .content table {
- width: 560px;
-}
+#People .content table { width: 560px; }
#people-f .content p,
#people-f .content ul,
-#people-f .content table {
- width: 680px;
-}
-
+#people-f .content table { width: 680px; }
/************************************************************** examples ***/
@@ -1377,16 +1246,12 @@ p.doc-float { margin-left: 250px; }
p.doc { margin-right: 40px; margin-top: 30px;}
pre.code { clear: both; margin-top: 10px; }
-/* #examples-nav { margin-left: -44px; display: relative; } */
//#examples-nav { margin-left: 0px; display: relative; }
.examples-nav-div { margin-left: -44px; margin-top: -10px; width: 480px; display: relative; align: left; }
#examples-nav img { display: absolute; top: 15px; left: 100px; }
-/*#Examples h1 { margin-bottom: 0; }*/
-
-
div.updateRequired {
color:#999;
}
@@ -1402,7 +1267,9 @@ ul.examples {
-webkit-column-count:3; /* Safari and Chrome */
column-count:3;
}
+
ul.examples li { margin: 0; padding: 0; }
+
ul.examples ul {
list-style: none;
padding: 0;
@@ -1410,58 +1277,80 @@ ul.examples ul {
margin-bottom: 17px;
width: 100%;
}
+
ul.examples ul li {
margin: 0;
}
+
div.examples-nav {
margin-left: -41px;
margin-bottom: 17px;
position: relative;
}
-div.examples-nav img { position: relative; top: 11px; }
-
-
-/**************************************************************** updates, courses, happenings ***/
-/*
-#Courses .content, #Updates .content, #Happenings .content {
- width: 595px;
- }
-#Updates h2 { margin-top: 0 0 20px 0; }
-
-
-.course-desc p { margin: 0; }
-.course-desc p.date { margin: 0; }
-.course-desc h3 { margin: 0; font-size: 1em; font-weight: bold; line-height: 1em; }
-.course-desc { margin-bottom: 2em; }
-*/
-
-/************************************************************** comparison ***/
-/*
-
-#Compare h1 { margin-top: 2em; }
-#Compare h2 { margin-bottom: 0; }
-#Compare .threecol { float: left; width: 210px; margin-right: 20px; }
-#Compare .threecol p { margin-top: 0; }
-
-
-#Compare .content {
- margin-left : 55px;
- margin-right : 0px;
- position: relative;
-}
-*/
-/************************************************************** troubleshooting ***/
-/*
-#Troubleshooting h1 { margin-top: 2em; }
-#Troubleshooting h5 a { float: left; margin-left: -30px; }
-ul.nostyle { margin: 0; padding: 0; list-style: none outside; }
-#Troubleshooting td { padding-bottom: 1em; }
-*/
-
-/************************************************************** FAQ ***/
-
-/*
-#FAQ h5 a { float: left; margin-left: -30px; }
-*/
+div.examples-nav img { position: relative; top: 11px; }
+ .donate-card-row {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-justify-content: space-between;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ margin-left: -10px;
+ margin-right: -10px;
+ }
+
+ .donate-card {
+ text-align: center;
+ width: 30%;
+ border: 1px solid #CBCBCB;
+ /*background: #FAFAFA;*/
+ padding: 20px;
+ margin: 10px;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -webkit-justify-content: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ }
+
+ .donate-card h4 {
+ line-height: 1.3;
+ margin: 0 0 0 0;
+ color: #2c7bb5;
+ }
+
+ a.donate-card {
+ color: #252525;
+ }
+
+ a.donate-card:hover {
+ border-color: #2c7bb5;
+ }
+
+ .donate-list {
+ list-style: none;
+ margin-left: 0;
+ padding-left: 0;
+ }
+
+ .donate-list li {
+ margin-bottom: 0;
+ }
+
+ .donate-list li:before {
+ content: '» '
+ }
+
+ .donate-content hr {
+ margin-top: 2em;
+ margin-bottom: 2em;
+ background: none;
+ border: none;
+ border-top: 1px solid #CBCBCB;
+ }
diff --git a/download/README.md b/download/README.md
deleted file mode 100755
index d8599a827..000000000
--- a/download/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## Processing Donation Form
-
-### Description
-
-The code here handles the Stripe and PayPal purchasing system for Processing Foundation.
-
-### Libraries/Classes Used
-[Stripe Donation Form](https://github.com/tommymarshall/Stripe-Donation-Form/zipball/master)
-[PayPal Express Checkout](https://github.com/maly/paypal)
-[PHPMailer](https://github.com/Synchro/PHPMailer)
-
-### Feature Overview
-
-- Process donation using Stripe Payments & PayPal Express Checkout
-- Send email reciept
-- Log purchase
-- Forward user to Downloads page
\ No newline at end of file
diff --git a/download/_downloads.php b/download/_downloads.php
deleted file mode 100644
index be770bbbd..000000000
--- a/download/_downloads.php
+++ /dev/null
@@ -1,428 +0,0 @@
-
-
+
+
+
+
+Video
+Daniel Shiffman
+
+Live Video
+
+
+
+Step 1. Import the Processing video library.
+
+Although the video library is developed and maintained by the Processing Foundation, due to its size, it must still be downloaded separately through the contributions manager. The Video and Sound libraries need to be downloaded through the Library Manager. Select "Add Library..." from the "Import Library..." submenu within the Sketch menu.
+
+Once you’ve got the library installed, the next step is to import the library in your code. This is done by selecting the menu option Sketch → Import Library → Video, or by typing the following line of code (which should go at the very top of your sketch):
+
+import processing.video.*;
+
+Using the “Import Library” menu option does nothing other than automatically insert that line into your code, so manual typing is entirely equivalent.
+
+
+Step 2. Declare a Capture object.
+
+You’ve recently seen how to create objects from classes built into the Processing language such as PShape and PImage. Both of these classes, it should be noted, are part of the processing.core library and, therefore,no import statement were required. The processing.video library has two useful classes inside of it — Capture, for live video, and Movie, for recorded video. In this step, I’ll be declaring a Capture object.
+
+Capture video;
+
+
+Step 3. Initialize the Capture object.
+
+The Capture object “video” is just like any other object — to construct an object, you use the new operator followed by the constructor. With a Capture object, this code typically appears in setup().
+
+video = new Capture();
+
+The above line of code is missing the appropriate arguments for the constructor. Remember, this is not a class you wrote yourself so there is no way to know what is required between the parentheses without consulting the online reference.
+
+The reference will show there are several ways to call the Capture constructor. A typical way to call the constructor is with three arguments:
+
+void setup() {
+ video = new Capture(this, 320, 240);
+}
+
+Let’s walk through the arguments used in the Capture constructor.
+
+
+
+
+There are some cases, however, where the above will not do. For example, what if you have multiple cameras attached to your computer? How do you select the one you want to capture? In addition, in some rare cases, you might also want to specify a frame rate from the camera. For these cases, Processing will give you a list of all possible camera configurations via Capture.list(). You can display these in your message console, for example, by saying:
+
+printArray(Capture.list());
+
+You can use the text of these configurations to create a Capture object. On a Mac with a built-in camera,for example, this might look like:
+
+video = new Capture(this, "name=FaceTime HD Camera (Built-in),size=320x240,fps=30");
+
+Capture.list() actually gives you an array so you can also simply refer to the index of the configuration you want.
+
+video = new Capture(this, Capture.list()[0]);
+
+
+Step 4. Start the capture process.
+
+Once the camera is ready, it’s up to you to tell Processing to start capturing images.
+
+void setup() {
+ video = new Capture(this, 320, 240);
+ video.start();
+}
+
+In almost every case you want to begin capturing right in setup(). Nevertheless, start() is its own method, and you do have the option of, say, not starting capturing until some other time (such as when a button is pressed, etc.)
+
+
+Step 5. Read the image from the camera.
+
+There are two strategies for reading frames from the camera. I will briefly look at both and choose one forthe remainder of the examples in this chapter. Both strategies, however, operate under the same fundamental principle: I only want to read an image from the camera when a new frame is available to be read.
+
+
+In order to check if an image is available, you use the function available(), which returns true or false depending on whether something is there. If it is there, the function read() is called and the frame from the camera is read into memory. You can do this over and over again in the draw() loop, always checking to see if a new image is free to be read.
+
+void draw() {
+ if (video.available()) {
+ video.read();
+ }
+}
+
+The second strategy, the “event” approach, requires a function that executes any time a certain event — in this case a camera event — occurs. The function mousePressed() is executed whenever the mouse is pressed. With video, you have the option to implement the function captureEvent(), which is invoked any time a capture event occurs, that is, a new frame is available from the camera. These event functions (mousePressed(), keyPressed(), captureEvent(), etc.) aresometimes referred to as a “callback.” And as a brief aside, if you’re following closely, this is where this fits in. The Capture object, video, knows to notify this sketch by invoking captureEvent() because you passed it a reference to this sketch when creating the Capture object video.
+
+captureEvent() is a function and therefore needs to live in its own block, outside of setup() and draw().
+
+void captureEvent(Capture video) {
+ video.read();
+}
+
+You might notice something odd about captureEvent(). It includes an argument of type Capture in its definition. This might seem redundant to you; after all, in this example I already have a global variable video. Nevertheless in the case where you might have more than one capture device, the same event function can be used for both and the video library will make sure that the correct Capture object is passed in to captureEvent().
+
+To summarize, I want to call the function read() whenever there is something to read, and I can do so by either checking manually using available() within draw() or allowing a callback to handle it for you — captureEvent(). This allows sketches to operate more efficientlyby separating out the logic for reading from the camera from the main animation loop.
+
+Step 6. Display the video image.
+
+This is, without a doubt, the easiest part. You can think of a Capture object as a PImage that changes over time, and, in fact, a Capture object can be utilized in an identical manner as a PImage object.
+
+
+
+image(video, 0, 0);
+
+All of this is put together in the following code:
+
+// Step 1. Import the video library.
+import processing.video.*;
+
+//Step 2. Declare a capture object.
+Capture video;
+
+// Step 5. Read from the camera when a new image is available!
+void captureEvent(Capture video) {
+ video.read();
+}
+
+void setup() {
+ size(320, 240);
+
+ // Step 3. Initialize Capture object.
+ video = new Capture(this, 320, 240);
+
+ // Step 4. Start the capturing process.
+ video.start();
+}
+
+// Step 6. Display the image.
+void draw() {
+image(video, 0, 0);
+}
+
+Again, anything you can do with a PImage (resize, tint, move, etc.) you can do with a Capture object. As long as you read() from that object, the video image will update as you manipulate it. See the following example:
+
+
+
+import processing.video.*;
+
+Capture video;
+
+void setup() {
+ size(320, 240);
+ video = new Capture(this, 320, 240);
+ video.start();
+}
+
+void captureEvent(Capture video) {
+ video.read();
+}
+
+void draw() {
+ background(255);
+ tint(mouseX, mouseY, 255);
+ translate(width/2, height/2);
+ imageMode(CENTER);
+ rotate(PI/4);
+ image(video, 0, 0, mouseX, mouseY);
+}
+
+Note that a video image can be tinted just like a PImage. It can also be moved, rotated, and sized just like a PImage. Following is the “adjusting brightness” example with a video image:
+
+
+
+// Step 1. Import the video library
+import processing.video.*;
+
+// Step 2. Declare a Capture object
+Capture video;
+
+void setup() {
+ size(320, 240);
+
+ // Step 3. Initialize Capture object via Constructor
+ video = new Capture(this, 320, 240);
+ video.start();
+}
+
+// An event for when a new frame is available
+void captureEvent(Capture video) {
+ // Step 4. Read the image from the camera.
+ video.read();
+}
+void draw() {
+ loadPixels();
+ video.loadPixels();
+
+ for (int x = 0; x < video.width; x++) {
+ for (int y = 0; y < video.height; y++) {
+ // Calculate the 1D location from a 2D grid
+ int loc = x + y * video.width;
+
+ // Get the red, green, blue values from a pixel
+ float r = red (video.pixels[loc]);
+ float g = green(video.pixels[loc]);
+ float b = blue (video.pixels[loc]);
+
+ // Calculate an amount to change brightness based on proximity to the mouse
+ float d = dist(x, y, mouseX, mouseY);
+ float adjustbrightness = map(d, 0, 100, 4, 0);
+ r *= adjustbrightness;
+ g *= adjustbrightness;
+ b *= adjustbrightness;
+
+ // Constrain RGB to make sure they are within 0-255 color range
+ r = constrain(r, 0, 255);
+ g = constrain(g, 0, 255);
+ b = constrain(b, 0, 255);
+
+ // Make a new color and set pixel in the window
+ color c = color(r, g, b);
+ pixels[loc] = c;
+ }
+ }
+
+ updatePixels();
+}
+
+
+
+Recorded video
+
+
+Step 1. Instead of a Capture object, declare a Movie object.
+
+Movie movie;
+
+
+Step 2. Initialize Movie object.
+
+movie = new Movie(this, "testmovie.mov");
+
+The only necessary arguments are this and the movie’s filename enclosed in quotes. The movie file should be stored in the sketch’s data directory.
+
+
+Step 3. Start movie playing.
+
+There are two options, play(), which plays the movie once, or loop(), which loops it continuously.
+
+movie.loop();
+
+
+Step 4. Read frame from movie.
+
+Again, this is identical to capture. You can either check to see if a new frame is available, or use a callback function.
+
+void draw() {
+ if (movie.available()) {
+ movie.read();
+ }
+}
+
+Or:
+
+void movieEvent(Movie movie) {
+ movie.read();
+}
+
+
+Step 5. Display the movie.
+
+image(movie, 0, 0);
+
+The following code shows the program all together:
+
+import processing.video.*;
+
+// Step 1. Declare a Movie object.
+Movie movie;
+
+void setup() {
+ size(320, 240);
+
+ // Step 2. Initialize Movie object. The file "testmovie.mov" should live in the data folder.
+ movie = new Movie(this, "testmovie.mov");
+
+ // Step 3. Start playing movie. To play just once play() can be used instead.
+ movie.loop();
+}
+
+// Step 4. Read new frames from the movie.
+void movieEvent(Movie movie) {
+ movie.read();
+}
+
+// Step 5. Display movie.
+void draw() {
+ image(movie, 0, 0);
+}
+
+
+Although Processing is by no means the most sophisticated environment for displaying and manipulating recorded video, there are some more advanced features available in the video library. There are functions for obtaining the duration (length measured in seconds) of a video, for speeding it up and slowing it down, and for jumping to a specific point in the video (among others). If you find that performance is sluggish and the video playback is choppy, I would suggest trying the P2D or P3D renderers.
+
+Following is an example that makes use of jump() (jump to a specific point in the video) and duration() (returns the length of movie in seconds). In this example, if mouseX equals 0, the video jumps to the beginning. If mouseX equals width, it jumps to the end. Any other value is in between. The jump() function allows you to jump immediately to a point of time within the video. duration() returns the total length of the movie in seconds.
+
+
+import processing.video.*;
+
+Movie movie;
+
+void setup() {
+ size(200, 200);
+ background(0);
+ movie = new Movie(this, "testmovie.mov");
+}
+
+void movieEvent(Movie movie) {
+ movie.read();
+}
+
+void draw() {
+ // Ratio of mouse X over width
+ float ratio = mouseX / (float) width;
+
+ movie.jump(ratio * movie.duration());
+
+ image(movie, 0, 0);
+}
+
+
+
+Software mirrors
+
+You can apply basic image processing techniques to video images, reading and replacing the pixels one by one. Taking this idea one step further, you can read the pixels and apply the colors to shapes drawn onscreen.
+
+I will begin with an example that captures a video at 80 × 60 pixels and renders it on a 640 × 480 window. For each pixel in the video, I will draw a rectangle eight pixels wide and eight pixels tall.
+
+Let’s first write the program that displays the grid of rectangles. In the following example, the videoScale variable stores the ratio of the window’s pixel size to the grid’s size and for every column and row, a rectangle is drawn at an (x,y) location scaled and sized by videoScale.
+
+
+
+// Size of each cell in the grid, ratio of window size to video size
+int videoScale = 8;
+// Number of columns and rows in the system
+int cols, rows;
+
+void setup() {
+ size(640, 480);
+ // Initialize columns and rows
+ cols = width/videoScale;
+ rows = height/videoScale;
+}
+
+void draw() {
+ // Begin loop for columns
+ for (int i = 0; i < cols; i++) {
+ // Begin loop for rows
+ for (int j = 0; j < rows; j++) {
+ // Scaling up to draw a rectangle at (x,y)
+ int x = i*videoScale;
+ int y = j*videoScale;
+ fill(255);
+ stroke(0);
+ rect(x, y, videoScale, videoScale);
+ }
+ }
+}
+
+Knowing that I want to have squares eight pixels wide by eight pixels high, I can calculate the number of columns as the width divided by eight and the number of rows as the height divided by eight.
+
+
+I can now capture a video image that is 80 × 60. This is useful because capturing a 640 × 480 video from a camera can be slow compared to 80 × 60. I only want to capture the color information at the resolution required for the sketch.
+
+
+
+For every square at column i and row j, I look up the color at pixel (i, j) in the video image and color it accordingly. See the following example with the new parts in bold:
+
+import processing.video.*;
+
+// Size of each cell in the grid, ratio of window size to video size
+int videoScale = 8;
+// Number of columns and rows in the system
+int cols, rows;
+// Variable to hold onto Capture object
+Capture video;
+
+void setup() {
+ size(640, 480);
+ // Initialize columns and rows
+ cols = width/videoScale;
+ rows = height/videoScale;
+ background(0);
+ video = new Capture(this, cols, rows);
+ video.start()
+}
+
+// Read image from the camera
+void captureEvent(Capture video) {
+ video.read();
+}
+
+void draw() {
+ video.loadPixels();
+ // Begin loop for columns
+ for (int i = 0; i < cols; i++) {
+ // Begin loop for rows
+ for (int j = 0; j < rows; j++) {
+ // Where are you, pixel-wise?
+ int x = i*videoScale;
+ int y = j*videoScale;
+ color c = video.pixels[i + j*video.width];
+ fill(c);
+ stroke(0);
+ rect(x, y, videoScale, videoScale);
+ }
+ }
+}
+
+As you can see, expanding the simple grid system to include colors from video only requires a few additions. I have to declare and initialize the Capture object, read from it, and pull colors from the pixel array.
+
+Less literal mappings of pixel colors to shapes in the grid can also be applied. In the following example, only the colors black and white are used. Squares are larger where brighter pixels in the video appear, and smaller for darker pixels.
+
+// Each pixel from the video source is drawn as
+// a rectangle with size based on brightness.
+
+import processing.video.*;
+// Size of each cell in the grid
+int videoScale = 10;
+// Number of columns and rows in the system
+int cols, rows;
+// Variable for capture device
+Capture video;
+
+void setup() {
+ size(640, 480);
+ // Initialize columns and rows
+ cols = width / videoScale;
+ rows = height / videoScale;
+ // Construct the Capture object
+ video = new Capture(this, cols, rows);
+ video.start();
+}
+
+void captureEvent(Capture video) {
+ video.read();
+}
+
+void draw() {
+ background(0);
+ video.loadPixels();
+ // Begin loop for columns
+ for (int i = 0; i < cols; i++) {
+ // Begin loop for rows
+ for (int j = 0; j < rows; j++) {
+ // Where are you, pixel-wise?
+ int x = i*videoScale;
+ int y = j*videoScale;
+
+ // Reverse the column to mirro the image.
+ int loc = (video.width - i - 1) + j * video.width;
+
+ color c = video.pixels[loc];
+ // A rectangle's size is calculated as a function of the pixel’s brightness.
+ // A bright pixel is a large rectangle, and a dark pixel is a small one.
+ float sz = (brightness(c)/255) * videoScale;
+
+ rectMode(CENTER);
+ fill(255);
+ noStroke();
+ rect(x + videoScale/2, y + videoScale/2, sz, sz);
+ }
+ }
+}
+
+It’s often useful to think of developing software mirrors in two steps. This will also help you think beyondthe more obvious mapping of pixels to shapes on a grid.
+
+Step 1. Develop an interesting pattern that covers an entire window.
+
+Step 2. Use a video’s pixels as a look-up table for coloring that pattern.
+
+Say for Step 1, I write a program that scribbles a random line around the window. Here is my algorithm, written in pseudocode.
+
+
+
+ —Pick a new (x,y), staying within the window.
+ —Draw a line from the old (x,y) to the new (x,y).
+ —Save the new (x,y).
+
+
+// Two global variables
+float x;
+float y;
+
+void setup() {
+ size(320, 240);
+ background(255);
+ // Start x and y in the center
+ x = width/2;
+ y = height/2;
+}
+
+void draw() {
+ float newx = constrain(x + random(-20, 20), 0, width);
+ float newy = constrain(y + random(-20, 20), 0, height);
+
+ // Line from (x,y) to the (newx,newy)
+ stroke(0);
+ strokeWeight(4);
+ line(x, y, newx, newy);
+
+ x = newx;
+ y = newy;
+}
+
+Now that I have finished the pattern generating sketch, I can change stroke() to set a color according to the video image. Note again the new lines of code added in bold in the following code:
+
+
+
+import processing.video.*;
+// Two global variables
+float x;
+float y;
+
+// Variable to hold onto Capture object.
+Capture video;
+
+void setup() {
+ size(320, 240);
+ background(255);
+ // Start x and y in the center
+ x = width/2;
+ y = height/2;
+ // Start the capture process
+ video = new Capture(this, width, height);
+ video.start();
+}
+
+void captureEvent(Capture video) {
+ // Read image from the camera
+ video.read();
+}
+
+void draw() {
+ video.loadPixels();
+ float newx = constrain(x + random(-20, 20), 0, width);
+ float newy = constrain(y + random(-20, 20), 0, height-1);
+
+ // Find the midpoint of the line
+ int midx = int((newx + x) / 2);
+ int midy = int((newy + y) / 2);
+ // Pick the color from the video, reversing x
+ color c = video.pixels[(width-1-midx) + midy*video.width];
+
+ // Draw a line from (x,y) to (newx,newy)
+ stroke(c);
+ strokeWeight(4);
+ line(x, y, newx, newy);
+
+ // Save (newx,newy) in (x,y)
+ x = newx;
+ y = newy;
+}
+
+
+
+Download Processing. Processing is available for Linux, Mac OS X, and Windows. Select your choice to download the software below.
- if($thankYou): ?>
- Thank you for donating to the Processing Foundation.
- endif; ?>
-
-
-
-
-
-
-
-
-
- Stable Releases
-
-
- Pre-Releases
-
-
-
- Scott";
-$name = "Scott Murray";
-$email = "shm@alignedleft.com";
-
-
-
-// Build and send the email *using PHPMailer
-
-$mail = new PHPMailer();
-
-$mail->SMTPDebug = 3; //0 is no debug output, 3 is verbose
-
-$mail->IsSMTP();
-$mail->SMTPAuth = true;
-$mail->SMTPSecure = 'tls';
-$mail->Port = 25;
-$mail->Host = $mailConfig['host'];
-$mail->Username = $mailConfig['user'];
-$mail->Password = $mailConfig['pass'];
-
-$mail->From = 'foundation@processing.org';
-$mail->FromName = 'Processing Foundation';
-$mail->addAddress($email, $name);
-$mail->addBCC('foundation@processing.org');
-
-$message = str_replace('%name%', $name , $body) . "\n\n";
-$message .= "Email: " . $email . "
\n";
-
-$mail->isHTML(true);
-$mail->Subject = "Test message from Processing.org";
-$mail->Body = $message;
-
-if(!$mail->send()) {
- echo 'Message could not be sent.';
- echo 'Mailer Error: ' . $mail->ErrorInfo;
-} else {
- echo 'Message has been sent';
-}
-
-
-//echo("Download Processing. Please consider making a donation to the Processing Foundation before downloading the software.
-
-$=$amount?> will be donated to the Processing Foundation
-
-
-
-
-
-
\n";
- $message .= "Email: " . $email . "
\n";
- $message .= "Date: " . date('M j, Y', $date) . "
\n";
- $message .= "Best regards, and thanks again,
Ben Fry, Casey Reas, and Dan Shiffman";
-
- $mail->isHTML(true);
- $mail->Subject = $config['email-subject'];
- $mail->Body = $message;
-
- $mail->Send();
-
- $log = __DIR__ . '/../../../cred/purchases.log';
- $cleanDate = date('Y-m-d', $date);
- $data = $cleanDate."\t".$amount."\t".'paypal'."\t".$name."\t".$email."\t".get_client_ip()."\n";
- file_put_contents($log, $data, FILE_APPEND | LOCK_EX);
-
-
-}
-
-?>
\ No newline at end of file
diff --git a/download/_selectForm.php b/download/_selectForm.php
deleted file mode 100644
index a3ac30aff..000000000
--- a/download/_selectForm.php
+++ /dev/null
@@ -1,35 +0,0 @@
-Download Processing. Please consider making a donation to the Processing Foundation before downloading the software.
-
-
-
-
\n";
- $message .= "Email: " . $email . "
\n";
- $message .= "Date: " . date('M j, Y', $donation['created']) . "
\n";
- $message .= "Transaction ID: " . $donation['id'] . "
\n\n\n";
- $message .= "Best regards, and thanks again,
Ben Fry, Casey Reas, and Dan Shiffman";
-
- $mail->isHTML(true);
- $mail->Subject = $config['email-subject'];
- $mail->Body = $message;
-
- $mail->Send();
-
- $log = __DIR__ . '/../../../cred/purchases.log';
- $cleanDate = date('Y-m-d', $donation['created']);
- $data = $cleanDate."\t".$amount."\t".'stripe'."\t".$name."\t".$email."\t".get_client_ip()."\n";
- file_put_contents($log, $data, FILE_APPEND | LOCK_EX);
-
-
- // Forward to "Downloads" page
- header('Location: ' . $config['download']);
- exit;
-
- }
- catch (Stripe_Error $e) {
- $showPaymentForm = true;
- $dinky = $e->getJsonBody();
- $dinky = $dinky['error']['message'];
- }
- catch (Exception $e) {
- $error = $e->getMessage();
- }
-}
-
-?>
\ No newline at end of file
diff --git a/download/index.php b/download/index.php
deleted file mode 100755
index 7a84b8df2..000000000
--- a/download/index.php
+++ /dev/null
@@ -1,160 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\n";
- return $errorMsg;
- }
-}
diff --git a/download/phpmailer/class.pop3.php b/download/phpmailer/class.pop3.php
deleted file mode 100755
index d4082a0d7..000000000
--- a/download/phpmailer/class.pop3.php
+++ /dev/null
@@ -1,417 +0,0 @@
-
- * @author Andy Prevost
- * @author Jim Jagielski
- */
-
-class POP3 {
- /**
- * Default POP3 port
- * @var int
- */
- public $POP3_PORT = 110;
-
- /**
- * Default Timeout
- * @var int
- */
- public $POP3_TIMEOUT = 30;
-
- /**
- * POP3 Carriage Return + Line Feed
- * @var string
- */
- public $CRLF = "\r\n";
-
- /**
- * Displaying Debug warnings? (0 = now, 1+ = yes)
- * @var int
- */
- public $do_debug = 2;
-
- /**
- * POP3 Mail Server
- * @var string
- */
- public $host;
-
- /**
- * POP3 Port
- * @var int
- */
- public $port;
-
- /**
- * POP3 Timeout Value
- * @var int
- */
- public $tval;
-
- /**
- * POP3 Username
- * @var string
- */
- public $username;
-
- /**
- * POP3 Password
- * @var string
- */
- public $password;
-
- /**
- * Sets the POP3 PHPMailer Version number
- * @var string
- */
- public $Version = '5.2.4';
-
- /////////////////////////////////////////////////
- // PROPERTIES, PRIVATE AND PROTECTED
- /////////////////////////////////////////////////
-
- /**
- * @var resource Resource handle for the POP connection socket
- */
- private $pop_conn;
- /**
- * @var boolean Are we connected?
- */
- private $connected;
- /**
- * @var array Error container
- */
- private $error; // Error log array
-
- /**
- * Constructor, sets the initial values
- * @access public
- * @return POP3
- */
- public function __construct() {
- $this->pop_conn = 0;
- $this->connected = false;
- $this->error = null;
- }
-
- /**
- * Combination of public events - connect, login, disconnect
- * @access public
- * @param string $host
- * @param bool|int $port
- * @param bool|int $tval
- * @param string $username
- * @param string $password
- * @param int $debug_level
- * @return bool
- */
- public function Authorise ($host, $port = false, $tval = false, $username, $password, $debug_level = 0) {
- $this->host = $host;
-
- // If no port value is passed, retrieve it
- if ($port == false) {
- $this->port = $this->POP3_PORT;
- } else {
- $this->port = $port;
- }
-
- // If no port value is passed, retrieve it
- if ($tval == false) {
- $this->tval = $this->POP3_TIMEOUT;
- } else {
- $this->tval = $tval;
- }
-
- $this->do_debug = $debug_level;
- $this->username = $username;
- $this->password = $password;
-
- // Refresh the error log
- $this->error = null;
-
- // Connect
- $result = $this->Connect($this->host, $this->port, $this->tval);
-
- if ($result) {
- $login_result = $this->Login($this->username, $this->password);
-
- if ($login_result) {
- $this->Disconnect();
-
- return true;
- }
-
- }
-
- // We need to disconnect regardless if the login succeeded
- $this->Disconnect();
-
- return false;
- }
-
- /**
- * Connect to the POP3 server
- * @access public
- * @param string $host
- * @param bool|int $port
- * @param integer $tval
- * @return boolean
- */
- public function Connect ($host, $port = false, $tval = 30) {
- // Are we already connected?
- if ($this->connected) {
- return true;
- }
-
- /*
- On Windows this will raise a PHP Warning error if the hostname doesn't exist.
- Rather than supress it with @fsockopen, let's capture it cleanly instead
- */
-
- set_error_handler(array(&$this, 'catchWarning'));
-
- // Connect to the POP3 server
- $this->pop_conn = fsockopen($host, // POP3 Host
- $port, // Port #
- $errno, // Error Number
- $errstr, // Error Message
- $tval); // Timeout (seconds)
-
- // Restore the error handler
- restore_error_handler();
-
- // Does the Error Log now contain anything?
- if ($this->error && $this->do_debug >= 1) {
- $this->displayErrors();
- }
-
- // Did we connect?
- if ($this->pop_conn == false) {
- // It would appear not...
- $this->error = array(
- 'error' => "Failed to connect to server $host on port $port",
- 'errno' => $errno,
- 'errstr' => $errstr
- );
-
- if ($this->do_debug >= 1) {
- $this->displayErrors();
- }
-
- return false;
- }
-
- // Increase the stream time-out
-
- // Check for PHP 4.3.0 or later
- if (version_compare(phpversion(), '5.0.0', 'ge')) {
- stream_set_timeout($this->pop_conn, $tval, 0);
- } else {
- // Does not work on Windows
- if (substr(PHP_OS, 0, 3) !== 'WIN') {
- socket_set_timeout($this->pop_conn, $tval, 0);
- }
- }
-
- // Get the POP3 server response
- $pop3_response = $this->getResponse();
-
- // Check for the +OK
- if ($this->checkResponse($pop3_response)) {
- // The connection is established and the POP3 server is talking
- $this->connected = true;
- return true;
- }
- return false;
- }
-
- /**
- * Login to the POP3 server (does not support APOP yet)
- * @access public
- * @param string $username
- * @param string $password
- * @return boolean
- */
- public function Login ($username = '', $password = '') {
- if ($this->connected == false) {
- $this->error = 'Not connected to POP3 server';
-
- if ($this->do_debug >= 1) {
- $this->displayErrors();
- }
- }
-
- if (empty($username)) {
- $username = $this->username;
- }
-
- if (empty($password)) {
- $password = $this->password;
- }
-
- $pop_username = "USER $username" . $this->CRLF;
- $pop_password = "PASS $password" . $this->CRLF;
-
- // Send the Username
- $this->sendString($pop_username);
- $pop3_response = $this->getResponse();
-
- if ($this->checkResponse($pop3_response)) {
- // Send the Password
- $this->sendString($pop_password);
- $pop3_response = $this->getResponse();
-
- if ($this->checkResponse($pop3_response)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Disconnect from the POP3 server
- * @access public
- */
- public function Disconnect () {
- $this->sendString('QUIT');
-
- fclose($this->pop_conn);
- }
-
- /////////////////////////////////////////////////
- // Private Methods
- /////////////////////////////////////////////////
-
- /**
- * Get the socket response back.
- * $size is the maximum number of bytes to retrieve
- * @access private
- * @param integer $size
- * @return string
- */
- private function getResponse ($size = 128) {
- $pop3_response = fgets($this->pop_conn, $size);
-
- return $pop3_response;
- }
-
- /**
- * Send a string down the open socket connection to the POP3 server
- * @access private
- * @param string $string
- * @return integer
- */
- private function sendString ($string) {
- $bytes_sent = fwrite($this->pop_conn, $string, strlen($string));
-
- return $bytes_sent;
- }
-
- /**
- * Checks the POP3 server response for +OK or -ERR
- * @access private
- * @param string $string
- * @return boolean
- */
- private function checkResponse ($string) {
- if (substr($string, 0, 3) !== '+OK') {
- $this->error = array(
- 'error' => "Server reported an error: $string",
- 'errno' => 0,
- 'errstr' => ''
- );
-
- if ($this->do_debug >= 1) {
- $this->displayErrors();
- }
-
- return false;
- } else {
- return true;
- }
-
- }
-
- /**
- * If debug is enabled, display the error message array
- * @access private
- */
- private function displayErrors () {
- echo '';
-
- foreach ($this->error as $single_error) {
- print_r($single_error);
- }
-
- echo '';
- }
-
- /**
- * Takes over from PHP for the socket warning handler
- * @access private
- * @param integer $errno
- * @param string $errstr
- * @param string $errfile
- * @param integer $errline
- */
- private function catchWarning ($errno, $errstr, $errfile, $errline) {
- $this->error[] = array(
- 'error' => "Connecting to the POP3 server raised a PHP warning: ",
- 'errno' => $errno,
- 'errstr' => $errstr
- );
- }
-
- // End of class
-}
diff --git a/download/phpmailer/class.smtp.php b/download/phpmailer/class.smtp.php
deleted file mode 100755
index f0e4062ec..000000000
--- a/download/phpmailer/class.smtp.php
+++ /dev/null
@@ -1,1087 +0,0 @@
-Debugoutput == 'error_log') {
- error_log($str);
- } else {
- echo $str;
- }
- }
-
- /**
- * Initialize the class so that the data is in a known state.
- * @access public
- * @return SMTP
- */
- public function __construct() {
- $this->smtp_conn = 0;
- $this->error = null;
- $this->helo_rply = null;
-
- $this->do_debug = 0;
- }
-
- /////////////////////////////////////////////////
- // CONNECTION FUNCTIONS
- /////////////////////////////////////////////////
-
- /**
- * Connect to the server specified on the port specified.
- * If the port is not specified use the default SMTP_PORT.
- * If tval is specified then a connection will try and be
- * established with the server for that number of seconds.
- * If tval is not specified the default is 30 seconds to
- * try on the connection.
- *
- * SMTP CODE SUCCESS: 220
- * SMTP CODE FAILURE: 421
- * @access public
- * @param string $host
- * @param int $port
- * @param int $tval
- * @return bool
- */
- public function Connect($host, $port = 0, $tval = 30) {
- // set the error val to null so there is no confusion
- $this->error = null;
-
- // make sure we are __not__ connected
- if($this->connected()) {
- // already connected, generate error
- $this->error = array('error' => 'Already connected to a server');
- return false;
- }
-
- if(empty($port)) {
- $port = $this->SMTP_PORT;
- }
-
- // connect to the smtp server
- $this->smtp_conn = @fsockopen($host, // the host of the server
- $port, // the port to use
- $errno, // error number if any
- $errstr, // error message if any
- $tval); // give up after ? secs
- // verify we connected properly
- if(empty($this->smtp_conn)) {
- $this->error = array('error' => 'Failed to connect to server',
- 'errno' => $errno,
- 'errstr' => $errstr);
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ": $errstr ($errno)" . $this->CRLF . '
');
- }
- return false;
- }
-
- // SMTP server can take longer to respond, give longer timeout for first read
- // Windows does not have support for this timeout function
- if(substr(PHP_OS, 0, 3) != 'WIN') {
- $max = ini_get('max_execution_time');
- if ($max != 0 && $tval > $max) { // don't bother if unlimited
- @set_time_limit($tval);
- }
- stream_set_timeout($this->smtp_conn, $tval, 0);
- }
-
- // get any announcement
- $announce = $this->get_lines();
-
- if($this->do_debug >= 2) {
- $this->edebug('SMTP -> FROM SERVER:' . $announce . $this->CRLF . '
');
- }
-
- return true;
- }
-
- /**
- * Initiate a TLS communication with the server.
- *
- * SMTP CODE 220 Ready to start TLS
- * SMTP CODE 501 Syntax error (no parameters allowed)
- * SMTP CODE 454 TLS not available due to temporary reason
- * @access public
- * @return bool success
- */
- public function StartTLS() {
- $this->error = null; # to avoid confusion
-
- if(!$this->connected()) {
- $this->error = array('error' => 'Called StartTLS() without being connected');
- return false;
- }
-
- $this->client_send('STARTTLS' . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($this->do_debug >= 2) {
- $this->edebug('SMTP -> FROM SERVER:' . $rply . $this->CRLF . '
');
- }
-
- if($code != 220) {
- $this->error =
- array('error' => 'STARTTLS not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
-
- // Begin encrypted connection
- if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Performs SMTP authentication. Must be run after running the
- * Hello() method. Returns true if successfully authenticated.
- * @access public
- * @param string $username
- * @param string $password
- * @param string $authtype
- * @param string $realm
- * @param string $workstation
- * @return bool
- */
- public function Authenticate($username, $password, $authtype='LOGIN', $realm='', $workstation='') {
- if (empty($authtype)) {
- $authtype = 'LOGIN';
- }
-
- switch ($authtype) {
- case 'PLAIN':
- // Start authentication
- $this->client_send('AUTH PLAIN' . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 334) {
- $this->error =
- array('error' => 'AUTH not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- // Send encoded username and password
- $this->client_send(base64_encode("\0".$username."\0".$password) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 235) {
- $this->error =
- array('error' => 'Authentication not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- break;
- case 'LOGIN':
- // Start authentication
- $this->client_send('AUTH LOGIN' . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 334) {
- $this->error =
- array('error' => 'AUTH not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
-
- // Send encoded username
- $this->client_send(base64_encode($username) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 334) {
- $this->error =
- array('error' => 'Username not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
-
- // Send encoded password
- $this->client_send(base64_encode($password) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 235) {
- $this->error =
- array('error' => 'Password not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- break;
- case 'NTLM':
- /*
- * ntlm_sasl_client.php
- ** Bundled with Permission
- **
- ** How to telnet in windows: http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
- ** PROTOCOL Documentation http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
- */
- require_once 'extras/ntlm_sasl_client.php';
- $temp = new stdClass();
- $ntlm_client = new ntlm_sasl_client_class;
- if(! $ntlm_client->Initialize($temp)){//let's test if every function its available
- $this->error = array('error' => $temp->error);
- if($this->do_debug >= 1) {
- $this->edebug('You need to enable some modules in your php.ini file: ' . $this->error['error'] . $this->CRLF);
- }
- return false;
- }
- $msg1 = $ntlm_client->TypeMsg1($realm, $workstation);//msg1
-
- $this->client_send('AUTH NTLM ' . base64_encode($msg1) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
-
- if($code != 334) {
- $this->error =
- array('error' => 'AUTH not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF);
- }
- return false;
- }
-
- $challenge = substr($rply, 3);//though 0 based, there is a white space after the 3 digit number....//msg2
- $challenge = base64_decode($challenge);
- $ntlm_res = $ntlm_client->NTLMResponse(substr($challenge, 24, 8), $password);
- $msg3 = $ntlm_client->TypeMsg3($ntlm_res, $username, $realm, $workstation);//msg3
- // Send encoded username
- $this->client_send(base64_encode($msg3) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 235) {
- $this->error =
- array('error' => 'Could not authenticate',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF);
- }
- return false;
- }
- break;
- case 'CRAM-MD5':
- // Start authentication
- $this->client_send('AUTH CRAM-MD5' . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 334) {
- $this->error =
- array('error' => 'AUTH not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
-
- // Get the challenge
- $challenge = base64_decode(substr($rply, 4));
-
- // Build the response
- $response = $username . ' ' . $this->hmac($challenge, $password);
-
- // Send encoded credentials
- $this->client_send(base64_encode($response) . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($code != 334) {
- $this->error =
- array('error' => 'Credentials not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- break;
- }
- return true;
- }
-
- /**
- * Works like hash_hmac('md5', $data, $key) in case that function is not available
- * @access private
- * @param string $data
- * @param string $key
- * @return string
- */
- private function hmac($data, $key) {
- if (function_exists('hash_hmac')) {
- return hash_hmac('md5', $data, $key);
- }
-
- // The following borrowed from http://php.net/manual/en/function.mhash.php#27225
-
- // RFC 2104 HMAC implementation for php.
- // Creates an md5 HMAC.
- // Eliminates the need to install mhash to compute a HMAC
- // Hacked by Lance Rushing
-
- $b = 64; // byte length for md5
- if (strlen($key) > $b) {
- $key = pack('H*', md5($key));
- }
- $key = str_pad($key, $b, chr(0x00));
- $ipad = str_pad('', $b, chr(0x36));
- $opad = str_pad('', $b, chr(0x5c));
- $k_ipad = $key ^ $ipad ;
- $k_opad = $key ^ $opad;
-
- return md5($k_opad . pack('H*', md5($k_ipad . $data)));
- }
-
- /**
- * Returns true if connected to a server otherwise false
- * @access public
- * @return bool
- */
- public function Connected() {
- if(!empty($this->smtp_conn)) {
- $sock_status = stream_get_meta_data($this->smtp_conn);
- if($sock_status['eof']) {
- // the socket is valid but we are not connected
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> NOTICE:' . $this->CRLF . 'EOF caught while checking if connected');
- }
- $this->Close();
- return false;
- }
- return true; // everything looks good
- }
- return false;
- }
-
- /**
- * Closes the socket and cleans up the state of the class.
- * It is not considered good to use this function without
- * first trying to use QUIT.
- * @access public
- * @return void
- */
- public function Close() {
- $this->error = null; // so there is no confusion
- $this->helo_rply = null;
- if(!empty($this->smtp_conn)) {
- // close the connection and cleanup
- fclose($this->smtp_conn);
- $this->smtp_conn = 0;
- }
- }
-
- /////////////////////////////////////////////////
- // SMTP COMMANDS
- /////////////////////////////////////////////////
-
- /**
- * Issues a data command and sends the msg_data to the server
- * finializing the mail transaction. $msg_data is the message
- * that is to be send with the headers. Each header needs to be
- * on a single line followed by a
');
- }
-
- if($code != 354) {
- $this->error =
- array('error' => 'DATA command not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
-
- /* the server is ready to accept data!
- * according to rfc 821 we should not send more than 1000
- * including the CRLF
- * characters on a single line so we will break the data up
- * into lines by \r and/or \n then if needed we will break
- * each of those into smaller lines to fit within the limit.
- * in addition we will be looking for lines that start with
- * a period '.' and append and additional period '.' to that
- * line. NOTE: this does not count towards limit.
- */
-
- // normalize the line breaks so we know the explode works
- $msg_data = str_replace("\r\n", "\n", $msg_data);
- $msg_data = str_replace("\r", "\n", $msg_data);
- $lines = explode("\n", $msg_data);
-
- /* we need to find a good way to determine is headers are
- * in the msg_data or if it is a straight msg body
- * currently I am assuming rfc 822 definitions of msg headers
- * and if the first field of the first line (':' sperated)
- * does not contain a space then it _should_ be a header
- * and we can process all lines before a blank "" line as
- * headers.
- */
-
- $field = substr($lines[0], 0, strpos($lines[0], ':'));
- $in_headers = false;
- if(!empty($field) && !strstr($field, ' ')) {
- $in_headers = true;
- }
-
- $max_line_length = 998; // used below; set here for ease in change
-
- while(list(, $line) = @each($lines)) {
- $lines_out = null;
- if($line == '' && $in_headers) {
- $in_headers = false;
- }
- // ok we need to break this line up into several smaller lines
- while(strlen($line) > $max_line_length) {
- $pos = strrpos(substr($line, 0, $max_line_length), ' ');
-
- // Patch to fix DOS attack
- if(!$pos) {
- $pos = $max_line_length - 1;
- $lines_out[] = substr($line, 0, $pos);
- $line = substr($line, $pos);
- } else {
- $lines_out[] = substr($line, 0, $pos);
- $line = substr($line, $pos + 1);
- }
-
- /* if processing headers add a LWSP-char to the front of new line
- * rfc 822 on long msg headers
- */
- if($in_headers) {
- $line = "\t" . $line;
- }
- }
- $lines_out[] = $line;
-
- // send the lines to the server
- while(list(, $line_out) = @each($lines_out)) {
- if(strlen($line_out) > 0)
- {
- if(substr($line_out, 0, 1) == '.') {
- $line_out = '.' . $line_out;
- }
- }
- $this->client_send($line_out . $this->CRLF);
- }
- }
-
- // message data has been sent
- $this->client_send($this->CRLF . '.' . $this->CRLF);
-
- $rply = $this->get_lines();
- $code = substr($rply, 0, 3);
-
- if($this->do_debug >= 2) {
- $this->edebug('SMTP -> FROM SERVER:' . $rply . $this->CRLF . '
');
- }
-
- if($code != 250) {
- $this->error =
- array('error' => 'DATA not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- return true;
- }
-
- /**
- * Sends the HELO command to the smtp server.
- * This makes sure that we and the server are in
- * the same known state.
- *
- * Implements from rfc 821: HELO
');
- }
-
- if($code != 250) {
- $this->error =
- array('error' => $hello . ' not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
-
- $this->helo_rply = $rply;
-
- return true;
- }
-
- /**
- * Starts a mail transaction from the email address specified in
- * $from. Returns true if successful or false otherwise. If True
- * the mail transaction is started and then one or more Recipient
- * commands may be called followed by a Data command.
- *
- * Implements rfc 821: MAIL
');
- }
-
- if($code != 250) {
- $this->error =
- array('error' => 'MAIL not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- return true;
- }
-
- /**
- * Sends the quit command to the server and then closes the socket
- * if there is no error or the $close_on_error argument is true.
- *
- * Implements from rfc 821: QUIT
');
- }
-
- $rval = true;
- $e = null;
-
- $code = substr($byemsg, 0, 3);
- if($code != 221) {
- // use e as a tmp var cause Close will overwrite $this->error
- $e = array('error' => 'SMTP server rejected quit command',
- 'smtp_code' => $code,
- 'smtp_rply' => substr($byemsg, 4));
- $rval = false;
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $e['error'] . ': ' . $byemsg . $this->CRLF . '
');
- }
- }
-
- if(empty($e) || $close_on_error) {
- $this->Close();
- }
-
- return $rval;
- }
-
- /**
- * Sends the command RCPT to the SMTP server with the TO: argument of $to.
- * Returns true if the recipient was accepted false if it was rejected.
- *
- * Implements from rfc 821: RCPT
');
- }
-
- if($code != 250 && $code != 251) {
- $this->error =
- array('error' => 'RCPT not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- return true;
- }
-
- /**
- * Sends the RSET command to abort and transaction that is
- * currently in progress. Returns true if successful false
- * otherwise.
- *
- * Implements rfc 821: RSET
');
- }
-
- if($code != 250) {
- $this->error =
- array('error' => 'RSET failed',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Starts a mail transaction from the email address specified in
- * $from. Returns true if successful or false otherwise. If True
- * the mail transaction is started and then one or more Recipient
- * commands may be called followed by a Data command. This command
- * will send the message to the users terminal if they are logged
- * in and send them an email.
- *
- * Implements rfc 821: SAML
');
- }
-
- if($code != 250) {
- $this->error =
- array('error' => 'SAML not accepted from server',
- 'smtp_code' => $code,
- 'smtp_msg' => substr($rply, 4));
- if($this->do_debug >= 1) {
- $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply . $this->CRLF . '
');
- }
- return false;
- }
- return true;
- }
-
- /**
- * This is an optional command for SMTP that this class does not
- * support. This method is here to make the RFC821 Definition
- * complete for this class and __may__ be implimented in the future
- *
- * Implements from rfc 821: TURN
');
- }
- return false;
- }
-
- /**
- * Sends data to the server
- * @param string $data
- * @access public
- * @return Integer number of bytes sent to the server or FALSE on error
- */
- public function client_send($data) {
- if ($this->do_debug >= 1) {
- $this->edebug("CLIENT -> SMTP: $data" . $this->CRLF . '
');
- }
- return fwrite($this->smtp_conn, $data);
- }
-
- /**
- * Get the current error
- * @access public
- * @return array
- */
- public function getError() {
- return $this->error;
- }
-
- /////////////////////////////////////////////////
- // INTERNAL FUNCTIONS
- /////////////////////////////////////////////////
-
- /**
- * Read in as many lines as possible
- * either before eof or socket timeout occurs on the operation.
- * With SMTP we can tell if we have more lines to read if the
- * 4th character is '-' symbol. If it is a space then we don't
- * need to read anything else.
- * @access private
- * @return string
- */
- private function get_lines() {
- $data = '';
- $endtime = 0;
- /* If for some reason the fp is bad, don't inf loop */
- if (!is_resource($this->smtp_conn)) {
- return $data;
- }
- stream_set_timeout($this->smtp_conn, $this->Timeout);
- if ($this->Timelimit > 0) {
- $endtime = time() + $this->Timelimit;
- }
- while(is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
- $str = @fgets($this->smtp_conn, 515);
- if($this->do_debug >= 4) {
- $this->edebug("SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '
');
- $this->edebug("SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '
');
- }
- $data .= $str;
- if($this->do_debug >= 4) {
- $this->edebug("SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '
');
- }
- // if 4th character is a space, we are done reading, break the loop
- if(substr($str, 3, 1) == ' ') { break; }
- // Timed-out? Log and break
- $info = stream_get_meta_data($this->smtp_conn);
- if ($info['timed_out']) {
- if($this->do_debug >= 4) {
- $this->edebug('SMTP -> get_lines(): timed-out (' . $this->Timeout . ' seconds)
');
- }
- break;
- }
- // Now check if reads took too long
- if ($endtime) {
- if (time() > $endtime) {
- if($this->do_debug >= 4) {
- $this->edebug('SMTP -> get_lines(): timelimit reached (' . $this->Timelimit . ' seconds)
');
- }
- break;
- }
- }
- }
- return $data;
- }
-
-}
diff --git a/download/phpmailer529/.gitignore b/download/phpmailer529/.gitignore
deleted file mode 100755
index 989164d65..000000000
--- a/download/phpmailer529/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-docs/phpdoc/
-test/message.txt
-test/testbootstrap.php
-.idea
-build/
diff --git a/download/phpmailer529/.scrutinizer.yml b/download/phpmailer529/.scrutinizer.yml
deleted file mode 100755
index be706aeeb..000000000
--- a/download/phpmailer529/.scrutinizer.yml
+++ /dev/null
@@ -1,143 +0,0 @@
-before_commands:
- - "composer install --prefer-source"
-
-tools:
- # Code Coverage
- external_code_coverage:
- enabled: true
- timeout: 300
- filter:
- excluded_paths:
- - 'docs/*'
- - 'examples/*'
- - 'extras/*'
- - 'test/*'
- - 'vendor/*'
-
-
- php_code_coverage:
- enabled: false
- test_command: phpunit
- filter:
- excluded_paths:
- - 'docs/*'
- - 'examples/*'
- - 'extras/*'
- - 'test/*'
- - 'vendor/*'
-
-
- # Code Sniffer
- php_code_sniffer:
- enabled: true
- command: phpcs
- config:
- standard: PSR2
- sniffs:
- generic:
- files:
- one_class_per_file_sniff: false
- filter:
- excluded_paths:
- - 'docs/*'
- - 'examples/*'
- - 'extras/*'
- - 'test/*'
- - 'vendor/*'
-
-
- # Copy/Paste Detector
- php_cpd:
- enabled: true
- command: phpcpd
- excluded_dirs:
- - docs
- - examples
- - extras
- - test
- - vendor
-
-
- # PHP CS Fixer (http://http://cs.sensiolabs.org/).
- php_cs_fixer:
- enabled: true
- command: php-cs-fixer
- config:
- level: psr2
- filter:
- excluded_paths:
- - 'docs/*'
- - 'examples/*'
- - 'extras/*'
- - 'test/*'
- - 'vendor/*'
-
-
- # Analyzes the size and structure of a PHP project.
- php_loc:
- enabled: true
- command: phploc
- excluded_dirs:
- - docs
- - examples
- - extras
- - test
- - vendor
-
-
- # PHP Mess Detector (http://phpmd.org).
- php_mess_detector:
- enabled: true
- command: phpmd
- config:
- rulesets:
- - codesize
- - unusedcode
- - naming
- - design
- naming_rules:
- short_variable: { minimum: 2 }
- filter:
- excluded_paths:
- - 'docs/*'
- - 'examples/*'
- - 'extras/*'
- - 'test/*'
- - 'vendor/*'
-
- # Analyzes the size and structure of a PHP project.
- php_pdepend:
- enabled: true
- command: pdepend
- excluded_dirs:
- - docs
- - examples
- - extras
- - test
- - vendor
-
- # Runs Scrutinizer's PHP Analyzer Tool
- # https://scrutinizer-ci.com/docs/tools/php/php-analyzer/config_reference
- php_analyzer:
- enabled: true
- config:
- checkstyle:
- enabled: true
- naming:
- enabled: true
- property_name: ^[_a-zA-Z][a-zA-Z0-9_]*$ #Allow underscores & caps
- method_name: ^(?:[_a-zA-Z]|__)[a-zA-Z0-9_]*$ #Allow underscores & caps
- parameter_name: ^[a-z][a-zA-Z0-9_]*$ # Allow underscores
- local_variable: ^[a-zA-Z][a-zA-Z0-9_]*$ #Allow underscores & caps
- exception_name: ^[a-zA-Z][a-zA-Z0-9]*Exception$
- isser_method_name: ^(?:[_a-zA-Z]|__)[a-zA-Z0-9]*$ #Allow underscores & caps
- filter:
- excluded_paths:
- - 'docs/*'
- - 'examples/*'
- - 'extras/*'
- - 'test/*'
- - 'vendor/*'
-
- # Security Advisory Checker
- sensiolabs_security_checker: true
diff --git a/download/phpmailer529/.travis.yml b/download/phpmailer529/.travis.yml
deleted file mode 100755
index c49dd2182..000000000
--- a/download/phpmailer529/.travis.yml
+++ /dev/null
@@ -1,33 +0,0 @@
-language: php
-php:
- - 5.6
- - 5.5
- - 5.4
- - 5.3
- - hhvm
-
-matrix:
- allow_failures:
- - php: hhvm
-
-before_install:
- - sudo apt-get update -qq
- - sudo apt-get install -y -qq postfix
-before_script:
- - sudo service postfix stop
- - smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000 &
- - mkdir -p build/logs
- - cd test
- - cp testbootstrap-dist.php testbootstrap.php
- - chmod +x fakesendmail.sh
- - sudo mkdir -p /var/qmail/bin
- - sudo cp fakesendmail.sh /var/qmail/bin/sendmail
- - sudo cp fakesendmail.sh /usr/sbin/sendmail
- - echo 'sendmail_path = "/usr/sbin/sendmail -t -i "' | sudo tee "/home/travis/.phpenv/versions/`php -r 'echo PHP_VERSION;'`/etc/conf.d/sendmail.ini"
- - pwd
- - ls -al
-script:
- - phpunit --configuration ../travis.phpunit.xml.dist
-after_script:
- - wget https://scrutinizer-ci.com/ocular.phar
- - php ocular.phar code-coverage:upload --format=php-clover ../build/logs/clover.xml
diff --git a/download/phpmailer529/LICENSE b/download/phpmailer529/LICENSE
deleted file mode 100755
index 8e0763d1c..000000000
--- a/download/phpmailer529/LICENSE
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
-
-Other contributions are gladly received, whether in beer 🍺, T-shirts 👕, Amazon wishlist raids, or cold, hard cash 💰.
-
-## Changelog
-
-See [changelog](changelog.md).
-
-## History
-- PHPMailer was originally written in 2001 by Brent R. Matzelle as a [SourceForge project](http://sourceforge.net/projects/phpmailer/).
-- Marcus Bointon (coolbru on SF) and Andy Prevost (codeworxtech) took over the project in 2004.
-- Became an Apache incubator project on Google Code in 2010, managed by Jim Jagielski.
-- Marcus created his fork on [GitHub](https://github.com/Synchro/PHPMailer).
-- Jim and Marcus decide to join forces and use GitHub as the canonical and official repo for PHPMailer.
-- PHPMailer moves to the [PHPMailer organisation](https://github.com/PHPMailer) on GitHub.
-
-### What's changed since moving from SourceForge?
-- Official successor to the SourceForge and Google Code projects.
-- Test suite.
-- Continuous integration with Travis-CI.
-- Composer support.
-- Public development.
-- Additional languages and language strings.
-- CRAM-MD5 authentication support.
-- Preserves full repo history of authors, commits and branches from the original SourceForge project.
diff --git a/download/phpmailer529/VERSION b/download/phpmailer529/VERSION
deleted file mode 100755
index 485d792a3..000000000
--- a/download/phpmailer529/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-5.2.9
\ No newline at end of file
diff --git a/download/phpmailer529/changelog.md b/download/phpmailer529/changelog.md
deleted file mode 100755
index 52bc328ad..000000000
--- a/download/phpmailer529/changelog.md
+++ /dev/null
@@ -1,573 +0,0 @@
-# ChangeLog
-
-* Use `application/javascript` for .js attachments
-* Improve RFC2821 compliance for timelimits, especially for end-of-data
-* Add Azerbaijani translations (Thanks to @mirjalal)
-* Minor code cleanup for robustness
-* Add Indonesian translations (Thanks to @ceceprawiro)
-* Avoid `error_log` Debugoutput naming clash
-* Add ability to parse server capabilities in response to EHLO (useful for SendGrid etc)
-* Amended default values for WordWrap to match RFC
-* Remove html2text converter class, provide new mechanism for injecting converters
-* Improve pointers to docs and support in README
-* Add example file upload script
-* Refactor and major cleanup of EasyPeasyICS, now a lot more usable
-
-## Version 5.2.9 (Sept 25th 2014)
-* **Important: The autoloader is no longer autoloaded by the PHPMailer class**
-* Update html2text from https://github.com/mtibben/html2text
-* Improve Arabic translations (Thanks to @tarekdj)
-* Consistent handling of connection variables in SMTP and POP3
-* PHPDoc cleanup
-* Update composer to use PHPUnit 4.1
-* Pass consistent params to callbacks
-* More consistent handling of error states and debug output
-* Use property defaults, remove constructors
-* Remove unreachable code
-* Use older regex validation pattern for troublesome PCRE library versions
-* Improve PCRE detection in older PHP versions
-* Handle debug output consistently, and always in UTF-8
-* Allow user-defined debug output method via a callable
-* msgHTML now converts data URIs to embedded images
-* SMTP::getLastReply() will now always be populated
-* Improved example code in README
-* Ensure long filenames in Content-Disposition are encoded correctly
-* Simplify SMTP debug output mechanism, clarify levels with constants
-* Add SMTP connection check example
-* Simplify examples, don't use mysql* functions
-
-## Version 5.2.8 (May 14th 2014)
-* Increase timeout to match RFC2821 section 4.5.3.2 and thus not fail greetdelays, fixes #104
-* Add timestamps to default debug output
-* Add connection events and new level 3 to debug output options
-* Chinese language update (Thanks to @binaryoung)
-* Allow custom Mailer types (Thanks to @michield)
-* Cope with spaces around SMTP host specs
-* Fix processing of multiple hosts in connect string
-* Added Galician translation (Thanks to @donatorouco)
-* Autoloader now prepends
-* Docs updates
-* Add Latvian translation (Thanks to @eddsstudio)
-* Add Belarusian translation (Thanks to @amaksymiuk)
-* Make autoloader work better on older PHP versions
-* Avoid double-encoding if mbstring is overloading mail()
-* Add Portuguese translation (Thanks to @Jonadabe)
-* Make quoted-printable encoder respect line ending setting
-* Improve Chinese translation (Thanks to @PeterDaveHello)
-* Add Georgian translation (Thanks to @akalongman)
-* Add Greek translation (Thanks to @lenasterg)
-* Fix serverHostname on PHP < 5.3
-* Improve performance of SMTP class
-* Implement automatic 7bit downgrade
-* Add Vietnamese translation (Thanks to @vinades)
-* Improve example images, switch to PNG
-* Add Croatian translation (Thanks to @hrvoj3e)
-* Remove setting the Return-Path and deprecate the Return-path property - it's just wrong!
-* Fix language file loading if CWD has changed (@stephandesouza)
-* Add HTML5 email validation pattern
-* Improve Turkish translations (Thanks to @yasinaydin)
-* Improve Romanian translations (Thanks to @aflorea)
-* Check php.ini for path to sendmail/qmail before using default
-* Improve Farsi translation (Thanks to @MHM5000)
-* Don't use quoted-printable encoding for multipart types
-* Add Serbian translation (Thanks to ajevremovic at gmail.com)
-* Remove useless PHP5 check
-* Use SVG for build status badges
-* Store MessageDate on creation
-* Better default behaviour for validateAddress
-
-## Version 5.2.7 (September 12th 2013)
-* Add Ukrainian translation from @Krezalis
-* Support for do_verp
-* Fix bug in CRAM-MD5 AUTH
-* Propagate Debugoutput option to SMTP class (@Reblutus)
-* Determine MIME type of attachments automatically
-* Add cross-platform, multibyte-safe pathinfo replacement (with tests) and use it
-* Add a new 'html' Debugoutput type
-* Clean up SMTP debug output, remove embedded HTML
-* Some small changes in header formatting to improve IETF msglint test results
-* Update test_script to use some recently changed features, rename to code_generator
-* Generated code actually works!
-* Update SyntaxHighlighter
-* Major overhaul and cleanup of example code
-* New PHPMailer graphic
-* msgHTML now uses RFC2392-compliant content ids
-* Add line break normalization function and use it in msgHTML
-* Don't set unnecessary reply-to addresses
-* Make fakesendmail.sh a bit cleaner and safer
-* Set a content-transfer-encoding on multiparts (fixes msglint error)
-* Fix cid generation in msgHTML (Thanks to @digitalthought)
-* Fix handling of multiple SMTP servers (Thanks to @NanoCaiordo)
-* SMTP->connect() now supports stream context options (Thanks to @stanislavdavid)
-* Add support for iCal event alternatives (Thanks to @reblutus)
-* Update to Polish language file (Thanks to Krzysztof Kowalewski)
-* Update to Norwegian language file (Thanks to @datagutten)
-* Update to Hungarian language file (Thanks to @dominicus-75)
-* Add Persian/Farsi translation from @jaii
-* Make SMTPDebug property type match type in SMTP class
-* Add unit tests for DKIM
-* Major refactor of SMTP class
-* Reformat to PSR-2 coding standard
-* Introduce autoloader
-* Allow overriding of SMTP class
-* Overhaul of PHPDocs
-* Fix broken Q-encoding
-* Czech language update (Thanks to @nemelu)
-* Removal of excess blank lines in messages
-* Added fake POP server and unit tests for POP-before-SMTP
-
-## Version 5.2.6 (April 11th 2013)
-* Reflect move to PHPMailer GitHub organisation at https://github.com/PHPMailer/PHPMailer
-* Fix unbumped version numbers
-* Update packagist.org with new location
-* Clean up Changelog
-
-## Version 5.2.5 (April 6th 2013)
-* First official release after move from Google Code
-* Fixes for qmail when sending via mail()
-* Merge in changes from Google code 5.2.4 release
-* Minor coding standards cleanup in SMTP class
-* Improved unit tests, now tests S/MIME signing
-* Travis-CI support on GitHub, runs tests with fake SMTP server
-
-## Version 5.2.4 (February 19, 2013)
-* Fix tag and version bug.
-* un-deprecate isSMTP(), isMail(), IsSendmail() and isQmail().
-* Numerous translation updates
-
-## Version 5.2.3 (February 8, 2013)
-* Fix issue with older PCREs and ValidateAddress() (Bugz: 124)
-* Add CRAM-MD5 authentication, thanks to Elijah madden, https://github.com/okonomiyaki3000
-* Replacement of obsolete Quoted-Printable encoder with a much better implementation
-* Composer package definition
-* New language added: Hebrew
-
-## Version 5.2.2 (December 3, 2012)
-* Some fixes and syncs from https://github.com/Synchro/PHPMailer
-* Add Slovak translation, thanks to Michal Tinka
-
-## Version 5.2.2-rc2 (November 6, 2012)
-* Fix SMTP server rotation (Bugz: 118)
-* Allow override of autogen'ed 'Date' header (for Drupal's
- og_mailinglist module)
-* No whitespace after '-f' option (Bugz: 116)
-* Work around potential warning (Bugz: 114)
-
-## Version 5.2.2-rc1 (September 28, 2012)
-* Header encoding works with long lines (Bugz: 93)
-* Turkish language update (Bugz: 94)
-* undefined $pattern in EncodeQ bug squashed (Bugz: 98)
-* use of mail() in safe_mode now works (Bugz: 96)
-* ValidateAddress() now 'public static' so people can override the
- default and use their own validation scheme.
-* ValidateAddress() no longer uses broken FILTER_VALIDATE_EMAIL
-* Added in AUTH PLAIN SMTP authentication
-
-## Version 5.2.2-beta2 (August 17, 2012)
-* Fixed Postfix VERP support (Bugz: 92)
-* Allow action_function callbacks to pass/use
- the From address (passed as final param)
-* Prevent inf look for get_lines() (Bugz: 77)
-* New public var ($UseSendmailOptions). Only pass sendmail()
- options iff we really are using sendmail or something sendmail
- compatible. (Bugz: 75)
-* default setting for LE returned to "\n" due to popular demand.
-
-## Version 5.2.2-beta1 (July 13, 2012)
-* Expose PreSend() and PostSend() as public methods to allow
- for more control if serializing message sending.
-* GetSentMIMEMessage() only constructs the message copy when
- needed. Save memory.
-* Only pass params to mail() if the underlying MTA is
- "sendmail" (as defined as "having the string sendmail
- in its pathname") [#69]
-* Attachments now work with Amazon SES and others [Bugz#70]
-* Debug output now sent to stdout (via echo) or error_log [Bugz#5]
-* New var: Debugoutput (for above) [Bugz#5]
-* SMTP reads now Timeout aware (new var: Timeout=15) [Bugz#71]
-* SMTP reads now can have a Timelimit associated with them
- (new var: Timelimit=30)[Bugz#71]
-* Fix quoting issue associated with charsets
-* default setting for LE is now RFC compliant: "\r\n"
-* Return-Path can now be user defined (new var: ReturnPath)
- (the default is "" which implies no change from previous
- behavior, which was to use either From or Sender) [Bugz#46]
-* X-Mailer header can now be disabled (by setting to a
- whitespace string, eg " ") [Bugz#66]
-* Bugz closed: #68, #60, #42, #43, #59, #55, #66, #48, #49,
- #52, #31, #41, #5. #70, #69
-
-## Version 5.2.1 (January 16, 2012)
-* Closed several bugs #5
-* Performance improvements
-* MsgHTML() now returns the message as required.
-* New method: GetSentMIMEMessage() (returns full copy of sent message)
-
-## Version 5.2 (July 19, 2011)
-* protected MIME body and header
-* better DKIM DNS Resource Record support
-* better aly handling
-* htmlfilter class added to extras
-* moved to Apache Extras
-
-## Version 5.1 (October 20, 2009)
-* fixed filename issue with AddStringAttachment (thanks to Tony)
-* fixed "SingleTo" property, now works with Senmail, Qmail, and SMTP in
- addition to PHP mail()
-* added DKIM digital signing functionality, new properties:
- - DKIM_domain (sets the domain name)
- - DKIM_private (holds DKIM private key)
- - DKIM_passphrase (holds your DKIM passphrase)
- - DKIM_selector (holds the DKIM "selector")
- - DKIM_identity (holds the identifying email address)
-* added callback function support
- - callback function parameters include:
- result, to, cc, bcc, subject and body
- - see the test/test_callback.php file for usage.
-* added "auto" identity functionality
- - can automatically add:
- - Return-path (if Sender not set)
- - Reply-To (if ReplyTo not set)
- - can be disabled:
- - $mail->SetFrom('yourname@yourdomain.com','First Last',false);
- - or by adding the $mail->Sender and/or $mail->ReplyTo properties
-
-Note: "auto" identity added to help with emails ending up in spam or junk boxes because of missing headers
-
-## Version 5.0.2 (May 24, 2009)
-* Fix for missing attachments when inline graphics are present
-* Fix for missing Cc in header when using SMTP (mail was sent,
- but not displayed in header -- Cc receiver only saw email To:
- line and no Cc line, but did get the email (To receiver
- saw same)
-
-## Version 5.0.1 (April 05, 2009)
-* Temporary fix for missing attachments
-
-## Version 5.0.0 (April 02, 2009)
-With the release of this version, we are initiating a new version numbering
-system to differentiate from the PHP4 version of PHPMailer.
-Most notable in this release is fully object oriented code.
-
-### class.smtp.php:
-* Refactored class.smtp.php to support new exception handling
-* code size reduced from 29.2 Kb to 25.6 Kb
-* Removed unnecessary functions from class.smtp.php:
- - public function Expand($name) {
- - public function Help($keyword="") {
- - public function Noop() {
- - public function Send($from) {
- - public function SendOrMail($from) {
- - public function Verify($name) {
-
-### class.phpmailer.php:
-* Refactored class.phpmailer.php with new exception handling
-* Changed processing functionality of Sendmail and Qmail so they cannot be
- inadvertently used
-* removed getFile() function, just became a simple wrapper for
- file_get_contents()
-* added check for PHP version (will gracefully exit if not at least PHP 5.0)
-* enhanced code to check if an attachment source is the same as an embedded or
- inline graphic source to eliminate duplicate attachments
-
-### New /test_script
-We have written a test script you can use to test the script as part of your
-installation. Once you press submit, the test script will send a multi-mime
-email with either the message you type in or an HTML email with an inline
-graphic. Two attachments are included in the email (one of the attachments
-is also the inline graphic so you can see that only one copy of the graphic
-is sent in the email). The test script will also display the functional
-script that you can copy/paste to your editor to duplicate the functionality.
-
-### New examples
-All new examples in both basic and advanced modes. Advanced examples show
- Exception handling.
-
-### PHPDocumentator (phpdocs) documentation for PHPMailer version 5.0.0
-All new documentation
-
-## Version 2.3 (November 06, 2008)
-* added Arabic language (many thanks to Bahjat Al Mostafa)
-* removed English language from language files and made it a default within
- class.phpmailer.php - if no language is found, it will default to use
- the english language translation
-* fixed public/private declarations
-* corrected line 1728, $basedir to $directory
-* added $sign_cert_file to avoid improper duplicate use of $sign_key_file
-* corrected $this->Hello on line 612 to $this->Helo
-* changed default of $LE to "\r\n" to comply with RFC 2822. Can be set by the user
- if default is not acceptable
-* removed trim() from return results in EncodeQP
-* /test and three files it contained are removed from version 2.3
-* fixed phpunit.php for compliance with PHP5
-* changed $this->AltBody = $textMsg; to $this->AltBody = html_entity_decode($textMsg);
-* We have removed the /phpdoc from the downloads. All documentation is now on
- the http://phpmailer.codeworxtech.com website.
-
-## Version 2.2.1 () July 19 2008
-* fixed line 1092 in class.smtp.php (my apologies, error on my part)
-
-## Version 2.2 () July 15 2008
-* Fixed redirect issue (display of UTF-8 in thank you redirect)
-* fixed error in getResponse function declaration (class.pop3.php)
-* PHPMailer now PHP6 compliant
-* fixed line 1092 in class.smtp.php (endless loop from missing = sign)
-
-## Version 2.1 (Wed, June 04 2008)
-NOTE: WE HAVE A NEW LANGUAGE VARIABLE FOR DIGITALLY SIGNED S/MIME EMAILS. IF YOU CAN HELP WITH LANGUAGES OTHER THAN ENGLISH AND SPANISH, IT WOULD BE APPRECIATED.
-
-* added S/MIME functionality (ability to digitally sign emails)
- BIG THANKS TO "sergiocambra" for posting this patch back in November 2007.
- The "Signed Emails" functionality adds the Sign method to pass the private key
- filename and the password to read it, and then email will be sent with
- content-type multipart/signed and with the digital signature attached.
-* fully compatible with E_STRICT error level
- - Please note:
- In about half the test environments this development version was subjected
- to, an error was thrown for the date() functions used (line 1565 and 1569).
- This is NOT a PHPMailer error, it is the result of an incorrectly configured
- PHP5 installation. The fix is to modify your 'php.ini' file and include the
- date.timezone = Etc/UTC (or your own zone)
- directive, to your own server timezone
- - If you do get this error, and are unable to access your php.ini file:
- In your PHP script, add
- `date_default_timezone_set('Etc/UTC');`
- - do not try to use
- `$myVar = date_default_timezone_get();`
- as a test, it will throw an error.
-* added ability to define path (mainly for embedded images)
- function `MsgHTML($message,$basedir='')` ... where:
- `$basedir` is the fully qualified path
-* fixed `MsgHTML()` function:
- - Embedded Images where images are specified by `
`, appropriate for browser output
- * * `error_log` Output to error log as configured in php.ini
- *
- * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
- *
- * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
- *
- * @type string|callable
- * @see SMTP::$Debugoutput
- */
- public $Debugoutput = 'echo';
-
- /**
- * Whether to keep SMTP connection open after each message.
- * If this is set to true then to close the connection
- * requires an explicit call to smtpClose().
- * @type boolean
- */
- public $SMTPKeepAlive = false;
-
- /**
- * Whether to split multiple to addresses into multiple messages
- * or send them all in one message.
- * @type boolean
- */
- public $SingleTo = false;
-
- /**
- * Storage for addresses when SingleTo is enabled.
- * @type array
- * @TODO This should really not be public
- */
- public $SingleToArray = array();
-
- /**
- * Whether to generate VERP addresses on send.
- * Only applicable when sending via SMTP.
- * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
- * @link http://www.postfix.org/VERP_README.html Postfix VERP info
- * @type boolean
- */
- public $do_verp = false;
-
- /**
- * Whether to allow sending messages with an empty body.
- * @type boolean
- */
- public $AllowEmpty = false;
-
- /**
- * The default line ending.
- * @note The default remains "\n". We force CRLF where we know
- * it must be used via self::CRLF.
- * @type string
- */
- public $LE = "\n";
-
- /**
- * DKIM selector.
- * @type string
- */
- public $DKIM_selector = '';
-
- /**
- * DKIM Identity.
- * Usually the email address used as the source of the email
- * @type string
- */
- public $DKIM_identity = '';
-
- /**
- * DKIM passphrase.
- * Used if your key is encrypted.
- * @type string
- */
- public $DKIM_passphrase = '';
-
- /**
- * DKIM signing domain name.
- * @example 'example.com'
- * @type string
- */
- public $DKIM_domain = '';
-
- /**
- * DKIM private key file path.
- * @type string
- */
- public $DKIM_private = '';
-
- /**
- * Callback Action function name.
- *
- * The function that handles the result of the send email action.
- * It is called out by send() for each email sent.
- *
- * Value can be any php callable: http://www.php.net/is_callable
- *
- * Parameters:
- * boolean $result result of the send action
- * string $to email address of the recipient
- * string $cc cc email addresses
- * string $bcc bcc email addresses
- * string $subject the subject
- * string $body the email body
- * string $from email address of sender
- * @type string
- */
- public $action_function = '';
-
- /**
- * What to use in the X-Mailer header.
- * Options: null for default, whitespace for none, or a string to use
- * @type string
- */
- public $XMailer = '';
-
- /**
- * An instance of the SMTP sender class.
- * @type SMTP
- * @access protected
- */
- protected $smtp = null;
-
- /**
- * The array of 'to' addresses.
- * @type array
- * @access protected
- */
- protected $to = array();
-
- /**
- * The array of 'cc' addresses.
- * @type array
- * @access protected
- */
- protected $cc = array();
-
- /**
- * The array of 'bcc' addresses.
- * @type array
- * @access protected
- */
- protected $bcc = array();
-
- /**
- * The array of reply-to names and addresses.
- * @type array
- * @access protected
- */
- protected $ReplyTo = array();
-
- /**
- * An array of all kinds of addresses.
- * Includes all of $to, $cc, $bcc, $replyto
- * @type array
- * @access protected
- */
- protected $all_recipients = array();
-
- /**
- * The array of attachments.
- * @type array
- * @access protected
- */
- protected $attachment = array();
-
- /**
- * The array of custom headers.
- * @type array
- * @access protected
- */
- protected $CustomHeader = array();
-
- /**
- * The most recent Message-ID (including angular brackets).
- * @type string
- * @access protected
- */
- protected $lastMessageID = '';
-
- /**
- * The message's MIME type.
- * @type string
- * @access protected
- */
- protected $message_type = '';
-
- /**
- * The array of MIME boundary strings.
- * @type array
- * @access protected
- */
- protected $boundary = array();
-
- /**
- * The array of available languages.
- * @type array
- * @access protected
- */
- protected $language = array();
-
- /**
- * The number of errors encountered.
- * @type integer
- * @access protected
- */
- protected $error_count = 0;
-
- /**
- * The S/MIME certificate file path.
- * @type string
- * @access protected
- */
- protected $sign_cert_file = '';
-
- /**
- * The S/MIME key file path.
- * @type string
- * @access protected
- */
- protected $sign_key_file = '';
-
- /**
- * The S/MIME password for the key.
- * Used only if the key is encrypted.
- * @type string
- * @access protected
- */
- protected $sign_key_pass = '';
-
- /**
- * Whether to throw exceptions for errors.
- * @type boolean
- * @access protected
- */
- protected $exceptions = false;
-
- /**
- * Error severity: message only, continue processing.
- */
- const STOP_MESSAGE = 0;
-
- /**
- * Error severity: message, likely ok to continue processing.
- */
- const STOP_CONTINUE = 1;
-
- /**
- * Error severity: message, plus full stop, critical error reached.
- */
- const STOP_CRITICAL = 2;
-
- /**
- * SMTP RFC standard line ending.
- */
- const CRLF = "\r\n";
-
- /**
- * Constructor.
- * @param boolean $exceptions Should we throw external exceptions?
- */
- public function __construct($exceptions = false)
- {
- $this->exceptions = (boolean)$exceptions;
- }
-
- /**
- * Destructor.
- */
- public function __destruct()
- {
- if ($this->Mailer == 'smtp') { //close any open SMTP connection nicely
- $this->smtpClose();
- }
- }
-
- /**
- * Call mail() in a safe_mode-aware fashion.
- * Also, unless sendmail_path points to sendmail (or something that
- * claims to be sendmail), don't pass params (not a perfect fix,
- * but it will do)
- * @param string $to To
- * @param string $subject Subject
- * @param string $body Message Body
- * @param string $header Additional Header(s)
- * @param string $params Params
- * @access private
- * @return boolean
- */
- private function mailPassthru($to, $subject, $body, $header, $params)
- {
- //Check overloading of mail function to avoid double-encoding
- if (ini_get('mbstring.func_overload') & 1) {
- $subject = $this->secureHeader($subject);
- } else {
- $subject = $this->encodeHeader($this->secureHeader($subject));
- }
- if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
- $result = @mail($to, $subject, $body, $header);
- } else {
- $result = @mail($to, $subject, $body, $header, $params);
- }
- return $result;
- }
-
- /**
- * Output debugging info via user-defined method.
- * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
- * @see PHPMailer::$Debugoutput
- * @see PHPMailer::$SMTPDebug
- * @param string $str
- */
- protected function edebug($str)
- {
- if ($this->SMTPDebug <= 0) {
- return;
- }
- //Avoid clash with built-in function names
- if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
- call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
- return;
- }
- switch ($this->Debugoutput) {
- case 'error_log':
- //Don't output, just log
- error_log($str);
- break;
- case 'html':
- //Cleans up output a bit for a better looking, HTML-safe output
- echo htmlentities(
- preg_replace('/[\r\n]+/', '', $str),
- ENT_QUOTES,
- 'UTF-8'
- )
- . "
\n";
- break;
- case 'echo':
- default:
- //Normalize line breaks
- $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
- echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
- "\n",
- "\n \t ",
- trim($str)
- ) . "\n";
- }
- }
-
- /**
- * Sets message type to HTML or plain.
- * @param boolean $isHtml True for HTML mode.
- * @return void
- */
- public function isHTML($isHtml = true)
- {
- if ($isHtml) {
- $this->ContentType = 'text/html';
- } else {
- $this->ContentType = 'text/plain';
- }
- }
-
- /**
- * Send messages using SMTP.
- * @return void
- */
- public function isSMTP()
- {
- $this->Mailer = 'smtp';
- }
-
- /**
- * Send messages using PHP's mail() function.
- * @return void
- */
- public function isMail()
- {
- $this->Mailer = 'mail';
- }
-
- /**
- * Send messages using $Sendmail.
- * @return void
- */
- public function isSendmail()
- {
- $ini_sendmail_path = ini_get('sendmail_path');
-
- if (!stristr($ini_sendmail_path, 'sendmail')) {
- $this->Sendmail = '/usr/sbin/sendmail';
- } else {
- $this->Sendmail = $ini_sendmail_path;
- }
- $this->Mailer = 'sendmail';
- }
-
- /**
- * Send messages using qmail.
- * @return void
- */
- public function isQmail()
- {
- $ini_sendmail_path = ini_get('sendmail_path');
-
- if (!stristr($ini_sendmail_path, 'qmail')) {
- $this->Sendmail = '/var/qmail/bin/qmail-inject';
- } else {
- $this->Sendmail = $ini_sendmail_path;
- }
- $this->Mailer = 'qmail';
- }
-
- /**
- * Add a "To" address.
- * @param string $address
- * @param string $name
- * @return boolean true on success, false if address already used
- */
- public function addAddress($address, $name = '')
- {
- return $this->addAnAddress('to', $address, $name);
- }
-
- /**
- * Add a "CC" address.
- * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
- * @param string $address
- * @param string $name
- * @return boolean true on success, false if address already used
- */
- public function addCC($address, $name = '')
- {
- return $this->addAnAddress('cc', $address, $name);
- }
-
- /**
- * Add a "BCC" address.
- * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
- * @param string $address
- * @param string $name
- * @return boolean true on success, false if address already used
- */
- public function addBCC($address, $name = '')
- {
- return $this->addAnAddress('bcc', $address, $name);
- }
-
- /**
- * Add a "Reply-to" address.
- * @param string $address
- * @param string $name
- * @return boolean
- */
- public function addReplyTo($address, $name = '')
- {
- return $this->addAnAddress('Reply-To', $address, $name);
- }
-
- /**
- * Add an address to one of the recipient arrays.
- * Addresses that have been added already return false, but do not throw exceptions
- * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
- * @param string $address The email address to send to
- * @param string $name
- * @throws phpmailerException
- * @return boolean true on success, false if address already used or invalid in some way
- * @access protected
- */
- protected function addAnAddress($kind, $address, $name = '')
- {
- if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
- $this->setError($this->lang('Invalid recipient array') . ': ' . $kind);
- $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind);
- if ($this->exceptions) {
- throw new phpmailerException('Invalid recipient array: ' . $kind);
- }
- return false;
- }
- $address = trim($address);
- $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
- if (!$this->validateAddress($address)) {
- $this->setError($this->lang('invalid_address') . ': ' . $address);
- $this->edebug($this->lang('invalid_address') . ': ' . $address);
- if ($this->exceptions) {
- throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
- }
- return false;
- }
- if ($kind != 'Reply-To') {
- if (!isset($this->all_recipients[strtolower($address)])) {
- array_push($this->$kind, array($address, $name));
- $this->all_recipients[strtolower($address)] = true;
- return true;
- }
- } else {
- if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
- $this->ReplyTo[strtolower($address)] = array($address, $name);
- return true;
- }
- }
- return false;
- }
-
- /**
- * Set the From and FromName properties.
- * @param string $address
- * @param string $name
- * @param boolean $auto Whether to also set the Sender address, defaults to true
- * @throws phpmailerException
- * @return boolean
- */
- public function setFrom($address, $name = '', $auto = true)
- {
- $address = trim($address);
- $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
- if (!$this->validateAddress($address)) {
- $this->setError($this->lang('invalid_address') . ': ' . $address);
- $this->edebug($this->lang('invalid_address') . ': ' . $address);
- if ($this->exceptions) {
- throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
- }
- return false;
- }
- $this->From = $address;
- $this->FromName = $name;
- if ($auto) {
- if (empty($this->Sender)) {
- $this->Sender = $address;
- }
- }
- return true;
- }
-
- /**
- * Return the Message-ID header of the last email.
- * Technically this is the value from the last time the headers were created,
- * but it's also the message ID of the last sent message except in
- * pathological cases.
- * @return string
- */
- public function getLastMessageID()
- {
- return $this->lastMessageID;
- }
-
- /**
- * Check that a string looks like an email address.
- * @param string $address The email address to check
- * @param string $patternselect A selector for the validation pattern to use :
- * * `auto` Pick strictest one automatically;
- * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
- * * `pcre` Use old PCRE implementation;
- * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; same as pcre8 but does not allow 'dotless' domains;
- * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
- * * `noregex` Don't use a regex: super fast, really dumb.
- * @return boolean
- * @static
- * @access public
- */
- public static function validateAddress($address, $patternselect = 'auto')
- {
- if (!$patternselect or $patternselect == 'auto') {
- //Check this constant first so it works when extension_loaded() is disabled by safe mode
- //Constant was added in PHP 5.2.4
- if (defined('PCRE_VERSION')) {
- //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
- if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
- $patternselect = 'pcre8';
- } else {
- $patternselect = 'pcre';
- }
- } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
- //Fall back to older PCRE
- $patternselect = 'pcre';
- } else {
- //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
- if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
- $patternselect = 'php';
- } else {
- $patternselect = 'noregex';
- }
- }
- }
- switch ($patternselect) {
- case 'pcre8':
- /**
- * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
- * @link http://squiloople.com/2009/12/20/email-address-validation/
- * @copyright 2009-2010 Michael Rushton
- * Feel free to use and redistribute this code. But please keep this copyright notice.
- */
- return (boolean)preg_match(
- '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
- '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
- '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
- '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
- '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
- '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
- '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
- '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
- '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
- $address
- );
- case 'pcre':
- //An older regex that doesn't need a recent PCRE
- return (boolean)preg_match(
- '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
- '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
- '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
- '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
- '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
- '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
- '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
- '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
- '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
- '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
- $address
- );
- case 'html5':
- /**
- * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
- * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
- */
- return (boolean)preg_match(
- '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
- '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
- $address
- );
- case 'noregex':
- //No PCRE! Do something _very_ approximate!
- //Check the address is 3 chars or longer and contains an @ that's not the first or last char
- return (strlen($address) >= 3
- and strpos($address, '@') >= 1
- and strpos($address, '@') != strlen($address) - 1);
- case 'php':
- default:
- return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
- }
- }
-
- /**
- * Create a message and send it.
- * Uses the sending method specified by $Mailer.
- * @throws phpmailerException
- * @return boolean false on error - See the ErrorInfo property for details of the error.
- */
- public function send()
- {
- try {
- if (!$this->preSend()) {
- return false;
- }
- return $this->postSend();
- } catch (phpmailerException $exc) {
- $this->mailHeader = '';
- $this->setError($exc->getMessage());
- if ($this->exceptions) {
- throw $exc;
- }
- return false;
- }
- }
-
- /**
- * Prepare a message for sending.
- * @throws phpmailerException
- * @return boolean
- */
- public function preSend()
- {
- try {
- $this->mailHeader = '';
- if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
- throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
- }
-
- // Set whether the message is multipart/alternative
- if (!empty($this->AltBody)) {
- $this->ContentType = 'multipart/alternative';
- }
-
- $this->error_count = 0; // reset errors
- $this->setMessageType();
- // Refuse to send an empty message unless we are specifically allowing it
- if (!$this->AllowEmpty and empty($this->Body)) {
- throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
- }
-
- $this->MIMEHeader = $this->createHeader();
- $this->MIMEBody = $this->createBody();
-
- // To capture the complete message when using mail(), create
- // an extra header list which createHeader() doesn't fold in
- if ($this->Mailer == 'mail') {
- if (count($this->to) > 0) {
- $this->mailHeader .= $this->addrAppend('To', $this->to);
- } else {
- $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
- }
- $this->mailHeader .= $this->headerLine(
- 'Subject',
- $this->encodeHeader($this->secureHeader(trim($this->Subject)))
- );
- }
-
- // Sign with DKIM if enabled
- if (!empty($this->DKIM_domain)
- && !empty($this->DKIM_private)
- && !empty($this->DKIM_selector)
- && file_exists($this->DKIM_private)) {
- $header_dkim = $this->DKIM_Add(
- $this->MIMEHeader . $this->mailHeader,
- $this->encodeHeader($this->secureHeader($this->Subject)),
- $this->MIMEBody
- );
- $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF .
- str_replace("\r\n", "\n", $header_dkim) . self::CRLF;
- }
- return true;
-
- } catch (phpmailerException $exc) {
- $this->setError($exc->getMessage());
- if ($this->exceptions) {
- throw $exc;
- }
- return false;
- }
- }
-
- /**
- * Actually send a message.
- * Send the email via the selected mechanism
- * @throws phpmailerException
- * @return boolean
- */
- public function postSend()
- {
- try {
- // Choose the mailer and send through it
- switch ($this->Mailer) {
- case 'sendmail':
- case 'qmail':
- return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
- case 'smtp':
- return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
- case 'mail':
- return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
- default:
- $sendMethod = $this->Mailer.'Send';
- if (method_exists($this, $sendMethod)) {
- return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
- }
-
- return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
- }
- } catch (phpmailerException $exc) {
- $this->setError($exc->getMessage());
- $this->edebug($exc->getMessage());
- if ($this->exceptions) {
- throw $exc;
- }
- }
- return false;
- }
-
- /**
- * Send mail using the $Sendmail program.
- * @param string $header The message headers
- * @param string $body The message body
- * @see PHPMailer::$Sendmail
- * @throws phpmailerException
- * @access protected
- * @return boolean
- */
- protected function sendmailSend($header, $body)
- {
- if ($this->Sender != '') {
- if ($this->Mailer == 'qmail') {
- $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
- } else {
- $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
- }
- } else {
- if ($this->Mailer == 'qmail') {
- $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail));
- } else {
- $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail));
- }
- }
- if ($this->SingleTo) {
- foreach ($this->SingleToArray as $toAddr) {
- if (!@$mail = popen($sendmail, 'w')) {
- throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- fputs($mail, 'To: ' . $toAddr . "\n");
- fputs($mail, $header);
- fputs($mail, $body);
- $result = pclose($mail);
- $this->doCallback(
- ($result == 0),
- array($toAddr),
- $this->cc,
- $this->bcc,
- $this->Subject,
- $body,
- $this->From
- );
- if ($result != 0) {
- throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- }
- } else {
- if (!@$mail = popen($sendmail, 'w')) {
- throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- fputs($mail, $header);
- fputs($mail, $body);
- $result = pclose($mail);
- $this->doCallback(($result == 0), $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
- if ($result != 0) {
- throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
- }
- }
- return true;
- }
-
- /**
- * Send mail using the PHP mail() function.
- * @param string $header The message headers
- * @param string $body The message body
- * @link http://www.php.net/manual/en/book.mail.php
- * @throws phpmailerException
- * @access protected
- * @return boolean
- */
- protected function mailSend($header, $body)
- {
- $toArr = array();
- foreach ($this->to as $toaddr) {
- $toArr[] = $this->addrFormat($toaddr);
- }
- $to = implode(', ', $toArr);
-
- if (empty($this->Sender)) {
- $params = ' ';
- } else {
- $params = sprintf('-f%s', $this->Sender);
- }
- if ($this->Sender != '' and !ini_get('safe_mode')) {
- $old_from = ini_get('sendmail_from');
- ini_set('sendmail_from', $this->Sender);
- }
- $result = false;
- if ($this->SingleTo && count($toArr) > 1) {
- foreach ($toArr as $toAddr) {
- $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
- $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
- }
- } else {
- $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
- $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
- }
- if (isset($old_from)) {
- ini_set('sendmail_from', $old_from);
- }
- if (!$result) {
- throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL);
- }
- return true;
- }
-
- /**
- * Get an instance to use for SMTP operations.
- * Override this function to load your own SMTP implementation
- * @return SMTP
- */
- public function getSMTPInstance()
- {
- if (!is_object($this->smtp)) {
- $this->smtp = new SMTP;
- }
- return $this->smtp;
- }
-
- /**
- * Send mail via SMTP.
- * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
- * Uses the PHPMailerSMTP class by default.
- * @see PHPMailer::getSMTPInstance() to use a different class.
- * @param string $header The message headers
- * @param string $body The message body
- * @throws phpmailerException
- * @uses SMTP
- * @access protected
- * @return boolean
- */
- protected function smtpSend($header, $body)
- {
- $bad_rcpt = array();
-
- if (!$this->smtpConnect()) {
- throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
- }
- $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
- if (!$this->smtp->mail($smtp_from)) {
- $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
- throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
- }
-
- // Attempt to send to all recipients
- foreach ($this->to as $to) {
- if (!$this->smtp->recipient($to[0])) {
- $bad_rcpt[] = $to[0];
- $isSent = false;
- } else {
- $isSent = true;
- }
- $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From);
- }
- foreach ($this->cc as $cc) {
- if (!$this->smtp->recipient($cc[0])) {
- $bad_rcpt[] = $cc[0];
- $isSent = false;
- } else {
- $isSent = true;
- }
- $this->doCallback($isSent, array(), array($cc[0]), array(), $this->Subject, $body, $this->From);
- }
- foreach ($this->bcc as $bcc) {
- if (!$this->smtp->recipient($bcc[0])) {
- $bad_rcpt[] = $bcc[0];
- $isSent = false;
- } else {
- $isSent = true;
- }
- $this->doCallback($isSent, array(), array(), array($bcc[0]), $this->Subject, $body, $this->From);
- }
-
- // Only send the DATA command if we have viable recipients
- if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
- throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL);
- }
- if ($this->SMTPKeepAlive) {
- $this->smtp->reset();
- } else {
- $this->smtp->quit();
- $this->smtp->close();
- }
- if (count($bad_rcpt) > 0) { // Create error message for any bad addresses
- throw new phpmailerException(
- $this->lang('recipients_failed') . implode(', ', $bad_rcpt),
- self::STOP_CONTINUE
- );
- }
- return true;
- }
-
- /**
- * Initiate a connection to an SMTP server.
- * Returns false if the operation failed.
- * @param array $options An array of options compatible with stream_context_create()
- * @uses SMTP
- * @access public
- * @throws phpmailerException
- * @return boolean
- */
- public function smtpConnect($options = array())
- {
- if (is_null($this->smtp)) {
- $this->smtp = $this->getSMTPInstance();
- }
-
- // Already connected?
- if ($this->smtp->connected()) {
- return true;
- }
-
- $this->smtp->setTimeout($this->Timeout);
- $this->smtp->setDebugLevel($this->SMTPDebug);
- $this->smtp->setDebugOutput($this->Debugoutput);
- $this->smtp->setVerp($this->do_verp);
- $hosts = explode(';', $this->Host);
- $lastexception = null;
-
- foreach ($hosts as $hostentry) {
- $hostinfo = array();
- if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
- // Not a valid host entry
- continue;
- }
- // $hostinfo[2]: optional ssl or tls prefix
- // $hostinfo[3]: the hostname
- // $hostinfo[4]: optional port number
- // The host string prefix can temporarily override the current setting for SMTPSecure
- // If it's not specified, the default value is used
- $prefix = '';
- $tls = ($this->SMTPSecure == 'tls');
- if ($hostinfo[2] == 'ssl' or ($hostinfo[2] == '' and $this->SMTPSecure == 'ssl')) {
- $prefix = 'ssl://';
- $tls = false; // Can't have SSL and TLS at once
- } elseif ($hostinfo[2] == 'tls') {
- $tls = true;
- // tls doesn't use a prefix
- }
- $host = $hostinfo[3];
- $port = $this->Port;
- $tport = (integer)$hostinfo[4];
- if ($tport > 0 and $tport < 65536) {
- $port = $tport;
- }
- if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
- try {
- if ($this->Helo) {
- $hello = $this->Helo;
- } else {
- $hello = $this->serverHostname();
- }
- $this->smtp->hello($hello);
-
- if ($tls) {
- if (!$this->smtp->startTLS()) {
- throw new phpmailerException($this->lang('connect_host'));
- }
- // We must resend HELO after tls negotiation
- $this->smtp->hello($hello);
- }
- if ($this->SMTPAuth) {
- if (!$this->smtp->authenticate(
- $this->Username,
- $this->Password,
- $this->AuthType,
- $this->Realm,
- $this->Workstation
- )
- ) {
- throw new phpmailerException($this->lang('authenticate'));
- }
- }
- return true;
- } catch (phpmailerException $exc) {
- $lastexception = $exc;
- // We must have connected, but then failed TLS or Auth, so close connection nicely
- $this->smtp->quit();
- }
- }
- }
- // If we get here, all connection attempts have failed, so close connection hard
- $this->smtp->close();
- // As we've caught all exceptions, just report whatever the last one was
- if ($this->exceptions and !is_null($lastexception)) {
- throw $lastexception;
- }
- return false;
- }
-
- /**
- * Close the active SMTP session if one exists.
- * @return void
- */
- public function smtpClose()
- {
- if ($this->smtp !== null) {
- if ($this->smtp->connected()) {
- $this->smtp->quit();
- $this->smtp->close();
- }
- }
- }
-
- /**
- * Set the language for error messages.
- * Returns false if it cannot load the language file.
- * The default language is English.
- * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
- * @param string $lang_path Path to the language file directory, with trailing separator (slash)
- * @return boolean
- * @access public
- */
- public function setLanguage($langcode = 'en', $lang_path = '')
- {
- // Define full set of translatable strings in English
- $PHPMAILER_LANG = array(
- 'authenticate' => 'SMTP Error: Could not authenticate.',
- 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
- 'data_not_accepted' => 'SMTP Error: data not accepted.',
- 'empty_message' => 'Message body empty',
- 'encoding' => 'Unknown encoding: ',
- 'execute' => 'Could not execute: ',
- 'file_access' => 'Could not access file: ',
- 'file_open' => 'File Error: Could not open file: ',
- 'from_failed' => 'The following From address failed: ',
- 'instantiate' => 'Could not instantiate mail function.',
- 'invalid_address' => 'Invalid address',
- 'mailer_not_supported' => ' mailer is not supported.',
- 'provide_address' => 'You must provide at least one recipient email address.',
- 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
- 'signing' => 'Signing Error: ',
- 'smtp_connect_failed' => 'SMTP connect() failed.',
- 'smtp_error' => 'SMTP server error: ',
- 'variable_set' => 'Cannot set or reset variable: '
- );
- if (empty($lang_path)) {
- // Calculate an absolute path so it can work if CWD is not here
- $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
- }
- $foundlang = true;
- $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
- if ($langcode != 'en') { // There is no English translation file
- // Make sure language file path is readable
- if (!is_readable($lang_file)) {
- $foundlang = false;
- } else {
- // Overwrite language-specific strings.
- // This way we'll never have missing translations.
- $foundlang = include $lang_file;
- }
- }
- $this->language = $PHPMAILER_LANG;
- return (boolean)$foundlang; // Returns false if language not found
- }
-
- /**
- * Get the array of strings for the current language.
- * @return array
- */
- public function getTranslations()
- {
- return $this->language;
- }
-
- /**
- * Create recipient headers.
- * @access public
- * @param string $type
- * @param array $addr An array of recipient,
- * where each recipient is a 2-element indexed array with element 0 containing an address
- * and element 1 containing a name, like:
- * array(array('joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User'))
- * @return string
- */
- public function addrAppend($type, $addr)
- {
- $addresses = array();
- foreach ($addr as $address) {
- $addresses[] = $this->addrFormat($address);
- }
- return $type . ': ' . implode(', ', $addresses) . $this->LE;
- }
-
- /**
- * Format an address for use in a message header.
- * @access public
- * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name
- * like array('joe@example.com', 'Joe User')
- * @return string
- */
- public function addrFormat($addr)
- {
- if (empty($addr[1])) { // No name provided
- return $this->secureHeader($addr[0]);
- } else {
- return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
- $addr[0]
- ) . '>';
- }
- }
-
- /**
- * Word-wrap message.
- * For use with mailers that do not automatically perform wrapping
- * and for quoted-printable encoded messages.
- * Original written by philippe.
- * @param string $message The message to wrap
- * @param integer $length The line length to wrap to
- * @param boolean $qp_mode Whether to run in Quoted-Printable mode
- * @access public
- * @return string
- */
- public function wrapText($message, $length, $qp_mode = false)
- {
- $soft_break = ($qp_mode) ? sprintf(' =%s', $this->LE) : $this->LE;
- // If utf-8 encoding is used, we will need to make sure we don't
- // split multibyte characters when we wrap
- $is_utf8 = (strtolower($this->CharSet) == 'utf-8');
- $lelen = strlen($this->LE);
- $crlflen = strlen(self::CRLF);
-
- $message = $this->fixEOL($message);
- if (substr($message, -$lelen) == $this->LE) {
- $message = substr($message, 0, -$lelen);
- }
-
- $line = explode($this->LE, $message); // Magic. We know fixEOL uses $LE
- $message = '';
- for ($i = 0; $i < count($line); $i++) {
- $line_part = explode(' ', $line[$i]);
- $buf = '';
- for ($e = 0; $e < count($line_part); $e++) {
- $word = $line_part[$e];
- if ($qp_mode and (strlen($word) > $length)) {
- $space_left = $length - strlen($buf) - $crlflen;
- if ($e != 0) {
- if ($space_left > 20) {
- $len = $space_left;
- if ($is_utf8) {
- $len = $this->utf8CharBoundary($word, $len);
- } elseif (substr($word, $len - 1, 1) == '=') {
- $len--;
- } elseif (substr($word, $len - 2, 1) == '=') {
- $len -= 2;
- }
- $part = substr($word, 0, $len);
- $word = substr($word, $len);
- $buf .= ' ' . $part;
- $message .= $buf . sprintf('=%s', self::CRLF);
- } else {
- $message .= $buf . $soft_break;
- }
- $buf = '';
- }
- while (strlen($word) > 0) {
- if ($length <= 0) {
- break;
- }
- $len = $length;
- if ($is_utf8) {
- $len = $this->utf8CharBoundary($word, $len);
- } elseif (substr($word, $len - 1, 1) == '=') {
- $len--;
- } elseif (substr($word, $len - 2, 1) == '=') {
- $len -= 2;
- }
- $part = substr($word, 0, $len);
- $word = substr($word, $len);
-
- if (strlen($word) > 0) {
- $message .= $part . sprintf('=%s', self::CRLF);
- } else {
- $buf = $part;
- }
- }
- } else {
- $buf_o = $buf;
- $buf .= ($e == 0) ? $word : (' ' . $word);
-
- if (strlen($buf) > $length and $buf_o != '') {
- $message .= $buf_o . $soft_break;
- $buf = $word;
- }
- }
- }
- $message .= $buf . self::CRLF;
- }
-
- return $message;
- }
-
- /**
- * Find the last character boundary prior to $maxLength in a utf-8
- * quoted (printable) encoded string.
- * Original written by Colin Brown.
- * @access public
- * @param string $encodedText utf-8 QP text
- * @param integer $maxLength find last character boundary prior to this length
- * @return integer
- */
- public function utf8CharBoundary($encodedText, $maxLength)
- {
- $foundSplitPos = false;
- $lookBack = 3;
- while (!$foundSplitPos) {
- $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
- $encodedCharPos = strpos($lastChunk, '=');
- if (false !== $encodedCharPos) {
- // Found start of encoded character byte within $lookBack block.
- // Check the encoded byte value (the 2 chars after the '=')
- $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
- $dec = hexdec($hex);
- if ($dec < 128) { // Single byte character.
- // If the encoded char was found at pos 0, it will fit
- // otherwise reduce maxLength to start of the encoded char
- $maxLength = ($encodedCharPos == 0) ? $maxLength :
- $maxLength - ($lookBack - $encodedCharPos);
- $foundSplitPos = true;
- } elseif ($dec >= 192) { // First byte of a multi byte character
- // Reduce maxLength to split at start of character
- $maxLength = $maxLength - ($lookBack - $encodedCharPos);
- $foundSplitPos = true;
- } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
- $lookBack += 3;
- }
- } else {
- // No encoded character found
- $foundSplitPos = true;
- }
- }
- return $maxLength;
- }
-
- /**
- * Set the body wrapping.
- * @access public
- * @return void
- */
- public function setWordWrap()
- {
- if ($this->WordWrap < 1) {
- return;
- }
-
- switch ($this->message_type) {
- case 'alt':
- case 'alt_inline':
- case 'alt_attach':
- case 'alt_inline_attach':
- $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
- break;
- default:
- $this->Body = $this->wrapText($this->Body, $this->WordWrap);
- break;
- }
- }
-
- /**
- * Assemble message headers.
- * @access public
- * @return string The assembled headers
- */
- public function createHeader()
- {
- $result = '';
-
- // Set the boundaries
- $uniq_id = md5(uniqid(time()));
- $this->boundary[1] = 'b1_' . $uniq_id;
- $this->boundary[2] = 'b2_' . $uniq_id;
- $this->boundary[3] = 'b3_' . $uniq_id;
-
- if ($this->MessageDate == '') {
- $this->MessageDate = self::rfcDate();
- }
- $result .= $this->headerLine('Date', $this->MessageDate);
-
-
- // To be created automatically by mail()
- if ($this->SingleTo) {
- if ($this->Mailer != 'mail') {
- foreach ($this->to as $toaddr) {
- $this->SingleToArray[] = $this->addrFormat($toaddr);
- }
- }
- } else {
- if (count($this->to) > 0) {
- if ($this->Mailer != 'mail') {
- $result .= $this->addrAppend('To', $this->to);
- }
- } elseif (count($this->cc) == 0) {
- $result .= $this->headerLine('To', 'undisclosed-recipients:;');
- }
- }
-
- $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName)));
-
- // sendmail and mail() extract Cc from the header before sending
- if (count($this->cc) > 0) {
- $result .= $this->addrAppend('Cc', $this->cc);
- }
-
- // sendmail and mail() extract Bcc from the header before sending
- if ((
- $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
- )
- and count($this->bcc) > 0
- ) {
- $result .= $this->addrAppend('Bcc', $this->bcc);
- }
-
- if (count($this->ReplyTo) > 0) {
- $result .= $this->addrAppend('Reply-To', $this->ReplyTo);
- }
-
- // mail() sets the subject itself
- if ($this->Mailer != 'mail') {
- $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
- }
-
- if ($this->MessageID != '') {
- $this->lastMessageID = $this->MessageID;
- } else {
- $this->lastMessageID = sprintf('<%s@%s>', $uniq_id, $this->ServerHostname());
- }
- $result .= $this->HeaderLine('Message-ID', $this->lastMessageID);
- $result .= $this->headerLine('X-Priority', $this->Priority);
- if ($this->XMailer == '') {
- $result .= $this->headerLine(
- 'X-Mailer',
- 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer/)'
- );
- } else {
- $myXmailer = trim($this->XMailer);
- if ($myXmailer) {
- $result .= $this->headerLine('X-Mailer', $myXmailer);
- }
- }
-
- if ($this->ConfirmReadingTo != '') {
- $result .= $this->headerLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
- }
-
- // Add custom headers
- for ($index = 0; $index < count($this->CustomHeader); $index++) {
- $result .= $this->headerLine(
- trim($this->CustomHeader[$index][0]),
- $this->encodeHeader(trim($this->CustomHeader[$index][1]))
- );
- }
- if (!$this->sign_key_file) {
- $result .= $this->headerLine('MIME-Version', '1.0');
- $result .= $this->getMailMIME();
- }
-
- return $result;
- }
-
- /**
- * Get the message MIME type headers.
- * @access public
- * @return string
- */
- public function getMailMIME()
- {
- $result = '';
- $ismultipart = true;
- switch ($this->message_type) {
- case 'inline':
- $result .= $this->headerLine('Content-Type', 'multipart/related;');
- $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
- break;
- case 'attach':
- case 'inline_attach':
- case 'alt_attach':
- case 'alt_inline_attach':
- $result .= $this->headerLine('Content-Type', 'multipart/mixed;');
- $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
- break;
- case 'alt':
- case 'alt_inline':
- $result .= $this->headerLine('Content-Type', 'multipart/alternative;');
- $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
- break;
- default:
- // Catches case 'plain': and case '':
- $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
- $ismultipart = false;
- break;
- }
- // RFC1341 part 5 says 7bit is assumed if not specified
- if ($this->Encoding != '7bit') {
- // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
- if ($ismultipart) {
- if ($this->Encoding == '8bit') {
- $result .= $this->headerLine('Content-Transfer-Encoding', '8bit');
- }
- // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
- } else {
- $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
- }
- }
-
- if ($this->Mailer != 'mail') {
- $result .= $this->LE;
- }
-
- return $result;
- }
-
- /**
- * Returns the whole MIME message.
- * Includes complete headers and body.
- * Only valid post preSend().
- * @see PHPMailer::preSend()
- * @access public
- * @return string
- */
- public function getSentMIMEMessage()
- {
- return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
- }
-
-
- /**
- * Assemble the message body.
- * Returns an empty string on failure.
- * @access public
- * @throws phpmailerException
- * @return string The assembled message body
- */
- public function createBody()
- {
- $body = '';
-
- if ($this->sign_key_file) {
- $body .= $this->getMailMIME() . $this->LE;
- }
-
- $this->setWordWrap();
-
- $bodyEncoding = $this->Encoding;
- $bodyCharSet = $this->CharSet;
- if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
- $bodyEncoding = '7bit';
- $bodyCharSet = 'us-ascii';
- }
- $altBodyEncoding = $this->Encoding;
- $altBodyCharSet = $this->CharSet;
- if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
- $altBodyEncoding = '7bit';
- $altBodyCharSet = 'us-ascii';
- }
- switch ($this->message_type) {
- case 'inline':
- $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->attachAll('inline', $this->boundary[1]);
- break;
- case 'attach':
- $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->attachAll('attachment', $this->boundary[1]);
- break;
- case 'inline_attach':
- $body .= $this->textLine('--' . $this->boundary[1]);
- $body .= $this->headerLine('Content-Type', 'multipart/related;');
- $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
- $body .= $this->LE;
- $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->attachAll('inline', $this->boundary[2]);
- $body .= $this->LE;
- $body .= $this->attachAll('attachment', $this->boundary[1]);
- break;
- case 'alt':
- $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
- $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- $body .= $this->LE . $this->LE;
- if (!empty($this->Ical)) {
- $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
- $body .= $this->encodeString($this->Ical, $this->Encoding);
- $body .= $this->LE . $this->LE;
- }
- $body .= $this->endBoundary($this->boundary[1]);
- break;
- case 'alt_inline':
- $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
- $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->textLine('--' . $this->boundary[1]);
- $body .= $this->headerLine('Content-Type', 'multipart/related;');
- $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
- $body .= $this->LE;
- $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->attachAll('inline', $this->boundary[2]);
- $body .= $this->LE;
- $body .= $this->endBoundary($this->boundary[1]);
- break;
- case 'alt_attach':
- $body .= $this->textLine('--' . $this->boundary[1]);
- $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
- $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
- $body .= $this->LE;
- $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
- $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->endBoundary($this->boundary[2]);
- $body .= $this->LE;
- $body .= $this->attachAll('attachment', $this->boundary[1]);
- break;
- case 'alt_inline_attach':
- $body .= $this->textLine('--' . $this->boundary[1]);
- $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
- $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
- $body .= $this->LE;
- $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
- $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->textLine('--' . $this->boundary[2]);
- $body .= $this->headerLine('Content-Type', 'multipart/related;');
- $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
- $body .= $this->LE;
- $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- $body .= $this->LE . $this->LE;
- $body .= $this->attachAll('inline', $this->boundary[3]);
- $body .= $this->LE;
- $body .= $this->endBoundary($this->boundary[2]);
- $body .= $this->LE;
- $body .= $this->attachAll('attachment', $this->boundary[1]);
- break;
- default:
- // catch case 'plain' and case ''
- $body .= $this->encodeString($this->Body, $bodyEncoding);
- break;
- }
-
- if ($this->isError()) {
- $body = '';
- } elseif ($this->sign_key_file) {
- try {
- if (!defined('PKCS7_TEXT')) {
- throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
- }
- // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1
- $file = tempnam(sys_get_temp_dir(), 'mail');
- if (false === file_put_contents($file, $body)) {
- throw new phpmailerException($this->lang('signing') . ' Could not write temp file');
- }
- $signed = tempnam(sys_get_temp_dir(), 'signed');
- if (@openssl_pkcs7_sign(
- $file,
- $signed,
- 'file://' . realpath($this->sign_cert_file),
- array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
- null
- )
- ) {
- @unlink($file);
- $body = file_get_contents($signed);
- @unlink($signed);
- } else {
- @unlink($file);
- @unlink($signed);
- throw new phpmailerException($this->lang('signing') . openssl_error_string());
- }
- } catch (phpmailerException $exc) {
- $body = '';
- if ($this->exceptions) {
- throw $exc;
- }
- }
- }
- return $body;
- }
-
- /**
- * Return the start of a message boundary.
- * @access protected
- * @param string $boundary
- * @param string $charSet
- * @param string $contentType
- * @param string $encoding
- * @return string
- */
- protected function getBoundary($boundary, $charSet, $contentType, $encoding)
- {
- $result = '';
- if ($charSet == '') {
- $charSet = $this->CharSet;
- }
- if ($contentType == '') {
- $contentType = $this->ContentType;
- }
- if ($encoding == '') {
- $encoding = $this->Encoding;
- }
- $result .= $this->textLine('--' . $boundary);
- $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
- $result .= $this->LE;
- // RFC1341 part 5 says 7bit is assumed if not specified
- if ($encoding != '7bit') {
- $result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
- }
- $result .= $this->LE;
-
- return $result;
- }
-
- /**
- * Return the end of a message boundary.
- * @access protected
- * @param string $boundary
- * @return string
- */
- protected function endBoundary($boundary)
- {
- return $this->LE . '--' . $boundary . '--' . $this->LE;
- }
-
- /**
- * Set the message type.
- * PHPMailer only supports some preset message types,
- * not arbitrary MIME structures.
- * @access protected
- * @return void
- */
- protected function setMessageType()
- {
- $type = array();
- if ($this->alternativeExists()) {
- $type[] = 'alt';
- }
- if ($this->inlineImageExists()) {
- $type[] = 'inline';
- }
- if ($this->attachmentExists()) {
- $type[] = 'attach';
- }
- $this->message_type = implode('_', $type);
- if ($this->message_type == '') {
- $this->message_type = 'plain';
- }
- }
-
- /**
- * Format a header line.
- * @access public
- * @param string $name
- * @param string $value
- * @return string
- */
- public function headerLine($name, $value)
- {
- return $name . ': ' . $value . $this->LE;
- }
-
- /**
- * Return a formatted mail line.
- * @access public
- * @param string $value
- * @return string
- */
- public function textLine($value)
- {
- return $value . $this->LE;
- }
-
- /**
- * Add an attachment from a path on the filesystem.
- * Returns false if the file could not be found or read.
- * @param string $path Path to the attachment.
- * @param string $name Overrides the attachment name.
- * @param string $encoding File encoding (see $Encoding).
- * @param string $type File extension (MIME) type.
- * @param string $disposition Disposition to use
- * @throws phpmailerException
- * @return boolean
- */
- public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
- {
- try {
- if (!@is_file($path)) {
- throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
- }
-
- // If a MIME type is not specified, try to work it out from the file name
- if ($type == '') {
- $type = self::filenameToType($path);
- }
-
- $filename = basename($path);
- if ($name == '') {
- $name = $filename;
- }
-
- $this->attachment[] = array(
- 0 => $path,
- 1 => $filename,
- 2 => $name,
- 3 => $encoding,
- 4 => $type,
- 5 => false, // isStringAttachment
- 6 => $disposition,
- 7 => 0
- );
-
- } catch (phpmailerException $exc) {
- $this->setError($exc->getMessage());
- $this->edebug($exc->getMessage());
- if ($this->exceptions) {
- throw $exc;
- }
- return false;
- }
- return true;
- }
-
- /**
- * Return the array of attachments.
- * @return array
- */
- public function getAttachments()
- {
- return $this->attachment;
- }
-
- /**
- * Attach all file, string, and binary attachments to the message.
- * Returns an empty string on failure.
- * @access protected
- * @param string $disposition_type
- * @param string $boundary
- * @return string
- */
- protected function attachAll($disposition_type, $boundary)
- {
- // Return text of body
- $mime = array();
- $cidUniq = array();
- $incl = array();
-
- // Add all attachments
- foreach ($this->attachment as $attachment) {
- // Check if it is a valid disposition_filter
- if ($attachment[6] == $disposition_type) {
- // Check for string attachment
- $string = '';
- $path = '';
- $bString = $attachment[5];
- if ($bString) {
- $string = $attachment[0];
- } else {
- $path = $attachment[0];
- }
-
- $inclhash = md5(serialize($attachment));
- if (in_array($inclhash, $incl)) {
- continue;
- }
- $incl[] = $inclhash;
- $name = $attachment[2];
- $encoding = $attachment[3];
- $type = $attachment[4];
- $disposition = $attachment[6];
- $cid = $attachment[7];
- if ($disposition == 'inline' && isset($cidUniq[$cid])) {
- continue;
- }
- $cidUniq[$cid] = true;
-
- $mime[] = sprintf('--%s%s', $boundary, $this->LE);
- $mime[] = sprintf(
- 'Content-Type: %s; name="%s"%s',
- $type,
- $this->encodeHeader($this->secureHeader($name)),
- $this->LE
- );
- // RFC1341 part 5 says 7bit is assumed if not specified
- if ($encoding != '7bit') {
- $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE);
- }
-
- if ($disposition == 'inline') {
- $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE);
- }
-
- // If a filename contains any of these chars, it should be quoted,
- // but not otherwise: RFC2183 & RFC2045 5.1
- // Fixes a warning in IETF's msglint MIME checker
- // Allow for bypassing the Content-Disposition header totally
- if (!(empty($disposition))) {
- $encoded_name = $this->encodeHeader($this->secureHeader($name));
- if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
- $mime[] = sprintf(
- 'Content-Disposition: %s; filename="%s"%s',
- $disposition,
- $encoded_name,
- $this->LE . $this->LE
- );
- } else {
- $mime[] = sprintf(
- 'Content-Disposition: %s; filename=%s%s',
- $disposition,
- $encoded_name,
- $this->LE . $this->LE
- );
- }
- } else {
- $mime[] = $this->LE;
- }
-
- // Encode as string attachment
- if ($bString) {
- $mime[] = $this->encodeString($string, $encoding);
- if ($this->isError()) {
- return '';
- }
- $mime[] = $this->LE . $this->LE;
- } else {
- $mime[] = $this->encodeFile($path, $encoding);
- if ($this->isError()) {
- return '';
- }
- $mime[] = $this->LE . $this->LE;
- }
- }
- }
-
- $mime[] = sprintf('--%s--%s', $boundary, $this->LE);
-
- return implode('', $mime);
- }
-
- /**
- * Encode a file attachment in requested format.
- * Returns an empty string on failure.
- * @param string $path The full path to the file
- * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
- * @throws phpmailerException
- * @see EncodeFile(encodeFile
- * @access protected
- * @return string
- */
- protected function encodeFile($path, $encoding = 'base64')
- {
- try {
- if (!is_readable($path)) {
- throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
- }
- $magic_quotes = get_magic_quotes_runtime();
- if ($magic_quotes) {
- if (version_compare(PHP_VERSION, '5.3.0', '<')) {
- set_magic_quotes_runtime(false);
- } else {
- //Doesn't exist in PHP 5.4, but we don't need to check because
- //get_magic_quotes_runtime always returns false in 5.4+
- //so it will never get here
- ini_set('magic_quotes_runtime', 0);
- }
- }
- $file_buffer = file_get_contents($path);
- $file_buffer = $this->encodeString($file_buffer, $encoding);
- if ($magic_quotes) {
- if (version_compare(PHP_VERSION, '5.3.0', '<')) {
- set_magic_quotes_runtime($magic_quotes);
- } else {
- ini_set('magic_quotes_runtime', ($magic_quotes?'1':'0'));
- }
- }
- return $file_buffer;
- } catch (Exception $exc) {
- $this->setError($exc->getMessage());
- return '';
- }
- }
-
- /**
- * Encode a string in requested format.
- * Returns an empty string on failure.
- * @param string $str The text to encode
- * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
- * @access public
- * @return string
- */
- public function encodeString($str, $encoding = 'base64')
- {
- $encoded = '';
- switch (strtolower($encoding)) {
- case 'base64':
- $encoded = chunk_split(base64_encode($str), 76, $this->LE);
- break;
- case '7bit':
- case '8bit':
- $encoded = $this->fixEOL($str);
- // Make sure it ends with a line break
- if (substr($encoded, -(strlen($this->LE))) != $this->LE) {
- $encoded .= $this->LE;
- }
- break;
- case 'binary':
- $encoded = $str;
- break;
- case 'quoted-printable':
- $encoded = $this->encodeQP($str);
- break;
- default:
- $this->setError($this->lang('encoding') . $encoding);
- break;
- }
- return $encoded;
- }
-
- /**
- * Encode a header string optimally.
- * Picks shortest of Q, B, quoted-printable or none.
- * @access public
- * @param string $str
- * @param string $position
- * @return string
- */
- public function encodeHeader($str, $position = 'text')
- {
- $matchcount = 0;
- switch (strtolower($position)) {
- case 'phrase':
- if (!preg_match('/[\200-\377]/', $str)) {
- // Can't use addslashes as we don't know the value of magic_quotes_sybase
- $encoded = addcslashes($str, "\0..\37\177\\\"");
- if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
- return ($encoded);
- } else {
- return ("\"$encoded\"");
- }
- }
- $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
- break;
- /** @noinspection PhpMissingBreakStatementInspection */
- case 'comment':
- $matchcount = preg_match_all('/[()"]/', $str, $matches);
- // Intentional fall-through
- case 'text':
- default:
- $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
- break;
- }
-
- if ($matchcount == 0) { // There are no chars that need encoding
- return ($str);
- }
-
- $maxlen = 75 - 7 - strlen($this->CharSet);
- // Try to select the encoding which should produce the shortest output
- if ($matchcount > strlen($str) / 3) {
- // More than a third of the content will need encoding, so B encoding will be most efficient
- $encoding = 'B';
- if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) {
- // Use a custom function which correctly encodes and wraps long
- // multibyte strings without breaking lines within a character
- $encoded = $this->base64EncodeWrapMB($str, "\n");
- } else {
- $encoded = base64_encode($str);
- $maxlen -= $maxlen % 4;
- $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
- }
- } else {
- $encoding = 'Q';
- $encoded = $this->encodeQ($str, $position);
- $encoded = $this->wrapText($encoded, $maxlen, true);
- $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded));
- }
-
- $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
- $encoded = trim(str_replace("\n", $this->LE, $encoded));
-
- return $encoded;
- }
-
- /**
- * Check if a string contains multi-byte characters.
- * @access public
- * @param string $str multi-byte text to wrap encode
- * @return boolean
- */
- public function hasMultiBytes($str)
- {
- if (function_exists('mb_strlen')) {
- return (strlen($str) > mb_strlen($str, $this->CharSet));
- } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
- return false;
- }
- }
-
- /**
- * Does a string contain any 8-bit chars (in any charset)?
- * @param string $text
- * @return boolean
- */
- public function has8bitChars($text)
- {
- return (boolean)preg_match('/[\x80-\xFF]/', $text);
- }
-
- /**
- * Encode and wrap long multibyte strings for mail headers
- * without breaking lines within a character.
- * Adapted from a function by paravoid
- * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283
- * @access public
- * @param string $str multi-byte text to wrap encode
- * @param string $linebreak string to use as linefeed/end-of-line
- * @return string
- */
- public function base64EncodeWrapMB($str, $linebreak = null)
- {
- $start = '=?' . $this->CharSet . '?B?';
- $end = '?=';
- $encoded = '';
- if ($linebreak === null) {
- $linebreak = $this->LE;
- }
-
- $mb_length = mb_strlen($str, $this->CharSet);
- // Each line must have length <= 75, including $start and $end
- $length = 75 - strlen($start) - strlen($end);
- // Average multi-byte ratio
- $ratio = $mb_length / strlen($str);
- // Base64 has a 4:3 ratio
- $avgLength = floor($length * $ratio * .75);
-
- for ($i = 0; $i < $mb_length; $i += $offset) {
- $lookBack = 0;
- do {
- $offset = $avgLength - $lookBack;
- $chunk = mb_substr($str, $i, $offset, $this->CharSet);
- $chunk = base64_encode($chunk);
- $lookBack++;
- } while (strlen($chunk) > $length);
- $encoded .= $chunk . $linebreak;
- }
-
- // Chomp the last linefeed
- $encoded = substr($encoded, 0, -strlen($linebreak));
- return $encoded;
- }
-
- /**
- * Encode a string in quoted-printable format.
- * According to RFC2045 section 6.7.
- * @access public
- * @param string $string The text to encode
- * @param integer $line_max Number of chars allowed on a line before wrapping
- * @return string
- * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment
- */
- public function encodeQP($string, $line_max = 76)
- {
- if (function_exists('quoted_printable_encode')) { // Use native function if it's available (>= PHP5.3)
- return $this->fixEOL(quoted_printable_encode($string));
- }
- // Fall back to a pure PHP implementation
- $string = str_replace(
- array('%20', '%0D%0A.', '%0D%0A', '%'),
- array(' ', "\r\n=2E", "\r\n", '='),
- rawurlencode($string)
- );
- $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
- return $this->fixEOL($string);
- }
-
- /**
- * Backward compatibility wrapper for an old QP encoding function that was removed.
- * @see PHPMailer::encodeQP()
- * @access public
- * @param string $string
- * @param integer $line_max
- * @param boolean $space_conv
- * @return string
- * @deprecated Use encodeQP instead.
- */
- public function encodeQPphp(
- $string,
- $line_max = 76,
- /** @noinspection PhpUnusedParameterInspection */ $space_conv = false
- ) {
- return $this->encodeQP($string, $line_max);
- }
-
- /**
- * Encode a string using Q encoding.
- * @link http://tools.ietf.org/html/rfc2047
- * @param string $str the text to encode
- * @param string $position Where the text is going to be used, see the RFC for what that means
- * @access public
- * @return string
- */
- public function encodeQ($str, $position = 'text')
- {
- // There should not be any EOL in the string
- $pattern = '';
- $encoded = str_replace(array("\r", "\n"), '', $str);
- switch (strtolower($position)) {
- case 'phrase':
- // RFC 2047 section 5.3
- $pattern = '^A-Za-z0-9!*+\/ -';
- break;
- /** @noinspection PhpMissingBreakStatementInspection */
- case 'comment':
- // RFC 2047 section 5.2
- $pattern = '\(\)"';
- // intentional fall-through
- // for this reason we build the $pattern without including delimiters and []
- case 'text':
- default:
- // RFC 2047 section 5.1
- // Replace every high ascii, control, =, ? and _ characters
- $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
- break;
- }
- $matches = array();
- if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
- // If the string contains an '=', make sure it's the first thing we replace
- // so as to avoid double-encoding
- $eqkey = array_search('=', $matches[0]);
- if (false !== $eqkey) {
- unset($matches[0][$eqkey]);
- array_unshift($matches[0], '=');
- }
- foreach (array_unique($matches[0]) as $char) {
- $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
- }
- }
- // Replace every spaces to _ (more readable than =20)
- return str_replace(' ', '_', $encoded);
- }
-
-
- /**
- * Add a string or binary attachment (non-filesystem).
- * This method can be used to attach ascii or binary data,
- * such as a BLOB record from a database.
- * @param string $string String attachment data.
- * @param string $filename Name of the attachment.
- * @param string $encoding File encoding (see $Encoding).
- * @param string $type File extension (MIME) type.
- * @param string $disposition Disposition to use
- * @return void
- */
- public function addStringAttachment(
- $string,
- $filename,
- $encoding = 'base64',
- $type = '',
- $disposition = 'attachment'
- ) {
- // If a MIME type is not specified, try to work it out from the file name
- if ($type == '') {
- $type = self::filenameToType($filename);
- }
- // Append to $attachment array
- $this->attachment[] = array(
- 0 => $string,
- 1 => $filename,
- 2 => basename($filename),
- 3 => $encoding,
- 4 => $type,
- 5 => true, // isStringAttachment
- 6 => $disposition,
- 7 => 0
- );
- }
-
- /**
- * Add an embedded (inline) attachment from a file.
- * This can include images, sounds, and just about any other document type.
- * These differ from 'regular' attachments in that they are intended to be
- * displayed inline with the message, not just attached for download.
- * This is used in HTML messages that embed the images
- * the HTML refers to using the $cid value.
- * @param string $path Path to the attachment.
- * @param string $cid Content ID of the attachment; Use this to reference
- * the content when using an embedded image in HTML.
- * @param string $name Overrides the attachment name.
- * @param string $encoding File encoding (see $Encoding).
- * @param string $type File MIME type.
- * @param string $disposition Disposition to use
- * @return boolean True on successfully adding an attachment
- */
- public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
- {
- if (!@is_file($path)) {
- $this->setError($this->lang('file_access') . $path);
- return false;
- }
-
- // If a MIME type is not specified, try to work it out from the file name
- if ($type == '') {
- $type = self::filenameToType($path);
- }
-
- $filename = basename($path);
- if ($name == '') {
- $name = $filename;
- }
-
- // Append to $attachment array
- $this->attachment[] = array(
- 0 => $path,
- 1 => $filename,
- 2 => $name,
- 3 => $encoding,
- 4 => $type,
- 5 => false, // isStringAttachment
- 6 => $disposition,
- 7 => $cid
- );
- return true;
- }
-
- /**
- * Add an embedded stringified attachment.
- * This can include images, sounds, and just about any other document type.
- * Be sure to set the $type to an image type for images:
- * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'.
- * @param string $string The attachment binary data.
- * @param string $cid Content ID of the attachment; Use this to reference
- * the content when using an embedded image in HTML.
- * @param string $name
- * @param string $encoding File encoding (see $Encoding).
- * @param string $type MIME type.
- * @param string $disposition Disposition to use
- * @return boolean True on successfully adding an attachment
- */
- public function addStringEmbeddedImage(
- $string,
- $cid,
- $name = '',
- $encoding = 'base64',
- $type = '',
- $disposition = 'inline'
- ) {
- // If a MIME type is not specified, try to work it out from the name
- if ($type == '') {
- $type = self::filenameToType($name);
- }
-
- // Append to $attachment array
- $this->attachment[] = array(
- 0 => $string,
- 1 => $name,
- 2 => $name,
- 3 => $encoding,
- 4 => $type,
- 5 => true, // isStringAttachment
- 6 => $disposition,
- 7 => $cid
- );
- return true;
- }
-
- /**
- * Check if an inline attachment is present.
- * @access public
- * @return boolean
- */
- public function inlineImageExists()
- {
- foreach ($this->attachment as $attachment) {
- if ($attachment[6] == 'inline') {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check if an attachment (non-inline) is present.
- * @return boolean
- */
- public function attachmentExists()
- {
- foreach ($this->attachment as $attachment) {
- if ($attachment[6] == 'attachment') {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check if this message has an alternative body set.
- * @return boolean
- */
- public function alternativeExists()
- {
- return !empty($this->AltBody);
- }
-
- /**
- * Clear all To recipients.
- * @return void
- */
- public function clearAddresses()
- {
- foreach ($this->to as $to) {
- unset($this->all_recipients[strtolower($to[0])]);
- }
- $this->to = array();
- }
-
- /**
- * Clear all CC recipients.
- * @return void
- */
- public function clearCCs()
- {
- foreach ($this->cc as $cc) {
- unset($this->all_recipients[strtolower($cc[0])]);
- }
- $this->cc = array();
- }
-
- /**
- * Clear all BCC recipients.
- * @return void
- */
- public function clearBCCs()
- {
- foreach ($this->bcc as $bcc) {
- unset($this->all_recipients[strtolower($bcc[0])]);
- }
- $this->bcc = array();
- }
-
- /**
- * Clear all ReplyTo recipients.
- * @return void
- */
- public function clearReplyTos()
- {
- $this->ReplyTo = array();
- }
-
- /**
- * Clear all recipient types.
- * @return void
- */
- public function clearAllRecipients()
- {
- $this->to = array();
- $this->cc = array();
- $this->bcc = array();
- $this->all_recipients = array();
- }
-
- /**
- * Clear all filesystem, string, and binary attachments.
- * @return void
- */
- public function clearAttachments()
- {
- $this->attachment = array();
- }
-
- /**
- * Clear all custom headers.
- * @return void
- */
- public function clearCustomHeaders()
- {
- $this->CustomHeader = array();
- }
-
- /**
- * Add an error message to the error container.
- * @access protected
- * @param string $msg
- * @return void
- */
- protected function setError($msg)
- {
- $this->error_count++;
- if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
- $lasterror = $this->smtp->getError();
- if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
- $msg .= '
- * // Use default conversion
- * $plain = $mail->html2text($html);
- * // Use your own custom converter
- * $plain = $mail->html2text($html, function($html) {
- * $converter = new MyHtml2text($html);
- * return $converter->get_text();
- * });
- *
- * @param string $html The HTML text to convert
- * @param boolean|callable $advanced Any boolean value to use the internal converter,
- * or provide your own callable for custom conversion.
- * @return string
- */
- public function html2text($html, $advanced = false)
- {
- if (is_callable($advanced)) {
- return call_user_func($advanced, $html);
- }
- return html_entity_decode(
- trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
- ENT_QUOTES,
- $this->CharSet
- );
- }
-
- /**
- * Get the MIME type for a file extension.
- * @param string $ext File extension
- * @access public
- * @return string MIME type of file.
- * @static
- */
- public static function _mime_types($ext = '')
- {
- $mimes = array(
- 'xl' => 'application/excel',
- 'js' => 'application/javascript',
- 'hqx' => 'application/mac-binhex40',
- 'cpt' => 'application/mac-compactpro',
- 'bin' => 'application/macbinary',
- 'doc' => 'application/msword',
- 'word' => 'application/msword',
- 'class' => 'application/octet-stream',
- 'dll' => 'application/octet-stream',
- 'dms' => 'application/octet-stream',
- 'exe' => 'application/octet-stream',
- 'lha' => 'application/octet-stream',
- 'lzh' => 'application/octet-stream',
- 'psd' => 'application/octet-stream',
- 'sea' => 'application/octet-stream',
- 'so' => 'application/octet-stream',
- 'oda' => 'application/oda',
- 'pdf' => 'application/pdf',
- 'ai' => 'application/postscript',
- 'eps' => 'application/postscript',
- 'ps' => 'application/postscript',
- 'smi' => 'application/smil',
- 'smil' => 'application/smil',
- 'mif' => 'application/vnd.mif',
- 'xls' => 'application/vnd.ms-excel',
- 'ppt' => 'application/vnd.ms-powerpoint',
- 'wbxml' => 'application/vnd.wap.wbxml',
- 'wmlc' => 'application/vnd.wap.wmlc',
- 'dcr' => 'application/x-director',
- 'dir' => 'application/x-director',
- 'dxr' => 'application/x-director',
- 'dvi' => 'application/x-dvi',
- 'gtar' => 'application/x-gtar',
- 'php3' => 'application/x-httpd-php',
- 'php4' => 'application/x-httpd-php',
- 'php' => 'application/x-httpd-php',
- 'phtml' => 'application/x-httpd-php',
- 'phps' => 'application/x-httpd-php-source',
- 'swf' => 'application/x-shockwave-flash',
- 'sit' => 'application/x-stuffit',
- 'tar' => 'application/x-tar',
- 'tgz' => 'application/x-tar',
- 'xht' => 'application/xhtml+xml',
- 'xhtml' => 'application/xhtml+xml',
- 'zip' => 'application/zip',
- 'mid' => 'audio/midi',
- 'midi' => 'audio/midi',
- 'mp2' => 'audio/mpeg',
- 'mp3' => 'audio/mpeg',
- 'mpga' => 'audio/mpeg',
- 'aif' => 'audio/x-aiff',
- 'aifc' => 'audio/x-aiff',
- 'aiff' => 'audio/x-aiff',
- 'ram' => 'audio/x-pn-realaudio',
- 'rm' => 'audio/x-pn-realaudio',
- 'rpm' => 'audio/x-pn-realaudio-plugin',
- 'ra' => 'audio/x-realaudio',
- 'wav' => 'audio/x-wav',
- 'bmp' => 'image/bmp',
- 'gif' => 'image/gif',
- 'jpeg' => 'image/jpeg',
- 'jpe' => 'image/jpeg',
- 'jpg' => 'image/jpeg',
- 'png' => 'image/png',
- 'tiff' => 'image/tiff',
- 'tif' => 'image/tiff',
- 'eml' => 'message/rfc822',
- 'css' => 'text/css',
- 'html' => 'text/html',
- 'htm' => 'text/html',
- 'shtml' => 'text/html',
- 'log' => 'text/plain',
- 'text' => 'text/plain',
- 'txt' => 'text/plain',
- 'rtx' => 'text/richtext',
- 'rtf' => 'text/rtf',
- 'vcf' => 'text/vcard',
- 'vcard' => 'text/vcard',
- 'xml' => 'text/xml',
- 'xsl' => 'text/xml',
- 'mpeg' => 'video/mpeg',
- 'mpe' => 'video/mpeg',
- 'mpg' => 'video/mpeg',
- 'mov' => 'video/quicktime',
- 'qt' => 'video/quicktime',
- 'rv' => 'video/vnd.rn-realvideo',
- 'avi' => 'video/x-msvideo',
- 'movie' => 'video/x-sgi-movie'
- );
- return (array_key_exists(strtolower($ext), $mimes) ? $mimes[strtolower($ext)]: 'application/octet-stream');
- }
-
- /**
- * Map a file name to a MIME type.
- * Defaults to 'application/octet-stream', i.e.. arbitrary binary data.
- * @param string $filename A file name or full path, does not need to exist as a file
- * @return string
- * @static
- */
- public static function filenameToType($filename)
- {
- // In case the path is a URL, strip any query string before getting extension
- $qpos = strpos($filename, '?');
- if (false !== $qpos) {
- $filename = substr($filename, 0, $qpos);
- }
- $pathinfo = self::mb_pathinfo($filename);
- return self::_mime_types($pathinfo['extension']);
- }
-
- /**
- * Multi-byte-safe pathinfo replacement.
- * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.
- * Works similarly to the one in PHP >= 5.2.0
- * @link http://www.php.net/manual/en/function.pathinfo.php#107461
- * @param string $path A filename or path, does not need to exist as a file
- * @param integer|string $options Either a PATHINFO_* constant,
- * or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2
- * @return string|array
- * @static
- */
- public static function mb_pathinfo($path, $options = null)
- {
- $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
- $pathinfo = array();
- if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
- if (array_key_exists(1, $pathinfo)) {
- $ret['dirname'] = $pathinfo[1];
- }
- if (array_key_exists(2, $pathinfo)) {
- $ret['basename'] = $pathinfo[2];
- }
- if (array_key_exists(5, $pathinfo)) {
- $ret['extension'] = $pathinfo[5];
- }
- if (array_key_exists(3, $pathinfo)) {
- $ret['filename'] = $pathinfo[3];
- }
- }
- switch ($options) {
- case PATHINFO_DIRNAME:
- case 'dirname':
- return $ret['dirname'];
- case PATHINFO_BASENAME:
- case 'basename':
- return $ret['basename'];
- case PATHINFO_EXTENSION:
- case 'extension':
- return $ret['extension'];
- case PATHINFO_FILENAME:
- case 'filename':
- return $ret['filename'];
- default:
- return $ret;
- }
- }
-
- /**
- * Set or reset instance properties.
- *
- * Usage Example:
- * $page->set('X-Priority', '3');
- *
- * @access public
- * @param string $name
- * @param mixed $value
- * NOTE: will not work with arrays, there are no arrays to set/reset
- * @throws phpmailerException
- * @return boolean
- * @TODO Should this not be using __set() magic function?
- */
- public function set($name, $value = '')
- {
- try {
- if (isset($this->$name)) {
- $this->$name = $value;
- } else {
- throw new phpmailerException($this->lang('variable_set') . $name, self::STOP_CRITICAL);
- }
- } catch (Exception $exc) {
- $this->setError($exc->getMessage());
- if ($exc->getCode() == self::STOP_CRITICAL) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Strip newlines to prevent header injection.
- * @access public
- * @param string $str
- * @return string
- */
- public function secureHeader($str)
- {
- return trim(str_replace(array("\r", "\n"), '', $str));
- }
-
- /**
- * Normalize line breaks in a string.
- * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format.
- * Defaults to CRLF (for message bodies) and preserves consecutive breaks.
- * @param string $text
- * @param string $breaktype What kind of line break to use, defaults to CRLF
- * @return string
- * @access public
- * @static
- */
- public static function normalizeBreaks($text, $breaktype = "\r\n")
- {
- return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
- }
-
-
- /**
- * Set the public and private key files and password for S/MIME signing.
- * @access public
- * @param string $cert_filename
- * @param string $key_filename
- * @param string $key_pass Password for private key
- */
- public function sign($cert_filename, $key_filename, $key_pass)
- {
- $this->sign_cert_file = $cert_filename;
- $this->sign_key_file = $key_filename;
- $this->sign_key_pass = $key_pass;
- }
-
- /**
- * Quoted-Printable-encode a DKIM header.
- * @access public
- * @param string $txt
- * @return string
- */
- public function DKIM_QP($txt)
- {
- $line = '';
- for ($i = 0; $i < strlen($txt); $i++) {
- $ord = ord($txt[$i]);
- if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
- $line .= $txt[$i];
- } else {
- $line .= '=' . sprintf('%02X', $ord);
- }
- }
- return $line;
- }
-
- /**
- * Generate a DKIM signature.
- * @access public
- * @param string $signHeader
- * @throws phpmailerException
- * @return string
- */
- public function DKIM_Sign($signHeader)
- {
- if (!defined('PKCS7_TEXT')) {
- if ($this->exceptions) {
- throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
- }
- return '';
- }
- $privKeyStr = file_get_contents($this->DKIM_private);
- if ($this->DKIM_passphrase != '') {
- $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
- } else {
- $privKey = $privKeyStr;
- }
- if (openssl_sign($signHeader, $signature, $privKey)) {
- return base64_encode($signature);
- }
- return '';
- }
-
- /**
- * Generate a DKIM canonicalization header.
- * @access public
- * @param string $signHeader Header
- * @return string
- */
- public function DKIM_HeaderC($signHeader)
- {
- $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader);
- $lines = explode("\r\n", $signHeader);
- foreach ($lines as $key => $line) {
- list($heading, $value) = explode(':', $line, 2);
- $heading = strtolower($heading);
- $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces
- $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
- }
- $signHeader = implode("\r\n", $lines);
- return $signHeader;
- }
-
- /**
- * Generate a DKIM canonicalization body.
- * @access public
- * @param string $body Message Body
- * @return string
- */
- public function DKIM_BodyC($body)
- {
- if ($body == '') {
- return "\r\n";
- }
- // stabilize line endings
- $body = str_replace("\r\n", "\n", $body);
- $body = str_replace("\n", "\r\n", $body);
- // END stabilize line endings
- while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
- $body = substr($body, 0, strlen($body) - 2);
- }
- return $body;
- }
-
- /**
- * Create the DKIM header and body in a new message header.
- * @access public
- * @param string $headers_line Header lines
- * @param string $subject Subject
- * @param string $body Body
- * @return string
- */
- public function DKIM_Add($headers_line, $subject, $body)
- {
- $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
- $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
- $DKIMquery = 'dns/txt'; // Query method
- $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
- $subject_header = "Subject: $subject";
- $headers = explode($this->LE, $headers_line);
- $from_header = '';
- $to_header = '';
- $current = '';
- foreach ($headers as $header) {
- if (strpos($header, 'From:') === 0) {
- $from_header = $header;
- $current = 'from_header';
- } elseif (strpos($header, 'To:') === 0) {
- $to_header = $header;
- $current = 'to_header';
- } else {
- if ($current && strpos($header, ' =?') === 0) {
- $current .= $header;
- } else {
- $current = '';
- }
- }
- }
- $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
- $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
- $subject = str_replace(
- '|',
- '=7C',
- $this->DKIM_QP($subject_header)
- ); // Copied header fields (dkim-quoted-printable)
- $body = $this->DKIM_BodyC($body);
- $DKIMlen = strlen($body); // Length of body
- $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body
- $ident = ($this->DKIM_identity == '') ? '' : ' i=' . $this->DKIM_identity . ';';
- $dkimhdrs = 'DKIM-Signature: v=1; a=' .
- $DKIMsignatureType . '; q=' .
- $DKIMquery . '; l=' .
- $DKIMlen . '; s=' .
- $this->DKIM_selector .
- ";\r\n" .
- "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
- "\th=From:To:Subject;\r\n" .
- "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
- "\tz=$from\r\n" .
- "\t|$to\r\n" .
- "\t|$subject;\r\n" .
- "\tbh=" . $DKIMb64 . ";\r\n" .
- "\tb=";
- $toSign = $this->DKIM_HeaderC(
- $from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs
- );
- $signed = $this->DKIM_Sign($toSign);
- return $dkimhdrs . $signed . "\r\n";
- }
-
- /**
- * Allows for public read access to 'to' property.
- * @access public
- * @return array
- */
- public function getToAddresses()
- {
- return $this->to;
- }
-
- /**
- * Allows for public read access to 'cc' property.
- * @access public
- * @return array
- */
- public function getCcAddresses()
- {
- return $this->cc;
- }
-
- /**
- * Allows for public read access to 'bcc' property.
- * @access public
- * @return array
- */
- public function getBccAddresses()
- {
- return $this->bcc;
- }
-
- /**
- * Allows for public read access to 'ReplyTo' property.
- * @access public
- * @return array
- */
- public function getReplyToAddresses()
- {
- return $this->ReplyTo;
- }
-
- /**
- * Allows for public read access to 'all_recipients' property.
- * @access public
- * @return array
- */
- public function getAllRecipientAddresses()
- {
- return $this->all_recipients;
- }
-
- /**
- * Perform a callback.
- * @param boolean $isSent
- * @param array $to
- * @param array $cc
- * @param array $bcc
- * @param string $subject
- * @param string $body
- * @param string $from
- */
- protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
- {
- if (!empty($this->action_function) && is_callable($this->action_function)) {
- $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
- call_user_func_array($this->action_function, $params);
- }
- }
-}
-
-/**
- * PHPMailer exception handler
- * @package PHPMailer
- */
-class phpmailerException extends Exception
-{
- /**
- * Prettify error message output
- * @return string
- */
- public function errorMessage()
- {
- $errorMsg = '' . $this->getMessage() . "
\n";
- return $errorMsg;
- }
-}
diff --git a/download/phpmailer529/class.pop3.php b/download/phpmailer529/class.pop3.php
deleted file mode 100755
index 984885ff0..000000000
--- a/download/phpmailer529/class.pop3.php
+++ /dev/null
@@ -1,397 +0,0 @@
-
- * @author Jim Jagielski (jimjag) ';
- foreach ($this->errors as $error) {
- print_r($error);
- }
- echo '';
- }
- }
-
- /**
- * POP3 connection error handler.
- * @param integer $errno
- * @param string $errstr
- * @param string $errfile
- * @param integer $errline
- * @access private
- */
- private function catchWarning($errno, $errstr, $errfile, $errline)
- {
- $this->setError(array(
- 'error' => "Connecting to the POP3 server raised a PHP warning: ",
- 'errno' => $errno,
- 'errstr' => $errstr,
- 'errfile' => $errfile,
- 'errline' => $errline
- ));
- }
-}
diff --git a/download/phpmailer529/class.smtp.php b/download/phpmailer529/class.smtp.php
deleted file mode 100755
index d6991970f..000000000
--- a/download/phpmailer529/class.smtp.php
+++ /dev/null
@@ -1,1132 +0,0 @@
-
- * @author Jim Jagielski (jimjag)
`, appropriate for browser output
- * * `error_log` Output to error log as configured in php.ini
- *
- * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
- *
- * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
- *
- * @type string|callable
- */
- public $Debugoutput = 'echo';
-
- /**
- * Whether to use VERP.
- * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
- * @link http://www.postfix.org/VERP_README.html Info on VERP
- * @type boolean
- */
- public $do_verp = false;
-
- /**
- * The timeout value for connection, in seconds.
- * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
- * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
- * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2
- * @type integer
- */
- public $Timeout = 300;
-
- /**
- * How long to wait for commands to complete, in seconds.
- * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
- * @type integer
- */
- public $Timelimit = 300;
-
- /**
- * The socket for the server connection.
- * @type resource
- */
- protected $smtp_conn;
-
- /**
- * Error message, if any, for the last call.
- * @type array
- */
- protected $error = array();
-
- /**
- * The reply the server sent to us for HELO.
- * If null, no HELO string has yet been received.
- * @type string|null
- */
- protected $helo_rply = null;
-
- /**
- * The set of SMTP extensions sent in reply to EHLO command.
- * Indexes of the array are extension names.
- * Value at index 'HELO' or 'EHLO' (according to command that was sent)
- * represents the server name. In case of HELO it is the only element of the array.
- * Other values can be boolean TRUE or an array containing extension options.
- * If null, no HELO/EHLO string has yet been received.
- * @type array|null
- */
- protected $server_caps = null;
-
- /**
- * The most recent reply received from the server.
- * @type string
- */
- protected $last_reply = '';
-
- /**
- * Output debugging info via a user-selected method.
- * @see SMTP::$Debugoutput
- * @see SMTP::$do_debug
- * @param string $str Debug string to output
- * @param integer $level The debug level of this message; see DEBUG_* constants
- * @return void
- */
- protected function edebug($str, $level = 0)
- {
- if ($level > $this->do_debug) {
- return;
- }
- //Avoid clash with built-in function names
- if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
- call_user_func($this->Debugoutput, $str, $this->do_debug);
- return;
- }
- switch ($this->Debugoutput) {
- case 'error_log':
- //Don't output, just log
- error_log($str);
- break;
- case 'html':
- //Cleans up output a bit for a better looking, HTML-safe output
- echo htmlentities(
- preg_replace('/[\r\n]+/', '', $str),
- ENT_QUOTES,
- 'UTF-8'
- )
- . "
\n";
- break;
- case 'echo':
- default:
- //Normalize line breaks
- $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
- echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
- "\n",
- "\n \t ",
- trim($str)
- )."\n";
- }
- }
-
- /**
- * Connect to an SMTP server.
- * @param string $host SMTP server IP or host name
- * @param integer $port The port number to connect to
- * @param integer $timeout How long to wait for the connection to open
- * @param array $options An array of options for stream_context_create()
- * @access public
- * @return boolean
- */
- public function connect($host, $port = null, $timeout = 30, $options = array())
- {
- static $streamok;
- //This is enabled by default since 5.0.0 but some providers disable it
- //Check this once and cache the result
- if (is_null($streamok)) {
- $streamok = function_exists('stream_socket_client');
- }
- // Clear errors to avoid confusion
- $this->error = array();
- // Make sure we are __not__ connected
- if ($this->connected()) {
- // Already connected, generate error
- $this->error = array('error' => 'Already connected to a server');
- return false;
- }
- if (empty($port)) {
- $port = self::DEFAULT_SMTP_PORT;
- }
- // Connect to the SMTP server
- $this->edebug(
- "Connection: opening to $host:$port, t=$timeout, opt=".var_export($options, true),
- self::DEBUG_CONNECTION
- );
- $errno = 0;
- $errstr = '';
- if ($streamok) {
- $socket_context = stream_context_create($options);
- //Suppress errors; connection failures are handled at a higher level
- $this->smtp_conn = @stream_socket_client(
- $host . ":" . $port,
- $errno,
- $errstr,
- $timeout,
- STREAM_CLIENT_CONNECT,
- $socket_context
- );
- } else {
- //Fall back to fsockopen which should work in more places, but is missing some features
- $this->edebug(
- "Connection: stream_socket_client not available, falling back to fsockopen",
- self::DEBUG_CONNECTION
- );
- $this->smtp_conn = fsockopen(
- $host,
- $port,
- $errno,
- $errstr,
- $timeout
- );
- }
- // Verify we connected properly
- if (!is_resource($this->smtp_conn)) {
- $this->error = array(
- 'error' => 'Failed to connect to server',
- 'errno' => $errno,
- 'errstr' => $errstr
- );
- $this->edebug(
- 'SMTP ERROR: ' . $this->error['error']
- . ": $errstr ($errno)",
- self::DEBUG_CLIENT
- );
- return false;
- }
- $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
- // SMTP server can take longer to respond, give longer timeout for first read
- // Windows does not have support for this timeout function
- if (substr(PHP_OS, 0, 3) != 'WIN') {
- $max = ini_get('max_execution_time');
- if ($max != 0 && $timeout > $max) { // Don't bother if unlimited
- @set_time_limit($timeout);
- }
- stream_set_timeout($this->smtp_conn, $timeout, 0);
- }
- // Get any announcement
- $announce = $this->get_lines();
- $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
- return true;
- }
-
- /**
- * Initiate a TLS (encrypted) session.
- * @access public
- * @return boolean
- */
- public function startTLS()
- {
- if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
- return false;
- }
- // Begin encrypted connection
- if (!stream_socket_enable_crypto(
- $this->smtp_conn,
- true,
- STREAM_CRYPTO_METHOD_TLS_CLIENT
- )) {
- return false;
- }
- return true;
- }
-
- /**
- * Perform SMTP authentication.
- * Must be run after hello().
- * @see hello()
- * @param string $username The user name
- * @param string $password The password
- * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5)
- * @param string $realm The auth realm for NTLM
- * @param string $workstation The auth workstation for NTLM
- * @access public
- * @return boolean True if successfully authenticated.
- */
- public function authenticate(
- $username,
- $password,
- $authtype = null,
- $realm = '',
- $workstation = ''
- ) {
- if (!$this->server_caps) {
- $this->error = array('error' => 'Authentication is not allowed before HELO/EHLO');
- return false;
- }
-
- if (array_key_exists('EHLO', $this->server_caps)) {
- // SMTP extensions are available. Let's try to find a proper authentication method
-
- if (!array_key_exists('AUTH', $this->server_caps)) {
- $this->error = array( 'error' => 'Authentication is not allowed at this stage' );
- // 'at this stage' means that auth may be allowed after the stage changes
- // e.g. after STARTTLS
- return false;
- }
-
- self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL);
- self::edebug(
- 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']),
- self::DEBUG_LOWLEVEL
- );
-
- if (empty($authtype)) {
- foreach (array('LOGIN', 'CRAM-MD5', 'NTLM', 'PLAIN') as $method) {
- if (in_array($method, $this->server_caps['AUTH'])) {
- $authtype = $method;
- break;
- }
- }
- if (empty($authtype)) {
- $this->error = array( 'error' => 'No supported authentication methods found' );
- return false;
- }
- self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL);
- }
-
- if (!in_array($authtype, $this->server_caps['AUTH'])) {
- $this->error = array( 'error' => 'The requested authentication method "'
- . $authtype . '" is not supported by the server' );
- return false;
- }
- } elseif (empty($authtype)) {
- $authtype = 'LOGIN';
- }
- switch ($authtype) {
- case 'PLAIN':
- // Start authentication
- if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
- return false;
- }
- // Send encoded username and password
- if (!$this->sendCommand(
- 'User & Password',
- base64_encode("\0" . $username . "\0" . $password),
- 235
- )
- ) {
- return false;
- }
- break;
- case 'LOGIN':
- // Start authentication
- if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
- return false;
- }
- if (!$this->sendCommand("Username", base64_encode($username), 334)) {
- return false;
- }
- if (!$this->sendCommand("Password", base64_encode($password), 235)) {
- return false;
- }
- break;
- case 'NTLM':
- /*
- * ntlm_sasl_client.php
- * Bundled with Permission
- *
- * How to telnet in windows:
- * http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
- * PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
- */
- require_once 'extras/ntlm_sasl_client.php';
- $temp = new stdClass();
- $ntlm_client = new ntlm_sasl_client_class;
- //Check that functions are available
- if (!$ntlm_client->Initialize($temp)) {
- $this->error = array('error' => $temp->error);
- $this->edebug(
- 'You need to enable some modules in your php.ini file: '
- . $this->error['error'],
- self::DEBUG_CLIENT
- );
- return false;
- }
- //msg1
- $msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1
-
- if (!$this->sendCommand(
- 'AUTH NTLM',
- 'AUTH NTLM ' . base64_encode($msg1),
- 334
- )
- ) {
- return false;
- }
- //Though 0 based, there is a white space after the 3 digit number
- //msg2
- $challenge = substr($this->last_reply, 3);
- $challenge = base64_decode($challenge);
- $ntlm_res = $ntlm_client->NTLMResponse(
- substr($challenge, 24, 8),
- $password
- );
- //msg3
- $msg3 = $ntlm_client->TypeMsg3(
- $ntlm_res,
- $username,
- $realm,
- $workstation
- );
- // send encoded username
- return $this->sendCommand('Username', base64_encode($msg3), 235);
- case 'CRAM-MD5':
- // Start authentication
- if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
- return false;
- }
- // Get the challenge
- $challenge = base64_decode(substr($this->last_reply, 4));
-
- // Build the response
- $response = $username . ' ' . $this->hmac($challenge, $password);
-
- // send encoded credentials
- return $this->sendCommand('Username', base64_encode($response), 235);
- default:
- $this->error = array( 'error' => 'Authentication method "' . $authtype . '" is not supported' );
- return false;
- }
- return true;
- }
-
- /**
- * Calculate an MD5 HMAC hash.
- * Works like hash_hmac('md5', $data, $key)
- * in case that function is not available
- * @param string $data The data to hash
- * @param string $key The key to hash with
- * @access protected
- * @return string
- */
- protected function hmac($data, $key)
- {
- if (function_exists('hash_hmac')) {
- return hash_hmac('md5', $data, $key);
- }
-
- // The following borrowed from
- // http://php.net/manual/en/function.mhash.php#27225
-
- // RFC 2104 HMAC implementation for php.
- // Creates an md5 HMAC.
- // Eliminates the need to install mhash to compute a HMAC
- // by Lance Rushing
-
- $bytelen = 64; // byte length for md5
- if (strlen($key) > $bytelen) {
- $key = pack('H*', md5($key));
- }
- $key = str_pad($key, $bytelen, chr(0x00));
- $ipad = str_pad('', $bytelen, chr(0x36));
- $opad = str_pad('', $bytelen, chr(0x5c));
- $k_ipad = $key ^ $ipad;
- $k_opad = $key ^ $opad;
-
- return md5($k_opad . pack('H*', md5($k_ipad . $data)));
- }
-
- /**
- * Check connection state.
- * @access public
- * @return boolean True if connected.
- */
- public function connected()
- {
- if (is_resource($this->smtp_conn)) {
- $sock_status = stream_get_meta_data($this->smtp_conn);
- if ($sock_status['eof']) {
- // The socket is valid but we are not connected
- $this->edebug(
- 'SMTP NOTICE: EOF caught while checking if connected',
- self::DEBUG_CLIENT
- );
- $this->close();
- return false;
- }
- return true; // everything looks good
- }
- return false;
- }
-
- /**
- * Close the socket and clean up the state of the class.
- * Don't use this function without first trying to use QUIT.
- * @see quit()
- * @access public
- * @return void
- */
- public function close()
- {
- $this->error = array();
- $this->server_caps = null;
- $this->helo_rply = null;
- if (is_resource($this->smtp_conn)) {
- // close the connection and cleanup
- fclose($this->smtp_conn);
- $this->smtp_conn = null; //Makes for cleaner serialization
- $this->edebug('Connection: closed', self::DEBUG_CONNECTION);
- }
- }
-
- /**
- * Send an SMTP DATA command.
- * Issues a data command and sends the msg_data to the server,
- * finializing the mail transaction. $msg_data is the message
- * that is to be send with the headers. Each header needs to be
- * on a single line followed by a Examples using PHPMailer
-
-1. Advanced Example
-
-require 'PHPMailerAutoload.php';
-
-$mail = new PHPMailer();
-
-$mail->From = 'list@example.com';
-$mail->FromName = 'List manager';
-$mail->Host = 'smtp1.example.com;smtp2.example.com';
-$mail->Mailer = 'smtp';
-
-@mysqli_connect('localhost','root','password');
-@mysqli_select_db("my_company");
-$query = "SELECT full_name, email, photo FROM employee";
-$result = @mysqli_query($query);
-
-while ($row = mysqli_fetch_assoc($result))
-{
- // HTML body
- $body = "Hello <font size=\"4\">" . $row['full_name'] . "</font>, <p>";
- $body .= "<i>Your</i> personal photograph to this message.<p>";
- $body .= "Sincerely, <br>";
- $body .= "phpmailer List manager";
-
- // Plain text body (for mail clients that cannot read HTML)
- $text_body = 'Hello ' . $row['full_name'] . ", \n\n";
- $text_body .= "Your personal photograph to this message.\n\n";
- $text_body .= "Sincerely, \n";
- $text_body .= 'phpmailer List manager';
-
- $mail->Body = $body;
- $mail->AltBody = $text_body;
- $mail->addAddress($row['email'], $row['full_name']);
- $mail->addStringAttachment($row['photo'], 'YourPhoto.jpg');
-
- if(!$mail->send())
- echo "There has been a mail error sending to " . $row['email'] . "<br>";
-
- // Clear all addresses and attachments for next loop
- $mail->clearAddresses();
- $mail->clearAttachments();
-}
-
-2. Extending PHPMailer
-
-PHP include file: my_phpmailer.php
-
-require 'PHPMailerAutoload.php';
-
-class my_phpmailer extends PHPMailer {
- // Set default variables for all new objects
- public $From = 'from@example.com';
- public $FromName = 'Mailer';
- public $Host = 'smtp1.example.com;smtp2.example.com';
- public $Mailer = 'smtp'; // Alternative to isSMTP()
- public $WordWrap = 75;
-
- // Replace the default debug output function
- protected function edebug($msg) {
- print('My Site Error');
- print('Description:');
- printf('%s', $msg);
- exit;
- }
-
- //Extend the send function
- public function send() {
- $this->Subject = '[Yay for me!] '.$this->Subject;
- return parent::send()
- }
-
- // Create an additional function
- public function do_something($something) {
- // Place your new code here
- }
-}
-
-
-Now here's a normal PHP page in the site, which will have all the defaults set above:
-
-
-require 'my_phpmailer.php';
-
-// Instantiate your new class
-$mail = new my_phpmailer;
-
-// Now you only need to add the necessary stuff
-$mail->addAddress('josh@example.com', 'Josh Adams');
-$mail->Subject = 'Here is the subject';
-$mail->Body = 'This is the message body';
-$mail->addAttachment('c:/temp/11-10-00.zip', 'new_name.zip'); // optional name
-
-if(!$mail->send())
-{
- echo 'There was an error sending the message';
- exit;
-}
-
-echo 'Message was sent successfully';
-
-
-
diff --git a/download/phpmailer529/docs/faq.html b/download/phpmailer529/docs/faq.html
deleted file mode 100755
index 7033a142e..000000000
--- a/download/phpmailer529/docs/faq.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-PHPMailer FAQ
-
-
-
-
diff --git a/download/phpmailer529/docs/generatedocs.sh b/download/phpmailer529/docs/generatedocs.sh
deleted file mode 100755
index 9da1ddfe7..000000000
--- a/download/phpmailer529/docs/generatedocs.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-# Regenerate PHPMailer documentation
-# Run from within the docs folder
-rm -rf phpdoc/*
-phpdoc --directory .. --target ./phpdoc --ignore test/,examples/,extras/,test_script/,vendor/,language/ --sourcecode --force --title PHPMailer --template="clean"
-# You can merge regenerated docs into a separate docs working copy without messing up the git status like so:
-# rsync -a --delete --exclude ".git" --exclude "phpdoc-cache-*/" --exclude "README.md" phpdoc/ ../../phpmailer-docs
-# After updating docs, push/PR them to the phpmailer gh-pages branch: https://github.com/PHPMailer/PHPMailer/tree/gh-pages
diff --git a/download/phpmailer529/docs/pop3_article.txt b/download/phpmailer529/docs/pop3_article.txt
deleted file mode 100755
index fb90b9c76..000000000
--- a/download/phpmailer529/docs/pop3_article.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-This is built for PHP Mailer 1.72 and was not tested with any previous version. It was developed under PHP 4.3.11 (E_ALL). It works under PHP 5 and 5.1 with E_ALL, but not in Strict mode due to var deprecation (but then neither does PHP Mailer either!). It follows the RFC 1939 standard explicitly and is fully commented.
-
-With that noted, here is how to implement it:
-
-I didn't want to modify the PHP Mailer classes at all, so you will have to include/require this class along with the base one. It can sit quite happily in the phpmailer directory.
-
-When you need it, create your POP3 object
-
-Right before I invoke PHP Mailer I activate the POP3 authorisation. POP3 before SMTP is a process whereby you login to your web hosts POP3 mail server BEFORE sending out any emails via SMTP. The POP3 logon 'verifies' your ability to send email by SMTP, which typically otherwise blocks you. On my web host (Pair Networks) a single POP3 logon is enough to 'verify' you for 90 minutes. Here is some sample PHP code that activates the POP3 logon and then sends an email via PHP Mailer:
-
-authorise('pop3.example.com', 110, 30, 'mailer', 'password', 1);
-$mail = new PHPMailer(); $mail->SMTPDebug = 2; $mail->isSMTP();
-$mail->isHTML(false); $mail->Host = 'relay.example.com';
-$mail->From = 'mailer@example.com';
-$mail->FromName = 'Example Mailer';
-$mail->Subject = 'My subject';
-$mail->Body = 'Hello world';
-$mail->addAddress('rich@corephp.co.uk', 'Richard Davey');
-if (!$mail->send()) {
- echo $mail->ErrorInfo;
-}
-?>
-
-The PHP Mailer parts of this code should be obvious to anyone who has used PHP Mailer before. One thing to note - you almost certainly will not need to use SMTP Authentication *and* POP3 before SMTP together. The Authorisation method is a proxy method to all of the others within that class. There are connect, Logon and disconnect methods available, but I wrapped them in the single Authorisation one to make things easier.
-The Parameters
-
-The authorise parameters are as follows:
-
-$pop->authorise('pop3.example.com', 110, 30, 'mailer', 'password', 1);
-
- 1. pop3.example.com - The POP3 Mail Server Name (hostname or IP address)
- 2. 110 - The POP3 Port on which to connect (default is usually 110, but check with your host)
- 3. 30 - A connection time-out value (in seconds)
- 4. mailer - The POP3 Username required to logon
- 5. password - The POP3 Password required to logon
- 6. 1 - The class debug level (0 = off, 1+ = debug output is echoed to the browser)
-
-Final Comments + the Download
-
-1) This class does not support APOP connections. This is only because I did not have an APOP server to test with, but if you'd like to see that added just contact me.
-
-2) Opening and closing lots of POP3 connections can be quite a resource/network drain. If you need to send a whole batch of emails then just perform the authentication once at the start, and then loop through your mail sending script. Providing this process doesn't take longer than the verification period lasts on your POP3 server, you should be fine. With my host that period is 90 minutes, i.e. plenty of time.
-
-3) If you have heavy requirements for this script (i.e. send a LOT of email on a frequent basis) then I would advise seeking out an alternative sending method (direct SMTP ideally). If this isn't possible then you could modify this class so the 'last authorised' date is recorded somewhere (MySQL, Flat file, etc) meaning you only open a new connection if the old one has expired, saving you precious overhead.
-
-4) There are lots of other POP3 classes for PHP available. However most of them implement the full POP3 command set, where-as this one is purely for authentication, and much lighter as a result. However using any of the other POP3 classes to just logon to your server would have the same net result. At the end of the day, use whatever method you feel most comfortable with.
-Download
-
-My thanks to Chris Ryan for the inspiration (even if indirectly, via his SMTP class)
diff --git a/download/phpmailer529/examples/code_generator.phps b/download/phpmailer529/examples/code_generator.phps
deleted file mode 100755
index 341a7d674..000000000
--- a/download/phpmailer529/examples/code_generator.phps
+++ /dev/null
@@ -1,597 +0,0 @@
-CharSet = 'utf-8';
-$mail->Debugoutput = $CFG['smtp_debugoutput'];
-$example_code .= "\n\n\$mail = new PHPMailer(true);";
-$example_code .= "\n\$mail->CharSet = 'utf-8';";
-
-class phpmailerAppException extends phpmailerException
-{
-}
-
-$example_code .= "\n\nclass phpmailerAppException extends phpmailerException {}";
-$example_code .= "\n\ntry {";
-
-try {
- if (isset($_POST["submit"]) && $_POST['submit'] == "Submit") {
- $to = $_POST['To_Email'];
- if (!PHPMailer::validateAddress($to)) {
- throw new phpmailerAppException("Email address " . $to . " is invalid -- aborting!");
- }
-
- $example_code .= "\n\$to = '{$_POST['To_Email']}';";
- $example_code .= "\nif(!PHPMailer::validateAddress(\$to)) {";
- $example_code .= "\n throw new phpmailerAppException(\"Email address \" . " .
- "\$to . \" is invalid -- aborting!\");";
- $example_code .= "\n}";
-
- switch ($_POST['test_type']) {
- case 'smtp':
- $mail->isSMTP(); // telling the class to use SMTP
- $mail->SMTPDebug = (integer)$_POST['smtp_debug'];
- $mail->Host = $_POST['smtp_server']; // SMTP server
- $mail->Port = (integer)$_POST['smtp_port']; // set the SMTP port
- if ($_POST['smtp_secure']) {
- $mail->SMTPSecure = strtolower($_POST['smtp_secure']);
- }
- $mail->SMTPAuth = array_key_exists('smtp_authenticate', $_POST); // enable SMTP authentication?
- if (array_key_exists('smtp_authenticate', $_POST)) {
- $mail->Username = $_POST['authenticate_username']; // SMTP account username
- $mail->Password = $_POST['authenticate_password']; // SMTP account password
- }
-
- $example_code .= "\n\$mail->isSMTP();";
- $example_code .= "\n\$mail->SMTPDebug = " . $_POST['smtp_debug'] . ";";
- $example_code .= "\n\$mail->Host = \"" . $_POST['smtp_server'] . "\";";
- $example_code .= "\n\$mail->Port = \"" . $_POST['smtp_port'] . "\";";
- $example_code .= "\n\$mail->SMTPSecure = \"" . strtolower($_POST['smtp_secure']) . "\";";
- $example_code .= "\n\$mail->SMTPAuth = " . (array_key_exists(
- 'smtp_authenticate',
- $_POST
- ) ? 'true' : 'false') . ";";
- if (array_key_exists('smtp_authenticate', $_POST)) {
- $example_code .= "\n\$mail->Username = \"" . $_POST['authenticate_username'] . "\";";
- $example_code .= "\n\$mail->Password = \"" . $_POST['authenticate_password'] . "\";";
- }
- break;
- case 'mail':
- $mail->isMail(); // telling the class to use PHP's mail()
- $example_code .= "\n\$mail->isMail();";
- break;
- case 'sendmail':
- $mail->isSendmail(); // telling the class to use Sendmail
- $example_code .= "\n\$mail->isSendmail();";
- break;
- case 'qmail':
- $mail->isQmail(); // telling the class to use Qmail
- $example_code .= "\n\$mail->isQmail();";
- break;
- default:
- throw new phpmailerAppException('Invalid test_type provided');
- }
-
- try {
- if ($_POST['From_Name'] != '') {
- $mail->addReplyTo($_POST['From_Email'], $_POST['From_Name']);
- $mail->From = $_POST['From_Email'];
- $mail->FromName = $_POST['From_Name'];
-
- $example_code .= "\n\$mail->addReplyTo(\"" .
- $_POST['From_Email'] . "\", \"" . $_POST['From_Name'] . "\");";
- $example_code .= "\n\$mail->From = \"" . $_POST['From_Email'] . "\";";
- $example_code .= "\n\$mail->FromName = \"" . $_POST['From_Name'] . "\";";
- } else {
- $mail->addReplyTo($_POST['From_Email']);
- $mail->From = $_POST['From_Email'];
- $mail->FromName = $_POST['From_Email'];
-
- $example_code .= "\n\$mail->addReplyTo(\"" . $_POST['From_Email'] . "\");";
- $example_code .= "\n\$mail->From = \"" . $_POST['From_Email'] . "\";";
- $example_code .= "\n\$mail->FromName = \"" . $_POST['From_Email'] . "\";";
- }
-
- if ($_POST['To_Name'] != '') {
- $mail->addAddress($to, $_POST['To_Name']);
- $example_code .= "\n\$mail->addAddress(\"$to\", \"" . $_POST['To_Name'] . "\");";
- } else {
- $mail->addAddress($to);
- $example_code .= "\n\$mail->addAddress(\"$to\");";
- }
-
- if ($_POST['bcc_Email'] != '') {
- $indiBCC = explode(" ", $_POST['bcc_Email']);
- foreach ($indiBCC as $key => $value) {
- $mail->addBCC($value);
- $example_code .= "\n\$mail->addBCC(\"$value\");";
- }
- }
-
- if ($_POST['cc_Email'] != '') {
- $indiCC = explode(" ", $_POST['cc_Email']);
- foreach ($indiCC as $key => $value) {
- $mail->addCC($value);
- $example_code .= "\n\$mail->addCC(\"$value\");";
- }
- }
- } catch (phpmailerException $e) { //Catch all kinds of bad addressing
- throw new phpmailerAppException($e->getMessage());
- }
- $mail->Subject = $_POST['Subject'] . ' (PHPMailer test using ' . strtoupper($_POST['test_type']) . ')';
- $example_code .= "\n\$mail->Subject = \"" . $_POST['Subject'] .
- '(PHPMailer test using ' . strtoupper($_POST['test_type']) . ')";';
-
- if ($_POST['Message'] == '') {
- $body = file_get_contents('contents.html');
- } else {
- $body = $_POST['Message'];
- }
-
- $example_code .= "\n\$body = <<<'EOT'\n" . htmlentities($body) . "\nEOT;";
-
- $mail->WordWrap = 78; // set word wrap to the RFC2822 limit
- $mail->msgHTML($body, dirname(__FILE__), true); //Create message bodies and embed images
-
- $example_code .= "\n\$mail->WordWrap = 78;";
- $example_code .= "\n\$mail->msgHTML(\$body, dirname(__FILE__), true); //Create message bodies and embed images";
-
- $mail->addAttachment('images/phpmailer_mini.png', 'phpmailer_mini.png'); // optional name
- $mail->addAttachment('images/phpmailer.png', 'phpmailer.png'); // optional name
- $example_code .= "\n\$mail->addAttachment('images/phpmailer_mini.png'," .
- "'phpmailer_mini.png'); // optional name";
- $example_code .= "\n\$mail->addAttachment('images/phpmailer.png', 'phpmailer.png'); // optional name";
-
- $example_code .= "\n\ntry {";
- $example_code .= "\n \$mail->send();";
- $example_code .= "\n \$results_messages[] = \"Message has been sent using " .
- strtoupper($_POST['test_type']) . "\";";
- $example_code .= "\n}";
- $example_code .= "\ncatch (phpmailerException \$e) {";
- $example_code .= "\n throw new phpmailerAppException('Unable to send to: ' . \$to. ': '.\$e->getMessage());";
- $example_code .= "\n}";
-
- try {
- $mail->send();
- $results_messages[] = "Message has been sent using " . strtoupper($_POST["test_type"]);
- } catch (phpmailerException $e) {
- throw new phpmailerAppException("Unable to send to: " . $to . ': ' . $e->getMessage());
- }
- }
-} catch (phpmailerAppException $e) {
- $results_messages[] = $e->errorMessage();
-}
-$example_code .= "\n}";
-$example_code .= "\ncatch (phpmailerAppException \$e) {";
-$example_code .= "\n \$results_messages[] = \$e->errorMessage();";
-$example_code .= "\n}";
-$example_code .= "\n\nif (count(\$results_messages) > 0) {";
-$example_code .= "\n echo \"
- A: PHP by itself is fairly fast, but it recompiles scripts every time they are run, which takes up valuable
- computer resources. You can bypass this by using an opcode cache which compiles
- PHP code and store it in memory to reduce overhead immensely. APC
- (Alternative PHP Cache) is a free opcode cache extension in the PECL library.
- A: On a single machine the sendmail (or Qmail) is fastest overall.
- Next fastest is mail() to give you the best performance. Both do not have the overhead of SMTP.
- If you do not have a local mail server (as is typical on Windows), SMTP is your only option.
- A: If you are using a Unix machine this is probably because the user
- running your web server does not have read access to the directory in question. If you are using Windows,
- then the problem is probably that you have used single backslashes to denote directories (\).
- A single backslash has a special meaning to PHP so these are not
- valid. Instead use double backslashes ("\\") or a single forward
- slash ("/").Run results
\\n\";";
-$example_code .= "\n echo \"\\n\";";
-$example_code .= "\nforeach (\$results_messages as \$result) {";
-$example_code .= "\n echo \"
\\n\";";
-$example_code .= "\n}";
-?>
-
-
-
- Run results
';
- echo '';
- foreach ($results_messages as $result) {
- echo "
';
-}
-
-if (isset($_POST["submit"]) && $_POST["submit"] == "Submit") {
- echo "
\n";
- echo "
Script:\n";
- echo "\n";
- echo $example_code;
- echo "\n
\n";
- echo "\n
\n";
-}
-?>
-
-
-
\ No newline at end of file
diff --git a/download/phpmailer529/examples/contents.html b/download/phpmailer529/examples/contents.html
deleted file mode 100755
index 9257f6dd9..000000000
--- a/download/phpmailer529/examples/contents.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
- This is a test of PHPMailer.
-
- PHPMailer code examples
-
About testing email sending
-
-
-Security note
-code_generator.phps
-mail.phps
-exceptions.phps
-smtp.phps
-smtp_no_auth.phps
-sendmail.phps
-gmail.phps
-pop_before_smtp.phps
-mailing_list.phps
-
-smtp_check.phps
-
-
';
- break; //Abandon sending
- } else {
- echo "Message sent to :" . $row['full_name'] . ' (' . str_replace("@", "@", $row['email']) . ')
';
- //Mark it as sent in the DB
- mysqli_query(
- $mysql,
- "UPDATE mailinglist SET sent = true WHERE email = '" .
- mysqli_real_escape_string($mysql, $row['email']) . "'"
- );
- }
- // Clear all addresses and attachments for next loop
- $mail->clearAddresses();
- $mail->clearAttachments();
-}
diff --git a/download/phpmailer529/examples/pop_before_smtp.phps b/download/phpmailer529/examples/pop_before_smtp.phps
deleted file mode 100755
index 164dfe8dd..000000000
--- a/download/phpmailer529/examples/pop_before_smtp.phps
+++ /dev/null
@@ -1,54 +0,0 @@
-isSMTP();
- //Enable SMTP debugging
- // 0 = off (for production use)
- // 1 = client messages
- // 2 = client and server messages
- $mail->SMTPDebug = 2;
- //Ask for HTML-friendly debug output
- $mail->Debugoutput = 'html';
- //Set the hostname of the mail server
- $mail->Host = "mail.example.com";
- //Set the SMTP port number - likely to be 25, 465 or 587
- $mail->Port = 25;
- //Whether to use SMTP authentication
- $mail->SMTPAuth = false;
- //Set who the message is to be sent from
- $mail->setFrom('from@example.com', 'First Last');
- //Set an alternative reply-to address
- $mail->addReplyTo('replyto@example.com', 'First Last');
- //Set who the message is to be sent to
- $mail->addAddress('whoto@example.com', 'John Doe');
- //Set the subject line
- $mail->Subject = 'PHPMailer POP-before-SMTP test';
- //Read an HTML message body from an external file, convert referenced images to embedded,
- //and convert the HTML into a basic plain-text alternative body
- $mail->msgHTML(file_get_contents('contents.html'), dirname(__FILE__));
- //Replace the plain text body with one created manually
- $mail->AltBody = 'This is a plain-text message body';
- //Attach an image file
- $mail->addAttachment('images/phpmailer_mini.png');
- //send the message
- //Note that we don't need check the response from this because it will throw an exception if it has trouble
- $mail->send();
- echo "Message sent!";
-} catch (phpmailerException $e) {
- echo $e->errorMessage(); //Pretty error messages from PHPMailer
-} catch (Exception $e) {
- echo $e->getMessage(); //Boring error messages from anything else!
-}
diff --git a/download/phpmailer529/examples/scripts/XRegExp.js b/download/phpmailer529/examples/scripts/XRegExp.js
deleted file mode 100755
index ebdb9c948..000000000
--- a/download/phpmailer529/examples/scripts/XRegExp.js
+++ /dev/null
@@ -1,664 +0,0 @@
-// XRegExp 1.5.1
-// (c) 2007-2012 Steven Levithan
-// MIT License
-// ]+)>/i, backref: 1}, //
tag attributes
- // {regex: XRegExp('(?ix) \\s src=" (?
'+this.getTitleHtml(this.getParam("title"))+""+"
"+""+(gutter?' "+""+"'+this.getLineNumbersHtml(t)+" ":"")+''+' "+".*?)"+"(?\n";
- $html .= $this->code;
+ $html .= $this->pde_code;
$html .= "\n\n";
$html .= "\n
\n\n";
if ($count >= $per_col) {
diff --git a/generate/libraries.php b/generate/libraries.php
index ee8bc5652..d34c53ba2 100755
--- a/generate/libraries.php
+++ b/generate/libraries.php
@@ -19,7 +19,7 @@
//`cd $path && /usr/bin/git pull https://github.com/processing/processing-docs/`;
-$libraries = array('net', 'serial', 'video', 'dxf', 'pdf', 'sound', 'io');
+$libraries = array('net', 'serial', 'video', 'dxf', 'pdf', 'sound', 'io', 'svg');
$lib_dir = REFERENCEDIR.'libraries/';
// Create Index
@@ -47,7 +47,7 @@
// template and copy index
$index = CONTENTDIR.$source.'/index.html';
- if($lib == 'pdf' || $lib == 'dxf') {
+ if($lib == 'pdf' || $lib == 'dxf' || $lib == 'svg') {
//$page = new Page(strtoupper($lib) . ' \\ Libraries', 'Libraries', 'Library-index');
$page = new Page(strtoupper($lib) . ' \\ Libraries', 'Libraries');
} else {
diff --git a/generate/libraries_local.php b/generate/libraries_local.php
index 7c946d94f..ddaeaff96 100755
--- a/generate/libraries_local.php
+++ b/generate/libraries_local.php
@@ -8,7 +8,7 @@
$benchmark_start = microtime_float();
-$libraries = array('net', 'serial', 'video', 'dxf', 'pdf', 'sound', 'io');
+$libraries = array('net', 'serial', 'video', 'dxf', 'pdf', 'sound', 'io', 'svg');
$lib_dir = DISTDIR.'libraries';
diff --git a/generate/reference.php b/generate/reference.php
index fd6ecc0f8..5e2a7532c 100644
--- a/generate/reference.php
+++ b/generate/reference.php
@@ -38,7 +38,9 @@ function out($output) {
out("Pulling in latest changes from processing/processing-sound/...");
$soundRepoPath = "{$path}../processing-sound";
-$shell_output = shell_exec("cd $soundRepoPath && /usr/bin/git pull https://github.com/processing/processing-sound/ 2>&1");
+//$shell_output = shell_exec("cd $soundRepoPath && /usr/bin/git pull https://github.com/processing/processing-sound/ 2>&1");
+// clone new processing-sound library from work-in-progress repository instead
+$shell_output = shell_exec("rm -rf $soundRepoPath && mkdir $soundRepoPath && cd $soundRepoPath && /usr/bin/git clone https://github.com/processing/processing-sound.git . 2>&1");
out($shell_output);
out("---------------");
@@ -64,20 +66,24 @@ function out($output) {
// Compress distribution into a ZIP, so it can be rolled into an IDE build.
+// processing/processing/java/
out("Compressing distribution directory...");
shell_exec("rm $mainRepoPath/build/shared/reference.zip 2>&1");
+//shell_exec("rm $mainRepoPath/java/reference.zip 2>&1"); // Add 10 Nov 2016 - CR
$docsRepoPath = "{$path}../processing-docs";
$shell_output = shell_exec("cd $docsRepoPath && cp -r distribution/ $mainRepoPath/build/shared/reference/ 2>&1");
+//$shell_output = shell_exec("cd $docsRepoPath && cp -r distribution/ $mainRepoPath/java/reference/ 2>&1"); // Add 10 Nov 2016 - CR
out($shell_output);
$shell_output = shell_exec("cd $mainRepoPath/build/shared/ && zip -r reference.zip reference/ 2>&1");
+//$shell_output = shell_exec("cd $mainRepoPath/java/ && zip -r reference.zip reference/ 2>&1"); // Add 10 Nov 2016 - CR
out($shell_output);
shell_exec("rm -r $mainRepoPath/build/shared/reference/ 2>&1");
+//shell_exec("rm -r $mainRepoPath/java/reference/ 2>&1"); // Add 10 Nov 2016 - CR
out("Done compressing!");
-
$benchmark_end = microtime_float();
$execution_time = round($benchmark_end - $benchmark_start, 4);
out("Generated files in $execution_time seconds.");
-?>
\ No newline at end of file
+?>
diff --git a/generate/staticpages.php b/generate/staticpages.php
index 307199396..1a60b6291 100755
--- a/generate/staticpages.php
+++ b/generate/staticpages.php
@@ -28,9 +28,9 @@
writeFile('overview/index.html', $page->out());
#copydirr($source.'/images', $path.'/images');
-$page = new Page("Foundation", "Foundation");
-$page->content(file_get_contents($source."foundation.html"));
-writeFile('foundation/index.html', $page->out());
+#$page = new Page("Foundation", "Foundation");
+#$page->content(file_get_contents($source."foundation.html"));
+#writeFile('foundation/index.html', $page->out());
$page = new Page("People", "People");
$page->content(file_get_contents($source."people.html"));
@@ -44,6 +44,17 @@
$page->content(file_get_contents($source."handbook.html"));
writeFile('handbook/index.html', $page->out());
+// Added 4 April 2017 for Membership Initiative
+$page = new Page("Support", "Donate");
+$page->content(file_get_contents($source."support.html"));
+writeFile('download/support.html', $page->out());
+
+// Added 6 April 2017 for Membership Initiative
+$page = new Page("Download", "Download");
+$page->content(file_get_contents($source."download.html"));
+writeFile('download/index.html', $page->out());
+
+
// Copy over the errata file for Processing: A Programming Handbook...
// copy($source.'processing-errata.txt', $path.'books/processing-errata.txt');
// Copy over the media.zip file for Getting Started with Processing...
@@ -54,21 +65,21 @@
writeFile('copyright.html', $page->out());
// Copy over the images for the shop index
-if (!is_dir($path.'shop')) {
- mkdir($path.'shop', 0757);
-}
+#if (!is_dir($path.'shop')) {
+# mkdir($path.'shop', 0757);
+#}
-if (!is_dir($path.'shop/imgs')) {
- mkdir($path.'shop/imgs', 0757);
-}
+#if (!is_dir($path.'shop/imgs')) {
+# mkdir($path.'shop/imgs', 0757);
+#}
-if (is_dir($path.'shop/imgs')) {
- copydirr($source.'shop/imgs', $path.'shop/imgs', null, 0757, false);
-}
+#if (is_dir($path.'shop/imgs')) {
+# copydirr($source.'shop/imgs', $path.'shop/imgs', null, 0757, false);
+#}
-$page = new Page("Shop", "Shop");
-$page->content(file_get_contents($source.'shop/'."index.html"));
-writeFile('shop/index.html', $page->out());
+#$page = new Page("Shop", "Shop");
+#$page->content(file_get_contents($source.'shop/'."index.html"));
+#writeFile('shop/index.html', $page->out());
$benchmark_end = microtime_float();
$execution_time = round($benchmark_end - $benchmark_start, 4);
diff --git a/img/cc.png b/img/cc.png
new file mode 100644
index 000000000..4acf8c4ec
Binary files /dev/null and b/img/cc.png differ
diff --git a/img/learning/books/coding-art.jpg b/img/learning/books/coding-art.jpg
new file mode 100644
index 000000000..79fa91e5a
Binary files /dev/null and b/img/learning/books/coding-art.jpg differ
diff --git a/img/learning/books/creating-procedural-artworks.jpg b/img/learning/books/creating-procedural-artworks.jpg
new file mode 100644
index 000000000..2724174b5
Binary files /dev/null and b/img/learning/books/creating-procedural-artworks.jpg differ
diff --git a/img/learning/books/data-driven-graphic-design.jpg b/img/learning/books/data-driven-graphic-design.jpg
new file mode 100644
index 000000000..d04fcb2cd
Binary files /dev/null and b/img/learning/books/data-driven-graphic-design.jpg differ
diff --git a/img/learning/books/il-codice-dei-cibernetici-sm.jpg b/img/learning/books/il-codice-dei-cibernetici-sm.jpg
new file mode 100644
index 000000000..6c1033a16
Binary files /dev/null and b/img/learning/books/il-codice-dei-cibernetici-sm.jpg differ
diff --git a/img/learning/books/il-codice-dei-cibernetici.jpg b/img/learning/books/il-codice-dei-cibernetici.jpg
new file mode 100644
index 000000000..725940450
Binary files /dev/null and b/img/learning/books/il-codice-dei-cibernetici.jpg differ
diff --git a/img/learning/books/o-codigo.jpg b/img/learning/books/o-codigo.jpg
new file mode 100644
index 000000000..e70fad0e9
Binary files /dev/null and b/img/learning/books/o-codigo.jpg differ
diff --git a/img/learning/books/opencv.jpg b/img/learning/books/opencv.jpg
new file mode 100644
index 000000000..826db6e99
Binary files /dev/null and b/img/learning/books/opencv.jpg differ
diff --git a/img/learning/books/pro-processing.jpg b/img/learning/books/pro-processing.jpg
new file mode 100644
index 000000000..25e7f6863
Binary files /dev/null and b/img/learning/books/pro-processing.jpg differ
diff --git a/img/learning/books/processing-an-introduction-to-programming.png b/img/learning/books/processing-an-introduction-to-programming.png
new file mode 100644
index 000000000..e92a39b12
Binary files /dev/null and b/img/learning/books/processing-an-introduction-to-programming.png differ
diff --git a/img/learning/books/processing-android-sm.jpg b/img/learning/books/processing-android-sm.jpg
new file mode 100644
index 000000000..a6b81a2a0
Binary files /dev/null and b/img/learning/books/processing-android-sm.jpg differ
diff --git a/img/learning/books/processing-android.jpg b/img/learning/books/processing-android.jpg
new file mode 100644
index 000000000..e66bc832f
Binary files /dev/null and b/img/learning/books/processing-android.jpg differ
diff --git a/img/learning/books/programming-101.jpg b/img/learning/books/programming-101.jpg
new file mode 100644
index 000000000..3749c36a2
Binary files /dev/null and b/img/learning/books/programming-101.jpg differ
diff --git a/img/learning/books/programming-for-artists.jpg b/img/learning/books/programming-for-artists.jpg
new file mode 100644
index 000000000..dce698ddf
Binary files /dev/null and b/img/learning/books/programming-for-artists.jpg differ
diff --git a/img/membership/membership-diy.jpg b/img/membership/membership-diy.jpg
new file mode 100644
index 000000000..475f57512
Binary files /dev/null and b/img/membership/membership-diy.jpg differ
diff --git a/img/membership/membership-learntoteach.jpg b/img/membership/membership-learntoteach.jpg
new file mode 100644
index 000000000..f6f8e206a
Binary files /dev/null and b/img/membership/membership-learntoteach.jpg differ
diff --git a/img/membership/membership-miami.jpg b/img/membership/membership-miami.jpg
new file mode 100644
index 000000000..13ce0d278
Binary files /dev/null and b/img/membership/membership-miami.jpg differ
diff --git a/img/membership/membership-p5.jpg b/img/membership/membership-p5.jpg
new file mode 100644
index 000000000..0a218af0d
Binary files /dev/null and b/img/membership/membership-p5.jpg differ
diff --git a/img/pcd17.png b/img/pcd17.png
new file mode 100644
index 000000000..cb5f2b18c
Binary files /dev/null and b/img/pcd17.png differ
diff --git a/java_generate/templates/class.template.html b/java_generate/templates/class.template.html
index 317ea7ffc..96634b4c1 100644
--- a/java_generate/templates/class.template.html
+++ b/java_generate/templates/class.template.html
@@ -1,7 +1,7 @@
-
disclaimer contact
- -content - -Updated on updated- Processing is a flexible software sketchbook and a language for learning how to code within the context of the visual arts. Since 2001, Processing has promoted software literacy within the visual arts and visual literacy within technology. There are tens of thousands of students, artists, designers, researchers, and hobbyists who use Processing for learning and prototyping. - -
+ Processing is a flexible software sketchbook and a language for learning how to code within the context of the visual arts. Since 2001, Processing has promoted software literacy within the visual arts and visual literacy within technology. There are tens of thousands of students, artists, designers, researchers, and hobbyists who use Processing for learning and prototyping. +
- New Books!
-
- The 2nd edition of Getting Started with Processing is here and it's updated for Processing 3. It's now in full color and there's a new chapter on working with data. The 2nd edition of the Processing Handbook is here too. Every chapter has been revised, and new chapters introduce more ways to work with data and geometry. New “synthesis” chapters offer discussion and worked examples of such topics as sketching with code, modularity, and algorithms.
-
-
-
+
To see more of what people are doing with Processing, check out these sites:
- -» CreativeApplications.Net
- » For Your Processing
- » Processing Subreddit
- » OpenProcessing
- » Vimeo
-
- » Studio Sketchpad
+
+ To see more of what people are doing with Processing, check out these sites:
+ » CreativeApplications.Net
+ » OpenProcessing
+ » For Your Processing
+ » Processing Subreddit
+ » Vimeo
+ » Studio Sketchpad
- To contribute to the development, please visit +
+ To contribute to Processing development, please visit Processing on GitHub to read instructions for downloading the code, building from the source, - reporting and tracking bugs, and + reporting and tracking bugs, and creating libraries and tools.
--
This example is for Processing 3+. If you have a previous version, use the examples included with your software. If you see any errors or have suggestions, please let us know.
+ + content diff --git a/templates/template.examples-basics.html b/templates/template.examples-basics.html deleted file mode 100644 index e2075f25e..000000000 --- a/templates/template.examples-basics.html +++ /dev/null @@ -1,7 +0,0 @@ -- These examples are running online through Processing.js using HTML5 Canvas and WebGL for rendering. There are many more examples included with the Processing application; please look there if you don't find what you're looking for here. -
- -content diff --git a/templates/template.examples-main.html b/templates/template.examples-main.html deleted file mode 100644 index 430686080..000000000 --- a/templates/template.examples-main.html +++ /dev/null @@ -1,7 +0,0 @@ -- These examples are running online through Processing.js using HTML5 Canvas and WebGL for rendering. There are many more examples included with the Processing application; please look there if you don't find what you're looking for here. -
- -content \ No newline at end of file diff --git a/templates/template.examples-topics.html b/templates/template.examples-topics.html deleted file mode 100644 index 8f4b71314..000000000 --- a/templates/template.examples-topics.html +++ /dev/null @@ -1,7 +0,0 @@ -- These examples are running online through Processing.js using HTML5 Canvas and WebGL for rendering. There are many more examples included with the Processing application; please look there if you don't find what you're looking for here. -
- -content \ No newline at end of file diff --git a/templates/template.examples.html b/templates/template.examples.html new file mode 100644 index 000000000..5973e8366 --- /dev/null +++ b/templates/template.examples.html @@ -0,0 +1,7 @@ ++ These examples are running online through p5.js using HTML Canvas for rendering. There are many more examples included with the Processing application; please look there if you don't find what you're looking for here. +
+ +content \ No newline at end of file diff --git a/templates/template.html b/templates/template.html index 91400ed36..b3836287a 100755 --- a/templates/template.html +++ b/templates/template.html @@ -26,6 +26,8 @@