From 165ee185c798c1a5a4f85ef89aeef96595056365 Mon Sep 17 00:00:00 2001 From: hickert Date: Thu, 12 Aug 2010 08:55:53 +0000 Subject: [PATCH] Removed PHPLot git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@19380 594d385d-05f5-0310-b6e9-bd551577e9d8 --- gosa-core/include/phplot-5.1.2/COPYING | 504 -- gosa-core/include/phplot-5.1.2/ChangeLog | 1010 --- .../include/phplot-5.1.2/HorizontalBars.txt | 243 - gosa-core/include/phplot-5.1.2/NEWS.txt | 814 --- gosa-core/include/phplot-5.1.2/README.txt | 156 - .../include/phplot-5.1.2/contrib/README.txt | 31 - .../contrib/color_range.example.php | 35 - .../phplot-5.1.2/contrib/color_range.php | 100 - .../contrib/color_range.test1.php | 55 - .../contrib/color_range.test2.php | 73 - .../contrib/prune_labels.example.php | 31 - .../phplot-5.1.2/contrib/prune_labels.php | 36 - .../contrib/prune_labels.test.php | 41 - gosa-core/include/phplot-5.1.2/phplot.php | 5873 ----------------- .../include/phplot-5.1.2/phplot_data.php | 270 - gosa-core/include/phplot-5.1.2/rgb.inc.php | 752 --- 16 files changed, 10024 deletions(-) delete mode 100644 gosa-core/include/phplot-5.1.2/COPYING delete mode 100644 gosa-core/include/phplot-5.1.2/ChangeLog delete mode 100644 gosa-core/include/phplot-5.1.2/HorizontalBars.txt delete mode 100644 gosa-core/include/phplot-5.1.2/NEWS.txt delete mode 100644 gosa-core/include/phplot-5.1.2/README.txt delete mode 100644 gosa-core/include/phplot-5.1.2/contrib/README.txt delete mode 100644 gosa-core/include/phplot-5.1.2/contrib/color_range.example.php delete mode 100755 gosa-core/include/phplot-5.1.2/contrib/color_range.php delete mode 100644 gosa-core/include/phplot-5.1.2/contrib/color_range.test1.php delete mode 100644 gosa-core/include/phplot-5.1.2/contrib/color_range.test2.php delete mode 100644 gosa-core/include/phplot-5.1.2/contrib/prune_labels.example.php delete mode 100644 gosa-core/include/phplot-5.1.2/contrib/prune_labels.php delete mode 100644 gosa-core/include/phplot-5.1.2/contrib/prune_labels.test.php delete mode 100644 gosa-core/include/phplot-5.1.2/phplot.php delete mode 100644 gosa-core/include/phplot-5.1.2/phplot_data.php delete mode 100644 gosa-core/include/phplot-5.1.2/rgb.inc.php diff --git a/gosa-core/include/phplot-5.1.2/COPYING b/gosa-core/include/phplot-5.1.2/COPYING deleted file mode 100644 index 602bfc946..000000000 --- a/gosa-core/include/phplot-5.1.2/COPYING +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/gosa-core/include/phplot-5.1.2/ChangeLog b/gosa-core/include/phplot-5.1.2/ChangeLog deleted file mode 100644 index 9d318a27c..000000000 --- a/gosa-core/include/phplot-5.1.2/ChangeLog +++ /dev/null @@ -1,1010 +0,0 @@ -This is the Change Log for PHPlot. -The project home page is http://sourceforge.net/projects/phplot/ ------------------------------------------------------------------------------ - -2010-06-29 (lbayuk) ===== Released as 5.1.2 ===== - * phplot.php: Updated version - * README.txt: Updated for new release - * NEWS.txt: Add text for new release - -2010-06-26 - * Feature request 2885930 "Horizontal Bars": - Horizontal bar charts are implemented, as an experimental feature. - A new data type 'text-data-yx' was added, which works with - 'bars' plot type to produce a horizontal bar chart from a data - array with X values for each Y value. Changes were made to - FindDataLimits, CalcMargins, CalcPlotAreaWorld, CalcBarWidths, - and CalcMaxDataLabelSize to handle the new data type. Other - changes were made to handle label position defaults and grid - defaults. New drawing functions were added for horizontal bars. - - * HorizontalBars.txt: new documentation file for experimental feature. - * Makefile: List new documentation file. - -2010-06-25 - * Each plot-type drawing function now checks that it is getting a data - type that it knows how to handle. A new internal function unifies the - checking and error message. (This is associated with an upcoming, - bigger change.) - - Compatibility: If you were using an invalid data type for a plot type - whose function did not check, will now get an error. - - * Removed some dubious code from DrawLines() and DrawSquared() and - rewrote comments there. The code initialized lastx[0] and lasty[0], - but lasty was mapped using the X (rather than Y) function. This was - obviously wrong, but closer inspection showed that the values were - never, used so the code was removed. - -2010-06-13 - * Truecolor.txt: removed - * Makefile, README.txt: Removed reference to Truecolor.txt. Full - documentation for truecolor images is now in the Reference Manual. - -2010-06-02 - * Fix bug 3010116 "Bad rendering of title in multi-plot image - when using TTF": - Make sure the main title is drawn only once. (If drawn multiple - times with TrueType font text, the anti-aliasing effects result - in poor quality text.) - -2010-05-31 - * Improvements to truecolor support (from feature request 2947679): - Truecolor support is now better integrated. The derived class only - has the constructor now, and the base class itself provides the alpha - color component support through the internal functions SetIndexColor(), - SetIndexDarkColor(), and SetRGBColor(). This means alpha channel - works with palette images too (in so far as GD supports this). - - * Truecolor.txt: Updated per changes to truecolor support. - - * Image tiling with mode 'scale' in tile_img(), used with image and - plot area backgrounds, now uses imagecopyresampled() rather than - imagecopyresized(). They are the same with palette images, but the - resampled copy gets better results with truecolor images. - -2010-05-29 - * Feature request 3002606 "Add to plot and image border options": - Added options 'right', 'top', and 'bottom' to SetPlotBorderType() - (existing options are 'left', 'sides', 'none', and 'full'). This - now also accepts an array of the above options, giving complete - control over which sides to draw. - Added option 'solid' to SetImageBorderType() to use the actual - color set with SetImageBorderColor(), rather than the darker - shade as type 'plain' does (for some reason). - New function SetImageBorderWidth() sets the width of the image - border. The image border width is now accounted for in margin - calculations, although existing plots will not change. - -2010-04-04 (lbayuk) ===== Released as 5.1.1 ===== - * phplot.php: Updated version - * README.txt: Updated for new release - * NEWS.txt: Add text for new release - -2010-04-01 - * Remove & from argument in SetDataValues(). The data array is not - modified and does not need to be passed by reference. (There is - no performance advantage, either.) - -2010-03-29 - * Feature request 2947679 "Support for alpha blending/Truecolor": - Implemented truecolor image support with a new class - PHPlot_truecolor, extended color specifications to allow - specification of an alpha value, and added a new optional parameter - to SetDataColors for a default alpha value for all data colors. - This feature is *EXPERIMENTAL* (see next item). - - * Truecolor.txt: New file, documentation for the new truecolor capability. - (The Truecolor feature is experimental, which means it is subject to - change in incompatible ways and the documentation has not yet been - incorporated into the PHPlot Reference Manual.) - - * Makefile: Include new documentation file in release. - -2010-03-26 - Fixed bug 2976735 "Improvements and fixes for 'area' plots": - Rewrote DrawArea() function which handles 'area' plot. - Part 1: This is related to feature request 2947679, Truecolor support - with transparency. The area plot function was filling each area from the X - axis up to the Y value, resulting in area overlaps. This wasn't a problem - with opaque colors, but with transparency, the overlapping areas resulted - in changed colors. The rewritten function fills the area between each line - instead of from each line down to the X axis. Plots with opaque colors - will not change. - Part 2: Area plots now work when the X axis is moved up with - SetXAxisPosition(). - Part 3: Fixed FindDataLimits() for area (and stackedbars too) to - take absolute values of Y values. The drawing function was doing this, - but not FindDataLimits, resulting in incorrect limits if any Y<0. - Part 4: The rewritten DrawArea() also handles a new plot type - 'stackedarea'. This is an area plot where the Y values are stacked, - similar to 'stackedbars'. - Note: As part of the changes, it is now an error to try an area plot - with an unequal number of Y points for each X. - -2010-03-23 - * Feature request 2973995 "Add y-Data to Stackedbars": - Implemented Y Data Labels for Stacked Bar charts (stackedbars). - The labels are enabled with SetYDataLabelPos, same as with bar charts. - There are two types of labels: above the stack with the total, and - within the bars at each segment. 'plotin' turns on the upper ones, and - 'plotstack' turns both on. - - * Other changes: - + Removed unimplemented second argument to SetYDataLabelPos. - + Fixed questionable logic in SetYDataLabelPos when given an argument - that belongs with SetYTickLabelPos. - + Fix comments at top of plot-type Draw functions. - - * Fix for bug 2974639 "Stacked bars plot breaks with X axis != 0": - Stacked bar plots with non-zero X axis position no longer break apart - into segments with gaps. The bars are drawn up from the X axis, and - any segments or partial segments below the X axis are not drawn. - -2010-03-22 - * Change related to feature request 2947679 - Fix 'dot' point shape: - Use imagefilledellipse(), not imagefilledarc(), when drawing the 'dot' - point shape. The fix was needed for future support of truecolor images - with transparency, but filled dots from imagefilledellipse() look - better (rounder) with regular images and opaque colors. - Credit to mvaldez for identifying the problem and providing the fix. - -2010-03-04 - * Fix for bug 2963757 "point_counts undefined error in 5.1.0": - Fixed CheckPointParams so it sets point_counts even when the point shape - and point size arrays are already the same size and do not need padding. - -2010-01-26 - * Fix for bug 2938219 "Bars go in wrong direction": - Fixed CalcAxisPositions() to be consistent in positioning the X axis. - When all Y values are <0 and the Y=0 line is not part of the plot range, - PHPlot will now default the X axis to the top of the plot, not the - bottom. This fixes the problem with bars to negative Y values being - drawn downward if Y=0 is visible, but upward if Y=0 is not visible. - This also affects thinbarline plots. - Credit to lauryn1298 for finding the bug. - -2009-12-24 (lbayuk) ===== Released as 5.1.0 ===== - -2009-12-18 - * Change for bug 1795971 "Fix default data colors": - The default Data Color and Error Bar Color arrays now have 16 - different colors, no duplicates, and nothing so light that it - is invisible. - Using '' or False as the argument to SetDataColors, SetErrorBarColors, - and SetDataBorderColors now re-initializes the map to the defaults. - This was previously undocumented, and in some cases set the map to - something different from the default. - -2009-12-15 - * Cleanup: Remove DrawAxisLegend() - empty function marked TODO, - not really clear what it was meant to do. - -2009-12-14 - * Fix for bug 2914403 "Pie + X/Y titles: Undefined property error": - In DrawGraph(), don't try to draw X or Y titles for pie charts. - - * Feature request 2899921: "allow different format for data and tick - labels"; Bug 2906436: "Fixes for X Tick Labels vs X Data Labels", - and partial implementation of changes from user 'adoll' regarding - tick vs data labels: - - New public functions: - + SetXDataLabelType() : Sets formatting for X Data Labels - + SetYDataLabelType() : Sets formatting for Y Data Labels (bar charts) - + SetXDataLabelAngle() : Sets text angle for X Data Labels - + SetYDataLabelAngle() : Sets text angle for Y Data Label (bar charts) - The defaults for these are set up to be fully backward compatible - with previous releases of PHPlot (except see the next item). - - Re-used function name SetXDataLabelAngle(): - + This has been deprecated and undocumented since 2003-12-07, and - used to just call SetXLabelAngle(). For new behavior, see above. - - Changes to public functions: - + SetXDataLabelPos() and SetXTickLabelPos() no longer cancel each - other out (set the other control variable to 'none'). Instead, - they are both considered before plot drawing. - - Changes to internal functions: - + DrawDataLabel() now uses the font, angle, and color arguments as - provided, and does not substitute values if they are empty. - + SetLabelType() now takes mode='xd' and 'yd' for X Data and Y Data - label formatting; 'x' and 'y' are for tick labels only now. - + Functions that work on Data labels now call FormatLabels() with the - new mode parameter value 'xd' or 'yd, and use the new - data_label_angle variables. - + New CheckLabels(), used by DrawGraph to process label parameters. - + CalcMargins() - Rewritten to handle changes to Tick and Data labels. - - Changes to internal class variables: - + New: x_data_label_angle, y_data_label_angle - + Do not initialize x_tick_label_pos or x_data_label_pos, so that - CheckLabels() can tell if they were set or not and apply defaults. - + Initialize y_data_label_pos to 'none', not 'plotleft'. - + Add 2 more indexes to label_format[] array: 'xd' and 'yd'. - - * Cleanup: - + Delete unused internal class variable: draw_y_data_label_lines - + Delete unused function SetDrawYDataLabelLines() - -2009-12-07 - * Fix bug 1795972 "Fix default point shapes": - + Added 10 new point shapes to the existing 10 shapes. - + Changed the default point shape from all 'diamond' to a - selection of up to 10 different shapes. - + Fixed bug in the code that tried to set the point shapes - and sizes arrays to be the same size. This was not working, - resulting in unexpected point sizes. - + Changed default point size to 6 for all shapes. It was trying - to be "5, 5, 3" but due to several bugs this was not working. - + Do not adjust shape sizes to even numbers (was done for only two - shapes). Instead, consistently truncate size/2 when needed. - NOTE: These may change the look of 'points' and 'linepoints' plots. - - * Changed startup initialization code: - + SetDefaultStyles() was doing some odd things using a variable - called "session_set", with comments referring to non-existent - session support code. This has been removed. There should be - no visible changes from this. PHPlot does not use PHP sessions. - -2009-12-04 - * Fix for bug 2908256, errors in pie charts with bad data array: - (From a Drupal contrib module report by thekevinday.) - With pie charts only, a data array with no valid Y values resulted - in PHP error messages. All other plot types handle this by producing - an image without a graph. - Fixed DrawPieChart to behave this way too. If there are no valid Y - values, or if the sum of all Y values is 0, do not error out, but - don't draw a pie chart either. - Also, pie charts now ignore non-numeric Y values, like other plot types. - -2009-11-20 (lbayuk) - * Fix for bug 2900914 "Problem with display of 0 on Y axis": - Changed how X and Y values are stepped by tick intervals, to avoid - cumulative round-off error. This fixes the problem when Y crosses 0 with - a tick step such as 0.1 resulting in a long label for a very small but - non-zero number. Fixed DrawXTicks, DrawYTicks, and CalcMaxTickLabelSize. - (Originally reported by cncnet) - -2009-11-19 (lbayuk) - * Improve support for using callbacks to annotate plots: - Added new callback 'draw_all', called after all drawing. - Supply plot_area[] as argument to some drawing callbacks. - Added new method GetDeviceXY() to translate from world coordinates. - Allow NULL or '' for $font in DrawText() internal method, meaning to - use the generic font. If callbacks want to use DrawText, this - avoids them having to reference the internal fonts[] array. - -2009-11-01 (lbayuk) - * Address bug report 2886365 "Declare all functions and variables in - PHP5 style" - PHP5 deprecates the use of 'var' to declare a class member variable. - All initialized class member variables are now declared 'public'. - (It was tempting to make most or all 'protected' or 'private', but - that would likely break too much, including the PHPlot Test Suite.) - - Most class member functions which are meant for internal use only are - now declared 'protected', so they cannot be called from scripts - (except in child classes). (Note PHP5 does not deprecate the use of - just 'function' to mean public, so public functions were not changed.) - Internal functions are those documented in the manual under Developer's - Guide, Internal Functions. If your code breaks because you are using - a method which is now protected, please post the details on the help - forum. - - Some member variables which were set in the constructor are now - initialized with the class instead. (No impact.) - - Removed commented-out, FIXME-noted code for interim labels. - -2009-10-12 (lbayuk) - * Bug report 2839547, allow SetImageBorderType('none') to reset the image - border type. Also checked for other cases where there is no reset; - found one that exists (Set[XY]LabelType) but needs to be documented. - -2009-07-09 (lbayuk) - * Added a hook $plot->locale_override which can be set to True to prevent - PHPlot from loading locale settings from the environment with - setlocale(LC_ALL, ''). This is necessary for testing PHPlot on Windows, - where you cannot force a locale with an environment variable. It might - also be needed for people who want PHPlot's locale to differ from the - web server's locale. - -2009-06-12 (lbayuk) ===== Released as 5.0.7 ===== - -2009-06-11 (lbayuk) - * Change PHPlot license to LGPL, per Afan. - phplot.php, phplot_data.php - Change license notice. - rgb.inc.php - Change top comments and remove bottom marker. - COPYING - new file, text of LGPL. - LICENSE.* - removed files - old licenses. - Makefile - change list of distributed files. - - * Fix for bug 2803900: SetRGBArray('large') does not work. The include - file defined a different array name than the main script expected. - (This bug seems to have happened over 8 years ago.) Fixed the array - names to match. Also removed the ./ prefix from the included filename - so it will be found if on the include path but not in the script - directory. Also added error check if the rgb.inc.php include file - is needed and not found. - -2009-05-25 (lbayuk) - * Added new feature to allow partial margin or plot area specification. - You can omit, or specify as NULL, any of the 4 arguments to - SetMarginsPixels() or SetPlotAreaPixels(), and this means PHPlot - should use the automatically calculated margin on that side. - Credit to adoll for this feature. - -2009-05-17 (lbayuk) - * Fix for bug 2791502 "Error plots treat missing Y values as 0": - Plots with data type data-data-error now support missing Y values, - instead of treating them as 0. This works with lines, points, - and linepoints plot types, and also honors SetDrawBrokenLines. - - - * Fix for bug 2792860 "Wrong DataLabelLines with missing Y": - Do not draw X Data Label Lines at points with missing Y values. - - - * Fix for bug 2786350 "Missing Y data results in bad auto-range": - Rewrote FindDataLimits to ignore missing Y values, rather than - treating them as if 0, for calculating range. - Bug report and analysis by mrten. - - * Fix for bug 2786354 "Incorrect auto-range for data-data-error": - For data-data-error data type, apply the positive and negative error - amounts for each Y point to that point only, rather than applying the - largest errors to the overall minimum and maximum Y value for the row. - - Note: The two fixes above can change existing plots which rely on - automatic Y range calculation. The first fix affects plots with - missing Y values and min(Y)>0. The second fix can affect plots using - data-data-error data type and different error values for different - points. In both cases the new Y range can be smaller than before. - -2009-01-20 (lbayuk) ===== Released as 5.0.6 ===== - -2009-01-18 (lbayuk) - * Fix for bug 1891636 "Misaligned TTF X Labels": - PHPlot was using the actual bounding box of each line of text - to allocate space and set the text positioning, but was ignoring the - fact that the text baseline is not the same as the bottom of the - bounding box. This resulted in uneven alignment of the X labels if - they had different heights (for example, month names Jul and Aug). - - PHPlot now calculates the size of text for allocation (SizeText) using - the descenders on the last line, and calculates the size for drawing - (DrawText) only to the baseline. PHPlot also now uses a fixed line - spacing for each line of text in a font, rather than the actual text - height. This allows separately drawn multi-line labels to align. - - * Changes to line spacing when using multi-line labels: - PHPlot was using the class variable line_spacing to mean the - number of pixels between lines of multi-line labels. This made the - spacing too small for larger fonts, and it was not possible to adjust - line spacing for different types of text. - - PHPlot now interprets line_spacing as the number of pixels only - for GD text, and as a scale factor for the font's built-in line - spacing for TrueType text. In addition, a new optional argument is - added to SetFont, SetFontGD, and SetFontTTF to set a line spacing - specific to that type of text. - - * Changes had to be made to the legend drawing code to accommodate the - changes to font handling. - - Note: The line spacing change results in slightly looser spacing on - multi-line TrueType text labels, and slightly taller legends, compared - to version 5.0.5. - -2008-09-21 (lbayuk) - * Interim fix for bug 1932571 "Data-Data Plot fails with same X values". - PHPlot will no longer hang when the range of X values is 0 (that is, when - x_min == x_max). It will arbitrarily set an X range of 1, so the - calculated tick step is not 0. This is a temporary fix. Work on a smarter - X and Y range calculation is in progress, which will handle edge cases - like this better, but it isn't ready and this bug has been open too long. - Credit to andyl for finding the bug. - - * Fix font path: Use DIRECTORY_SEPARATOR constant not '/'. - - Extended the label formatting capabilities, adding 'printf' and 'custom' - types, added a prefix and suffix for 'data' type, and allow format controls - to be included in SetXLabelType and SetYLabelType. - - External changes: - * Added 'printf' label type. The caller specifies the print format as the - 2nd argument to SetXLabelType or SetYLabelType (default '%e'). - $plot->SetXLabelType('printf', '%5.2f'); - - * Added 'custom' label type. The caller supplies a callback (typically a - function name) and optional pass-through argument as the 2nd and 3rd - arguments to Set[XY]LabelType. The function is called as $f($value, $arg) - to return the formatted $value. - $plot->SetXLabelType('custom', 'myfunction', $arg_value); - - * In addition to Set[XY]TimeFormat, the format string for type 'time' can - now be set as the 2nd argument to Set[XY]LabelType. - $plot->SetXLabelType('time', '%H:%M'); - - * In addition to SetPrecision[XY], the precision for type 'data' can now be - set as the 2nd argument to Set[XY]LabelType. A 3rd and 4th argument - can supply a prefix and suffix for 'data' formatting. (All optional) - $plot->SetXLabelType('data', 2, '$', 'US'); - - Internal changes: - * Class variables x_precision, y_precision, x_label_type, y_label_type, - x_time_format, and y_time_format have been removed. - - * New class array variable label_format[], with elements 'x' and 'y' which - are arrays for label formatting. Elements in the sub-arrays are not - initialized until needed. - - * New function SetLabelType, which implements Set[XY]LabelType now. - - * FormatLabel() was rewritten to support the new label formatting. - - Compatibility: - * Any code that directly references class variables related to label - formatting will break, except for data_units_text. Use the documented - function methods instead. Setting data_units_text as a suffix is - deprecated but still works. - - * The 'data' type precision for 'Y' is still used for pie chart labels. - -2008-07-12 (lbayuk) - Multiple comment spelling error fixes. No functional changes. - -2008-07-06 (lbayuk) - Changes to allow mixing GD fixed-font text and TrueType Font (TTF) text - on the same plot. - (This change came from work done trying to fix TTF text positioning, - where it looks like additional information needs to be stored for TrueType - fonts. The old font data structure was awkward to extend, and allowing - mixed GD/TTF text was on the to-do list anyway.) - - External changes: - * SetFontGD(), SetFontTTF(): New functions to set a font, with type. - * SetFont(): Now calls SetFontGD or SetFontTTF depending on $use_ttf. - These changes should be fully compatible with existing programs. - - Internal changes: - * Updated comments explaining SetUseTTF() now sets the default type - (not the only type) of text used. - * Put all the font data into a class array. (Replaces $this->generic_font - with $this->fonts['generic'], etc.) - * ProcessTextGD() and ProcessTextTTF() now take the font array as one - argument, rather than separate arguments for font path and size. - -2008-01-13 (lbayuk) ===== Released as 5.0.5 ===== - * phplot.php: Updated version - * README.txt: Updated for new release - * NEWS.txt: Add text for new release - * Makefile: Remove 'Callbacks' from release target, as this material is - now in the reference manual. - -2008-01-07 (lbayuk) - Copyright updated to 2008 and PHP4 no longer listed as supported. - - Major rewrite of the margin calculation functions to address multiple - problems. Fixes for bugs 1856207 "Margin error with 'xaxis'/'yaxis' - position, 1843012 "Make margins, drawing consistent", and 945439 - "x_tick_label_height not set correctly". - - Note: These changes are inter-dependent and cannot be split up. - - * Defer all calculations to DrawGraph time, to eliminate order dependencies. - These functions now just store their arguments in the object, and all - calculations happen later: - + SetXAxisPosition, SetYAxisPosition - + SetMarginsPixels - + SetPlotAreaPixels (Stores margins, not area, now.) - + SetPlotAreaWorld - + SetXTickIncrement, SetYTickIncrement - - * A new callback 'debug_scale' was added to trace the margin and scale - calculations. - - * CalcMargins was rewritten. Actual sizes of tick and data labels are now - used, rather than guesses like "use size of biggest Y value". A minimum - value (3 x safe_margin, or 15 pixels) applies to each margin. - - * FindDataLimits no longer needs to find the longest data label, since - CalcMargins now does that more precisely. - - * DrawXTitle and DrawYTitle now use position offsets calculated by - CalcMargins. Note: These titles are now offset from the plot area, - not the image area. The titles will move if you had set the plot area - or margins. - - * DrawYTick, DrawXTick rewritten to use pre-calculated offsets, and common - code moved to new CalcTicks(). - - * DrawXDataLabel: Use pre-calculated offsets for text. - - * DrawGraph: Rewrote top section (before drawing anything) to do the - calculations in the proper order, unconditionally. - - * Class variables removed: - x_label_inc, y_label_inc, _x_label_cnt : These were never used. - title_height, x_title_height, y_title_width : Now internal to CalcMargins. - data_limits_done : No more need to remember if FindDataLimits called. - - * New class variables added: - plot_margins_set : Keeps track of user-set plot area or automatic. - x_label_top_offset, x_label_bot_offset, x_offset_axis_offset, - y_label_left_offset, y_label_right_offset, y_label_axis_offset, - x_title_top_offset, x_title_bot_offset, - y_title_left_offset, y_title_left_offset : Label offsets - - * New internal functions: - CalcPlotAreaPixels : Deferred calculations taken out of SetPlotAreaPixels - and SetMarginsPixels. - CalcPlotAreaWorld : Deferred calculations taken out of SetPlotAreaWorld. - CalcAxisPositions : Calculate axis positions, moved from CalcTranslation. - CalcTicks : Calculate X and Y tick interval. This still uses the - same simple method (basically range/10), but now we could drop in a new - algorithm much more easily. This is now also used by CalcMargins. - Code taken out of DrawXTicks and DrawYTicks. - CalcMaxTickLabelSize : So CalcMargins can use the exact tick label sizes. - CalcMaxDataLabelSize : So CalcMargins can use the exact data label sizes. - DrawXTick : Code split out from DrawXTicks for symmetry with DrawYTick. - - -2007-12-13 (lbayuk) - * Changed ProcessTextTTF() so SizeText() will return integers. It rounds - the calculated values up, so the bounding box really contains the text. - This also prevents unneeded float calculations in derived values. - -2007-12-09 (lbayuk) - Major rewrite of the text drawing functions to address multiple problems. - Note: These changes are inter-dependent and cannot be split up. - - * Fixed bug 1813070 "Bad position for multi-line TrueType text": - TTF text is now drawn line-by-line, not as a block, for proper - alignment and positioning. - - * Fixed bug 1813071 "Wrong title height for multi-line TTF text": - Corrected miscalculation of overall height of multi-line TTF titles. - This bug resulted in over-sized margins. - The height is now computed line-by-line, including the inter-line spacing. - - * Fixed bug 1813474 "DrawText alignment arguments wrong": - Corrected meaning of 'top' vs 'bottom' alignment. PHPlot now follows - the usual conventions: 'top' alignment means top of text to reference. - DrawText default for vertical alignment is still 'bottom', but the - meaning was corrected. All callers of DrawText were fixed. - - * Fixed bug 1816844 "Fix order dependency for setting titles": - Defer processing titles strings until DrawGraph(), so there is no - more order dependency (no need to set font before setting title strings). - - * Fixed bug 1819668 "Horiz. align multi-line text: GD vs TTF": - The new text routines draw TTF text line-by-line and correctly do - right-, center-, and left- alignment of each line within a text block. - - * Fixed bug 1826513 "FIXME in DrawLegend: Max label length": - Use actual width of widest legend line to calculate legend box size. - - * Partial fix for bug 945439 "x_tick_label_height not set correctly": - In FindDataLimits(), save the longest data label, not just its length, - and use the actual rendered size of that string in CalcMargins() for - the margin calculations. - Also take into account which of the tick or data labels are visible. - This is not a complete fix, but is a significant improvement. - - The following changes were made related to the above fixes: - - + Replaced internal function TTFBBoxSize(), which didn't work right, with - SizeText(). It returns the orthogonal bounding box of a block of text, - and works with both GD and TTF text. - - + DrawText() and SizeText() call a single function ProcessText(), which is - the only place GD text and TTF text are distinguished. (So eventually - we will be able to mix GD and TTF text on a plot.) - - + New internal functions ProcessTextGD() and ProcessTextTTF() draw (or size) - GD and TTF text respectively. These are only called by ProcessText(). - These are re-implementations which properly position and align text. - - + Removed class variables title_angle, x_title_angle, and y_title_angle. The - titles only work at their fixed angles anyway (0, 0, and 90 respectively). - - + Line spacing set with SetLineSpacing() now affects TTF text as well as - GD text. Previously, it only affected GD text. The default line spacing - happens to be usable for TTF text. - - + Added new callback hook 'debug_textbox' for developing, testing, and - documenting. It provides access to the text area bounding box. - - + Removed unneeded class variables x_tick_label_height, y_tick_label_width, - x_tot_margin, y_tot_margin. - -2007-11-25 - * Improve error handling: - Internal functions PrintError() and DrawError() are now the same. Both - will draw the error message into the image and output it, and then - trigger a user-level error. If no error handler has been set, it will - exit, as before. But now the error message should also get logged, or - written to the standard error stream, depending on the SAPI in use. - You can now establish an error handler to catch most PHPlot errors and - do some cleanup before exit. - - This fix also covers bug #1823774 "Default Font Path and Error Message - Output". - - Fixed the return value of most PHPlot functions, to return False on - error, else True. Since uncaught errors are fatal anyway, this only - affects code with an error handler that returns, which is not - recommended and unsupported at this time. These changes are for - possible future error handling options. - -2007-11-22 - * Fix bug 1836528 "Insufficient checking of parameter values": - Rewrote CheckOption to correctly validate option choices. - (It previously accepted substrings and other incorrect values.) - PHPlot methods that use CheckOption now must be called with valid option - values. Empty strings are also no longer accepted. - -2007-11-17 (lbayuk) - * Change to callbacks to support extra arguments. - The PHPlot class can now pass extra arguments to a callback function. - Callback functions now take the following form: - my_callback($img, $passthru_arg, ...) - Where '...' is zero or more additional arguments supplied by PHPlot to - the callback. Each implemented callback reason will define any - additional arguments it uses. The existing defined callbacks have not - changed and do not currently pass any extra arguments. - -2007-11-10 (lbayuk) - * Fix bug 1827263 "Spoiled up pie-chart if $val is close to zero": - Skip pie slices which would result in an integer angle of zero - degrees, because the GD arc filling function will draw a complete - circle for that case. - Credit to Viacheslav for finding this. - - * Removed 8 of the functions (class methods) marked 'deprecated'. Only - deprecated functions which seem to have been for internal use have - been removed. Even old scripts shouldn't be using them, and they are - becoming a problem to maintain. - Removed: SetImageArea() DrawDotSeries() DrawLineSeries() CalcXHeights() - CalcYWidths() DrawLabels() InitImage() DrawDashedLine(). - -2007-10-20 (lbayuk) ===== Released as 5.0.4 ===== - * phplot.php: Updated copyright, version, and authors comments at top. - * README.txt: Updated for new release - * NEWS.txt: Add text for new release - -2007-10-18 (lbayuk) - * Add callbacks - experimental feature: - New functions SetCallback, GetCallback, RemoveCallback. - New internal function DoCallback. - Added callback hooks to DrawGraph. - - Re-arranged code in DrawGraph to bring pie chart drawing into the main - switch on plot type, rather than a special case in its own block. This - makes it easier to follow and easier to add callback hooks. - - * Callbacks: New file, documentation for the new callbacks feature. - (This won't be in the manual while it is an experimental feature.) - -2007-10-15 (lbayuk) - * Fix for bug 1813021: Miss-positioned right-justified vertical GD text. - Fixed DrawText() to correctly position 90 degree right-justified text - drawn in a fixed GD font. This could be seen with 90 degree Y tick - labels. (Found by accident while working on TrueType text problems.) - Also some code cleanup in DrawText: use elseif where appropriate. - -2007-10-09 (lbayuk) - * Code cleanup: Simplify SetIndexColor() and SetIndexDarkColor(). - There is no need to first try ImageColorExact, then ImageColorResolve - if that fails. ImageColorResolve does all that for us. - - Code cleanup: Rewrite SetRGBColor(). It now detects if an unrecognized - color name or color value form is used, and draws an error message. - Before this it would get a PHP index error and "headers already sent" - condition. - - * Code cleanup: Remove duplicated code for loading image files. - Added new class-private function GetImage() which loads an image based - on the image type, and also returns the image size. This replaces - duplicated code in tile_img() and SetInputFile(). - Also fixed comment at top of SetImageFile which said it was deprecated. - It isn't - it is used by the constructor. Moved the function out of the - 'deprecated' area up to below where it is used. - - * Code cleanup: PHPlot should not define or affect anything outside its - own class. - - Removed the check for __FUNCTION__ (PHP 4.3 and up). This is obsolete. - - Do not set error_reporting to E_ALL. Although it is recommended that - scripts do this, it is not the place of loaded classes to do it. - - Remove unused global constant TOTY. - - Removed constants MAXY and MINY. Global constants like this are bad. - These were used as magic index values into data[] to hold min and max Y - values for the row. Instead, put them in separate arrays which are - named data_miny[] and data_maxy[]. (This seems to be only used by the - data line drawing function.) - - Comment cleanup: Remove one commented-out partial function DrawPlotLabel, - and fix another commented-out code fragment in DrawYErrorBar. Both of - these had unmatched braces in them which caused a balance-braces check - to fail. - - * Code cleanup, array padding: Get rid of functions outside the class - and remove the interim fix for PHP 5 (which changed the behavior of - array_merge). Rewrote external function array_pad_array() as a new - class function pad_array(). It does not need access to the class, - but I don't think PHPlot should add to the global namespace more - than necessary. The third argument (array to use for padding) was - never used, so it was removed. It always pads the array with itself. - It now only works on 'usual integer indexed' arrays (0-based - sequential integer index). The was previously required but - undocumented for some of the arrays (like line_widths); now it is - required for all style arrays and will be documented. Now we can pad - the array to the required length, not just N times its previous - length, and we don't need array_merge. Deleted external function - array_merge_php4() as it is no longer used. - - Deleted PHP end marker ?>. You don't need this and it can cause - problems with extra whitespace in your output. - -2007-09-24 (lbayuk) - * Code cleanup: Fix ternary operator misuse. This doesn't change - behavior, but it was annoying me so I fixed it. - Replaced all cases of code like this: $a = ($a > $b) ? $b : $a - With just: if ($a > $b) $a = $b - - * Fix Makefile 'release' target to set owner/group when creating - the tar file. This avoids having to run it as root, but it needs - GNU tar to work. - -2007-09-08 (lbayuk) - * Fix for bug 1790441: Removed the PHPlot quasi-destructor function and - the register_shutdown_function() call which arranged for it to be used. - This was preventing release of memory when a PHPlot object was unset, - because the registered shutdown function held a reference to it. - So rather than improving memory use, it had the opposite effect. - Note: It is no longer necessary or recommended to use reference - assignment ($plot =& new PHPlot) for PHPlot object creation. - Thanks to annajilly for the thorough analysis, bug report, and fix. - -2007-09-05 (lbayuk) - * Rewrote FormatLabel() to ignore blank label values. Adapted from a - patch and feature request submitted by Gerhard Reithofer (exgerhardr). - Blank labels used to produce an error if the LabelType was set to - 'time', and zero if set to 'data'. Now they are just ignored. This - provides a simple way to have labels only at selected intervals when - using time or data formats. For example, you can have a date/time - label at every 10th data point by setting the labels for the other 9 - to be empty strings. Also: Removed $which_pos values 'plotx' and - 'ploty'. These were unused by PHPlot and this is an internal-only - function so there is no compatibility issue. Removed error checking on - $which_pos for the same reason; the error message used an undefined - variable anyway so it wouldn't have worked. - -2007-08-26 (lbayuk) - * Allow SetLegendStyle colorbox_align argument to be 'none', to suppress - the colorboxes in the legend. - - Fix comment on $legend_text_align: empty means right, not left. - - Rewrote DrawLegend layout code to make it easier to understand. The - result should be within 1 or 2 pixels of the previous size and position. - - * Fixes for bug 1779115: SetLegendWorld() fails on undefined vars - Store the given coordinates and remember that they need to be converted - from world to pixel coordinates, but defer trying to actually convert - them until it is time to draw the legend. This way, there are no - problems with the scale having to being set up first (which is nearly - impossible to do). Made the following changes: - - Changed legend class variables to be uninitialized, and unset (rather - than empty string) means use the defaults. Added a new variable: - $legend_xy_world. If it is set, (legend_x_pos, legend_y_pos) need to - be converted to pixel coords. If it is unset, they are already pixel - coords (or undefined, meaning defaults). - - Changed usage of internal function DrawLegend(): removed all arguments. - X and Y were always the class variables anyway, and now it needs to - also use the new flag to tell it if X and Y are world or pixel coords. - The third argument was unused. - - Removed third, unused, default NULL argument from SetLegendPixels and - SetLegendWorld. - - Changes to DrawLegend to convert x, y coords to pixel coordinates - if they came from SetLegendWorld. Also account for new usage of - the class variables: Test for unset to mean use default. - -2007-08-04 (lbayuk) - * New feature: control legend text and color box alignment. - Adds a new function SetLegendStyle to adjust the alignment of the - text and the color boxes inside the legend. - Based on part of bug 1208054, contributed by David Hernández Sanz. - -2006-12-02 (lbayuk) - * Fixes for bug 1605555: Y Data Labels use wrong font and not formatted. - Use y_label_font (not x_label_font) for Y Data Labels. - Use the formatted value for the label, not the original text. - (This applies to bar charts only, with the new Y data labels.) - - * One fix for bug 1208054: Localization of number format. - If number formatting is enabled with 'data' format type, PHPlot previously - used dot for decimal point and comma for thousands separator, and there - was no way to change it. - - This fix adds a new function: - SetNumberFormat($decimal_point, $thousands_separator) - to set the separators. In addition, if that function is not used, - PHPlot will now try to use locale-dependent separators. If locale - information is not available, it will fall back to the old defaults - of dot and comma. - - Note: This change may have some negative effects. 1) If your locale is - "C" or "Posix", you might not get a thousands separator now by default. - You should be using a more specific locale. 2) If your PHP script is - forcing a specific locale with setlocale(), PHPlot will probably undo - that because it uses setlocale(LC_ALL, '') to import locale information - from the environment. We have to do that, or a locale set through - the environment is ignored. But it will override a manually set locale. - - * Fix for bug 937944: X/Y Tick Counts - PHPlot could draw one too few Y tick marks, and one too many X tick marks. - - Changed the code to stop drawing X (Y) tick marks when the current X (Y) - value exceeds the maximum X (Y) value plus a small fudge factor. The fudge - factor accounts for cumulative error when repeatedly adding a delta to - the X (Y) value. - - Notes: The bug report was writing about Y tick counts only, but X tick - counts can also be wrong. The proposed fix in the bug report does not - work in all cases. - - This fix changes the appearance of many plots which were missing the - top-most Y tick mark. The extra X-tick mark problem is less common. - -===== Released as 5.0rc3 ===== - -2006-11-13 (lbayuk) - * Fix for bug 1437912: x-axis label misalignment [bar charts] - The calculations were redone from scratch. - New control variable 'bar_extra_space', which works in addition to - 'group_frac_width' to control how much extra space is around the bars. - Made bar widths match for 'stackedbars' and 1-bar-per-group 'bars'. - - NOTE: This changes the appearance of charts. bars in 'stackedbars' - will now be thinner, and bars in 'bars' graphs will be thicker. I - saw no reason for them being different before. - - This fix required fixing the positioning on the new bar data labels, - which was off before. The bar data labels will now be centered. - Additional fixes to bar chart data labels: - For negative values, the label will center under the bar. - Fixed X-adjustment to account for shading. - Fixed to not suppress the data label if the value is 0. - - -2006-11-10 (lbayuk) - * Fix for bug 1594457: DrawError text wrap and background fix - Do error image white background correctly, and word-wrap the text. - - * Fix for bug 1594458: Suppress lines or points in 'linepoints' - Don't draw X data labels twice for 'linepoints'. - Allow SetPointShapes value 'none' to suppress points, and allow - SetLineStyles value 'none' to suppress lines. This allows a 'linepoints' - graph to mix lines only, points only, and both on the same graph. - - -2006-11-09 (lbayuk) - * Fixes for bug 1446523: - + Wrong variable name in deprecated SetAxisFontSize() - + Fails to properly handle error if SetDataValues() was never - called, or not called with a data array. - - * Fix for bug 1117122: Pie Chart ignores SetPlotAreaPixels - Don't let DrawGraph recalculate the plot area for pie charts if the - user already set it with SetPlotAreaPixels. - - NOTE: This fix may slightly change the appearance of some pie charts, - whether or not they use SetPlotAreaPixels. - - * Fix for bug 1103992: Wrong max Y calculated for stackedbars - Changes FindDataLimits to calculate max Y correctly. It was counting - the first Y value in each record twice, which is always wrong but - only affected stackedbars because the Y values are summed. - - * Fix for bug 1096199: Wrong error bar colors in DrawDotsError. - Rewrites DrawDotsError to make it work like DrawLinesError to - correctly increment the record and color indexes. - Also fixes uninitialized x_now_pixels. - - * Fix for bug 1096197: No borders on unshaded Draw[Stacked]Bars - Unshaded Bars and StackedBars covered the border with the rectangle. - The fix is to draw the rectangle, then the border. - - NOTE: This fix changes chart appearance. Bars and Stacked Bars - will now get a black border around each bar by default, if you - turn off the 3D-shading. If you want borderless, unshaded bars - you need to use SetDataBorderColors to set the data border colors - to be the same as the data colors. - - * Fix for bug 1333164: Negative data values, if string variables, result - in unfilled bars. The problem was a string-to-string compare of a - negative number with the empty string x_axis_position. Fixed by - initializing x_axis_y_pixels to 0 if SetXAxisPosition was not used. - - -2005-04-17 (afan) - * Fix for bug [ 1161072 ] SetInputFile warning, background overwrite - - * Bug 1182672 fixed - -2005-04-15 (afan) - * fix for bug: [ 1182666 ] Y Auto-scale rounds in wrong direction - - * Fix for bugs 1144644 TrueType font path problems and 1106328 TTF - path/filename inconsistency - - * Fix Bug: [ 1117120 ] X Title sizing uses Y Title font height - -2005-04-13 (afan) - * Error in SetLineStyles() - does not accept an array argument - - -2005-03-29 (afan) - * Small typo fixed in SetYDataLabelPos - - * Update SetDataLabelPos: For past compatibility we accept plotleft, - ...but pass it to SetTickLabelPos - -2005-03-26 (afan) - * Change to line 3802: data lables now work with multiple bars with *$idx - -2005-03-25 (afan) - * Added Function DrawDataLabels to put data labels in world coords, - added call from DrawBars and modified SetYDataLabelPos to flag - whether or not to call DrawDataLabels. - -2005-01-20 (migueldb) - * Many bugfixes reported and solved by L. J. Bayuk. Thanks! - + fixed bug #1096190 - + FindDataLimits(): fixed bug #1096192 - + CalcTranslation(): fixed bug #1101317 - + DrawImageBorder(): fixed bug 1096200 - + DrawXDataLabel(): fixed bug 1099879 - + DrawDots(): fixed bug #1096194 - -===== Released as 5.0rc2 ===== - -2004-10-24 (migueldb) - * array_merge_php4(): added to cope with the bug introduced by - the change in array_merge() from PHP4 to PHP5 (I haven't verified this) - * Fixed some divisions by zero, thanks to an old bug report. - -2004-09-09 (migueldb) - * SetPointSize(): deprecated - * SetPointSizes(): added as replacement for SetPointSize(). - Now able to set point sizes on a per line basis. - * SetPointShape(): deprecated. - * SetPointShapes(): added as replacement for SetPointShape(). - Now able to set point shape on a per line basis. - * DrawDot(): now needs record number to decide which dot shape and - size to draw. - * CalcMargins(): dirty fix for x data label placing. - * tile_img(): fixed tile placement. - -2004-06-14 (migueldb) - * SetXTickLabelPos() and others: more on the bug reported by Jo Demol. - * Fixed bug reported by Jo Demol. - -2004-05-11 (migueldb) - * SetBgImage(): added. - * SetPlotAreaBgImage(): added. - * SetInputFile(): deprecated. - * DrawBackground(): now accepts images as backgrounds. - * DrawPlotAreaBackground(): now accepts images as backgrounds. - * tile_img(): internal method added. - -.......... -Editor's Note: For older changes to PHPlot, please see the CVS logs. diff --git a/gosa-core/include/phplot-5.1.2/HorizontalBars.txt b/gosa-core/include/phplot-5.1.2/HorizontalBars.txt deleted file mode 100644 index 9c2fadbb9..000000000 --- a/gosa-core/include/phplot-5.1.2/HorizontalBars.txt +++ /dev/null @@ -1,243 +0,0 @@ -phplot/HorizontalBars - Documentation for an experimental new plot type -Last updated for PHPlot-5.1.2 on 2010-06-26 -The project home page is http://sourceforge.net/projects/phplot/ ------------------------------------------------------------------------------ -Overview: - -This file documents a new plot type, Horizontal Bars. This was added to -PHPlot in version 5.1.2 as an experimental feature. - - NOTICE: - - This new plot type is experimental. This means anything about this - may change in future releases, in ways that might be incompatible - with the current implementation, or the new plot type might even - be removed completely. The new plot type is not yet documented in - the PHPlot Reference Manual. This text file is the only documentation. - -Feedback on this feature is welcome. Please use the "help & discussion" -forum at http://sourceforge.net/projects/phplot/ - ------------------------------------------------------------------------------ -Usage: - -In a horizontal bar chart, the X axis and Y axis are oriented the same as -in other PHPlot plot types: X axis is horizontal, increasing towards the -right, and Y axis is vertical, increasing towards the top. - - Y - ^ - | - |============== - | - |===== - | - |========= - | - +---------------------> X - -To make a horizontal bar chart, use the same plot type as vertical bar -charts ('bars'), but use the new data type 'text-data-yx'. The new data -type indicates your data array has a different representation, mapping Y -values to X values (instead of X values to Y values). - -For a normal (vertical) bar chart, the data array has type 'text-data' and -looks like this: - $data = array( array('Label1', Y11, Y12, ...), - array('Label2', Y21, Y22, ...), - ...); -Each entry (row) in the data array represents one group of bars. Each group -has a label and one or more Y values. The X values are implicit: the first -row has the first X value, the second row has the second X value, etc. - -For the new horizontal bar charts, the data array has the new type -'text-data-yx' and looks like this: - $data = array( array('Label1', X11, X12, ...), - array('Label2', X21, X22, ...), - ...); -Each entry (row) in the data array represents one group of bars. Each group -has a label and one or more X values. The Y values are implicit: the first -row has the first Y value, the second row has the second Y value, etc. - -As you can see, a vertical bar chart can be changed to a horizontal bar -chart simply by changing the data type passed to SetDataType(). The data -array itself does not change. Other issues with horizontal bar charts are -discussed below. - -This complete script makes a very simple horizontal bar chart: - SetDataValues(array(array('A', 10, 25), array('B', 30, 5))); - $p->SetDataType('text-data-yx'); - $p->SetPlotType('bars'); - $p->DrawGraph(); - -Note that the bars in a horizontal bar chart are ordered from bottom to top -(that is, increasing Y values). In the example above, the "A" label bar -group is drawn below the "B" label bar group. If you need bars ordered from -top to bottom, you will have to change your data array accordingly. - ------------------------------------------------------------------------------ -Ticks and Labels: - -Since the X axis and Y axis do not change positions for horizontal bar -charts, the label and tick controls still refer to the X and Y axis. -However, the independent values are now Y, and the dependent values are -now X. Also, the label strings in your data array are plotted along the Y -axis for horizontal bar charts, rather than along the X axis for regular -bar charts. - -To control the data labels positions, use SetYDataLabelPos(). New option -values have been added to this function, which was previously used only to -position bar chart value labels with the options 'plotin', 'plotstack', or -'none'. With horizontal bar charts, SetYDataLabelPos() positions the -regular data labels that go along the Y axis. The new option values are -'plotleft', 'plotright', or 'both'. - 'plotleft' : Draw data labels along the left side of the plot area. - 'plotright' : Draw data labels along the right side of the plot area. - 'both' : Draw data labels along both left and right sides. - 'none' : Do not draw data labels. - -For bar charts, it makes no sense to have ticks or tick labels along the -independent axis. This is the Y axis for horizontal bar charts. Therefore, -you should use SetYTickPos('none') to turn off the tick marks on the Y -axis. You do not normally need to use SetYTickLabelPos('none') to turn off -the tick labels along the Y axis, since PHPlot will do this automatically -if your data array has labels. - -To control the presentation of the data labels with horizontal bar charts, -use the correct functions that refer to the Y data labels, not X data -labels as with vertical bar charts. - - SetYDataLabelAngle() or SetYLabelAngle() - Set angle of data label text. Default is 0 degrees. - - SetYDataLabelType() or SetYLabelType() - Select the type of formatting for the data labels. - - SetFont(), SetFontGD(), or SetFontTTF() - Use the element name 'y_label' for the data labels. - -Note that the PHPlot Reference Manual currently says the Y Data Label -functions are only for bar chart data value labels (see Data Value Labels -below regarding this term). That information is out of date. These -functions are now also used for data labels in horizontal bar charts. - ------------------------------------------------------------------------------ -Grid: - -For horizontal bar charts, the X grid lines default on, and the Y grid lines -default off. (This is the opposite of normal bar charts, where the X grid -lines default off, and the Y grid lines default on.) - ------------------------------------------------------------------------------ -Y Axis Position: - -PHPlot uses a different default for the X axis and the Y axis positions. -This affects horizontal bar charts if you have any data values which are -less than zero. The X axis is normally positioned at Y=0, and the Y axis -is normally positioned at the left side of the plot. - -If you have both positive and negative values in your data array, both -vertical and horizontal bar charts will draw the bars away from the zero -value. For vertical bar charts, the X axis will be drawn at that zero value -(perhaps in the middle of the plot), with bars going up and down from -there. But for horizontal bar charts, the Y axis will by default remain at -the left edge of the plot; the bars will start from the X=0 value -(somewhere in the middle of the plot area) and go left and right from -there. In this situation, you might want to use SetYAxisPosition(0) to -force the Y axis to be at X=0. - ------------------------------------------------------------------------------ -Scaling: - -You can use SetPlotAreaWorld() to explicitly set any or all of the 4 limits -of the plot area. Any limits you do not provide will be calculated for you. -The algorithm is due for replacement, but it will now apply the same -calculations to Y and X values in horizontal bar charts as it currently -applies to X and Y (respectively) in vertical bar charts. That is, the -range for the independent variable will be calculated to contain and center -the bar groups, and the range for the dependent variable will include and -usually exceed the actual data range. - -The example under Usage above will produce an auto-calculated Y range of 4 -to 33, with the X range set to center the two bar groups. If you change -'text-data-yx' to 'text-data', you will get a vertical bar chart with the -same automatic range. - ------------------------------------------------------------------------------ -Data Value Labels: - -Data Value Labels are not yet available with horizontal bar charts. These -are the text labels within the plot that identify the data value just above -the bars. (See Example 5.19 "Bar Chart with Data Labels" in the manual.) - -Note: Data Value Labels are currently referred to in the manual as Y Data -Labels. If horizontal bars are accepted and documented in the manual, this -will be changed to call them 'Data Value Labels'. This is necessary to -avoid confusion with X Data Labels and Y Data Labels. - ------------------------------------------------------------------------------ -Other Plot Types Not Available: - -There is currently no corresponding horizontal analog for plot type -stackedbars, nor are there any other horizontal plot types at this time. -Using data type 'text-data-yx' with other plot types will fail. -(Starting with 5.1.2, PHPlot always checks that the selected data type -is supported for the selected plot type.) - ------------------------------------------------------------------------------ -Implementation Notes: - -The following is a summary of the changes made to PHPlot to implement -horizontal bar charts. - -1) Do not initialize y_tick_label_pos or y_data_label_pos. The defaults -have to be dynamically calculated for horizontal bar charts, so tick labels -can be suppressed. (This was already being done for X labels.) Existing -internal function CheckLabels() was extended to do this for Y also. - -2) Do not initialize the X and Y grid setting variables. The defaults have -to be dynamically calculated because they differ with swapped data arrays. -New internal function CalcGridSettings() does this. - -3) SetYDataLabelPos() accepts the new arguments plotleft, plotright, and -both. Old compatibility code that passed these values to SetYTickLabelPos() -has been removed. - -4) SetDataType() accepts a new value: 'text-data-yx'. - -5) FindDataLimits() was changed to properly calculate minimum and maximum -values from text-data-yx data arrays. The arrays data_miny and data_maxy -were renamed to just data_min and data_max, since they now describe limits -of either X or Y values, depending on the data type. - -6) Changes were made to CalcMargins() to account for the labels in the data -array being drawn on the Y axis instead of X axis, in the text-data-yx -case. - -7) CalcPlotAreaWorld() is extended to calculate defaulted plot ranges -correctly for the swapped X/Y case. The algorithm is the same (and due for -replacement). It applies a fixed range to Y and an extended range to X. It -is also ready for possible future expansion to include swapped X/Y plots -with explicit Y values. - -8) Changed CalcBarWidths() to use either the plot area width or height, -depending on the bar directions, when calculating the bar widths. - -9) Extended CalcMaxDataLabelSize() to work with both X and Y labels. -Before, it returned the maximum height of the data labels. Now it can -instead return the maximum width of the data labels; this is used for -horizontal bar charts. It also has to pick the proper font, angle, and -format code for X or Y. - -10) New internal function DrawYDataLabel() to draw data labels for -horizontal bar charts. - -11) New internal function DrawHorizBars() draws the horizontal bar chart. - -12) DrawGraph() now decides to draw a bar or horizontal bar chart based on -the data type (text-data or text-data-yx). - ------------------------------------------------------------------------------ diff --git a/gosa-core/include/phplot-5.1.2/NEWS.txt b/gosa-core/include/phplot-5.1.2/NEWS.txt deleted file mode 100644 index e5fdb2496..000000000 --- a/gosa-core/include/phplot-5.1.2/NEWS.txt +++ /dev/null @@ -1,814 +0,0 @@ -This is the NEWS file for PHPlot, with release documentation. -The project web site is http://sourceforge.net/projects/phplot/ -The project home page is http://phplot.sourceforge.net/ -Refer the the ChangeLog file for detailed source changes. ------------------------------------------------------------------------------ - -2010-06-29 Release 5.1.2 - -Overview: - -This is the current stable release of PHPlot. Truecolor image support is no -longer considered 'experimental', and is now documented in the reference -manual. There is a new experimental feature for horizontal bar charts. This -release also contains a bug fix and new feature. - - -Cautions and Important Notes: - -The advisory against using PHP-5.3.2 or PHP-5.2.13 with PHPlot if you use -TrueType fonts (TTF) continues. See the item below for PHPlot-5.1.1. The -good news is that this has been fixed by the PHP Team and will be in the -next releases. - -Compatibility of data type and plot type are now checked completely. If -you used an incorrect data type with certain plot types, your script may no -longer work until you fix the data type. Specifically, the area, squared, -and thinbarline plot types failed to check the data type they received, and -treated anything other than 'data-data' as 'text-data'. If you have a -squared plot with data type 'data-data-error', for example (which is not -supposed to work), it did produce a plot, but will now result in an error. - -The addition of horizontal bar charts should not impact any existing plot, -with one small exception. The function SetYDataLabelPos() used to accept -some additional, undocumented options (plotleft, plotright, both, yaxis) -and pass these through to SetYTickLabelPos() "for compatibility". It no -longer does so, as some of those are now used for horizontal bar chart -labels. To position Y tick labels, use only SetYTickLabelPos(). - - -New features in 5.1.2: - -#3002606 "Add to plot and image border options": - SetPlotBorderType() now accepts 'right', 'top', and 'bottom', as well - as an array of options. So you can now control exactly which of the 4 - border sides will be drawn. - SetImageBorderType() now accepts 'solid' as a choice. This will use the - actual color set with SetImageBorderColor(), rather than the darker - shade as type 'plain' does (which may have been a bug). - SetImageBorderWidth() is a new function that sets the width of the image - border. The defaults are the same as the fixed values used before: 1 - pixel for plain, 2 pixels for raised. The image border width is now - accounted for in margin calculations, if it is greater than 2 (to make - sure existing plots will not change). - -#2885930 "Horizontal Bars": - Horizontal bar charts are implemented, as an experimental feature. - 'Experimental' means they are not yet documented in the reference manual, - and subject to change or removal. - Refer to the text file HorizontalBars.txt for details. - -#2947679 (follow-up) "Support for alpha blending/Truecolor": - Truecolor support is now documented in the Reference Manual. The interim - documentation file Truecolor.txt has been removed. Alpha channel - specification now works with both constructors and both image types. This - fixes an issue if the base constructor was used with a truecolor background - image. (In PHPlot-5.1.1, the result would be a truecolor image, but the - alpha channel features were not available.) - - -Bug Fixed in 5.1.2: - -#3010116 "Bad rendering of title in multi-plot image when using TTF": - Make sure the main title is drawn only once, to avoid bad rendering of - TTF titles with multiple plots due to anti-aliasing. - ------------------------------------------------------------------------------ - -2010-04-04 Release 5.1.1 - -Overview: - -This is the current stable release of PHPlot. This release adds truecolor -image support as an experimental feature, fixes a number of bugs and adds -a few new features. - -The PHPlot reference manual has been updated to match this release. The -manual is available as a separate download from Sourceforge. The manual is -also available for on-line viewing from the project home page. - -See the ChangeLog file in the release for more about changes and bug fixes. - - -Cautions and Important Notes: - -Avoid using PHP-5.3.2 or PHP-5.2.13 with PHPlot if you use TrueType fonts -(TTF). Some new bugs were introduced in those releases that adversely -affects accurate positioning and rendering of TrueType font text. - - -New features in 5.1.1: - -#2947679 "Support for alpha blending/Truecolor": - PHPlot can now produce truecolor images, with alpha blending of colors and - other effects. This is considered an experimental feature, meaning it is - not yet documented in the PHPlot Reference Manual, and subject to change. - Refer to the text file Truecolor.txt included in the PHPlot release for - information on using truecolor. - Two drawing changes were made to improve plot appearance with Truecolor: - + Filled dots (in points & linespoints plots) are now drawn better. This - also makes them look rounder with regular (non-Truecolor) plots. - + Area plots have the areas filled without overlapping each area down to - the Y axis. This was needed to fix problems with alpha blending, and - should have no effect on non-Truecolor plots. - -#2973995 "Add y-Data to Stackedbars": - You can now have Y Data Labels with 'stackedbars' plots. These label the Y - values (incremental and total) for each bar. Refer to the reference manual - page for SetYDataLabelPos(). - - -Bug Fixes in 5.1.1: - -#2976735 "Improvements and fixes for 'area' plots": - Moving X axis works; handle Y<0 better; new 'stackedarea' plot type is a - variation on 'area' with the data represented differently. - -#2974639 "Stacked bars plot breaks with X axis != 0": - Moving X axis works. - -#2963757 "point_counts undefined error in 5.1.0": - Fixed an error introduced in PHPlot-5.1.0 when point size and shape arrays - were set to the same size. - -#2938219 "Bars go in wrong direction": - For bar charts with all Y<0, bars will still be drawn down even if Y=0 is - not in range. - ------------------------------------------------------------------------------ - -2009-12-24 Release 5.1.0 - -Overview: - -This is the current stable release of PHPlot. This release fixes a number of -bugs and adds some new features. Some of the changes in this release can -alter the appearance of plots, so be sure to review the information in this -NEWS file and test this release with your application. - -The PHPlot reference manual has been updated to match this release. The -manual is available as a separate download from Sourceforge. The manual is -also available for on-line viewing from the project home page. - -See the ChangeLog file in the release for more about changes and bug fixes. - - -New features in 5.1.0: - -+ A new "contrib" directory has been added for useful add-ons. - This currently contains: - * prune_labels : Control data label density on X axis. - * color_range : Define a gradient map for data colors. - -+ Feature Request 2899921 "Allow different format for data and tick labels" - Text angle and format can now be controlled separately for data labels. - -+ Locale loading override - New variable locale_override stops PHPlot from getting locale from system. - -+ Translating Coordinates - New function GetDeviceXY() to translate world to device coordinates. - -+ New drawing callback - New callback 'draw_all', called after all drawing is done. - The manual now contains an example of using this new callback and - the new GetDeviceXY() function to annotate a plot. - - -Bug Fixes in 5.1.0: - -#2914403 "Pie + X/Y titles: Undefined property error" - X/Y titles are now properly ignored for pie charts. - -#2908256 "Error: array_sum() should be an array" (drupal) -#2916864 "Should at least print legend on pie charts with empty data" - Pie charts with invalid data (no Y values > 0) now make an empty plot. - -#2906436 "Fixes for X Tick Labels vs X Data Labels" - Smarter determination of whether to do Tick labels, Data labels, or both. - -#2900914 "Problem with display of 0 on Y axis" - Fixed rounding error that could produce something like Y=8.12345E-16. - -#2886365 "PHP 5 patch" (Declare all functions and variables in PHP5 style) - Most internal PHPlot member functions now have "protected" visibility. - -#2839547 "SetImageBorderType('none') - You can use SetImageBorderType('none') to turn the image border back off. - -#1795972 "Fix default point shapes" - We now have 20 (vs 10) point shapes, with 10 (vs 1) used by default. - -#1795971 "Fix default data colors" - We now have 16 (vs 8) default data colors, no duplicates, all visible. - - -Visible Changes and Possible Incompatibilities: - -+ PHP5 visibility changes (Bug #2886365) -Details: Most internal PHPlot member functions now have visibility - 'protected', rather than all being public. All member variables are - still 'public'. - -Reason for the change: Use the recommended PHP5 syntax, better OO style. - -Compatibility: If you were calling a PHPlot internal function that got - changed to 'protected', this will break. Please report this. - - -+ Fix default point shapes (Bug 1795972) -Details: We now have 20 (vs 10) point shapes available, and by default we - have 10 (vs 1) different shapes in use. The default size is now 6 pixels - for all point shapes. - -Reason for the changes: Using different shapes helps distinguish the data - sets. The existing 10 defined shapes were not enough, since some of them - are not centered over the points, too small, or otherwise hard to see. - The code to synchronize the point shape and size arrays was broken, and - some dubious code to adjust sizes to even numbers needed to be fixed. - -Compatibility (1): If you have a points or linepoints plot with more than - one dataset, and you did not use SetPointShapes() to configure the - shapes, them your plot will change from using a diamond for all data - sets to using different shapes for up to 10 data sets. - -Compatibility (2): Fixing the point size/point shape array size bug may - slightly change the size of some shapes, but it now works the way it - was documented and supposed to work. - -+ Fix default data colors (Bug 1795971) -Details: Defined a new set of 16 default data colors. The colors are - different and contrast well against the default white background. - The first 4 colors were not changed. - -Reason for the change: The default 8 data colors included two instances - of orange, and one color which was invisible on a white background. - -Compatibility: Colors will change on any plot with more than 4 data sets - where you did not use SetDataColors() to set your own data colors. - -+ Re-used old function SetXDataLabelAngle() -Details: SetXDataLabelAngle() now does something different. - -Reason for the change: This name was needed for a new function, to set the - angle for the X Data Labels. The old use of this function was not - documented, and marked "deprecated" in the code since around 2003-12-07. - -Compatibility: If you are still using SetXDataLabelAngle() to set both Tick - and Data label angles, you need to use SetXLabelAngle() instead. - -+ Separate controls for tick and data labels (Feature Request 2899921) -Details: New functions SetXDataLabelAngle(), SetYDataLabelAngle(), - SetXDataLabelType(), and SetYDataLabelType() to allow separate control - over the angle and format of data labels, versus tick labels. - -Reason for the change: Allow Data Labels to use different formatting and - angle compared to Tick Labels. - -Compatibility: The default behavior has been set up such that there should - be no compatibility issues. For example: - Old behavior: SetXLabelType() sets the type for both tick and data labels. - New behavior: SetXLabelType() sets the type for tick labels and the - default type for data labels. SetXDataLabelType() sets the type for - data labels (overrides SetXLabelType). - -+ X Tick Labels vs X Data Labels (Bug 2906436) -Details: Regarding SetXTickLabelPos() and SetXDataLabelPos(): If only one - of them is called, the behavior is unchanged (only that label type will - be displayed). If both are called: Do exactly what was requested. If - neither was called: display only data labels if any data labels are - non-empty, else display only tick labels. - -Reason for the change: 1) Fix the long-standing problem behavior that by - default PHPlot overlays tick and data labels below the X axis. 2) Fix - order dependency between setting the position of tick and data labels. - 3) Prepare for future extension of data labels, and allow both tick - and data labels to be on if the programmer enables both. - -Compatibility: There are some cases where your plot will change. - (a) Calls neither SetXDataLabelPos() nor SetXTickLabelPos(): - Old behavior: Both tick and data labels displayed, possibly overlaid. - New behavior: If there are any non-blank data labels, then show only - the data labels, not the tick labels. Otherwise, show tick labels. - - (b) Calls both SetXDataLabelPos() and SetXTickLabelPos(), with other than - 'none' for each position: - Old behavior: The latter call was effective; earlier one ignored. - New behavior: Independent of order, both calls are effective. - ------------------------------------------------------------------------------ - -2009-06-14 Release 5.0.7 - -Overview: - -This is the current stable release of PHPlot. The release adds one new -feature, fixes a few bugs, and changes the license under which PHPlot -is released. - -The PHPlot reference manual has been updated to match this release. The -manual is available as a separate download from Sourceforge. The manual is -also now available for on-line viewing at http://phplot.sourceforge.net - -See the ChangeLog file for more about changes and bug fixes. - - -Licensing: - -PHPlot is now released on the terms of the GNU Lesser General Public -License, version 2.1. (Previous versions of PHPlot were released under -a dual "PHP/GPL" license.) The licensing change was authorized by the -original author and copyright holder of PHPlot. - - -New feature in 5.0.7: - -+ Plot area margins can now be partially specified, using either - SetMarginsPixels or SetPlotAreaPixels. In previous releases of - PHPlot you had to either specify all 4 margins or none. - Credit to adoll for this feature. - - -Visible Changes and Possible Incompatibilities: - -+ Y data range can change: - As a result of the bug fixes in this release, automatically-calculated - Y data ranges can change. If you have missing Y values in your data, - and you let PHPlot calculate the Y data range (that is, you do not - call SetPlotAreaWorld with a Ymin value), then the lower limit for Y - can change. If you have a plot with data-data-error data type, different - error values for different points, and let PHPlot calculate the Y data - range, then either Y limit can change. - - -Bug Fixes in 5.0.7: - - -+ Fix for bug 2803900: SetRGBArray('large') does not work: - Corrected an array name usage problem. You can now select the large - color map. Also PHPlot no longer overrides use of the PHP include - path when loading the large color map, and now reports an error if the - file is needed and not found. - -+ Fix for bug 2791502 "Error plots treat missing Y values as 0": - Missing Y values now with with data-data-error plots. - -+ Fix for bug 2792860 "Wrong DataLabelLines with missing Y": - Data label lines are now suppressed at missing Y values. - -+ Fix for bug 2786350 "Missing Y data results in bad auto-range": - Missing Y values are now ignored when calculating the Y data range. - Bug report and analysis by mrten. - -+ Fix for bug 2786354 "Incorrect auto-range for data-data-error": - The Y data range is now correctly calculated for data-data-error plots - when the error values differ from point to point. - - ------------------------------------------------------------------------------ - -2009-01-20 Release 5.0.6 - -Overview: - -This is the current stable release of PHPlot. The purpose of this release -is to fix additional problems with text spacing and positioning, and -introduce some minor new features. - -The PHPlot reference manual has been updated to match this release. The -manual is available as a separate download from Sourceforge. The manual is -also now available for on-line viewing at http://phplot.sourceforge.net - - -New features in 5.0.6: - -+ Allow mixing GD and TrueType font text on the same plot - You can use the new method functions SetFontGD() and SetFontTTF() to - select a font and font type for text element (labels, titles, etc.) For - example, you can have TrueType plot titles, and GD-fixed font labels. - SetUseTTF() now sets the default text type, TTF or GD. This is fully - backward compatible. - -+ Extended label formatting - See the reference manual for more information on these. - - New label formatting types are added: 'printf' (using a user-defined - format), and 'custom' (using a callback function). - - For 'data' type formatting, a prefix and suffix can be added. (PHPlot - previously had an undocumented suffix for 'data' type, which still - works.) - - For 'time' formatting, the format can now be specified in the same function - call rather than using SetXTimeFormat and SetYTimeFormat. - - For 'data' formatting, the precision can now be specified in the same - function call, rather than using SetPrecisionX and SetPrecisionY. - -+ Better control over line spacing in multi-line labels - - Line spacing can now be set separately for each text element using an - additional argument to SetFont, SetFontGD, and SetFontTTF. The overall - SetLineSpacing() value is the default for each text element that does not - have a specific line spacing set. - - PHPlot now interprets the value set for line spacing as the number of - pixels only for GD text. For TrueType text, it is a scale factor for the - font's built-in line spacing for TrueType text. The equation used is: - interline_spacing = line_spacing * font_natural_spacing / 6 - where line_spacing is either the global value set with SetLineSpacing - or a more specific value set with SetFont(), and font_natural_spacing - is the amount of space between lines built-in to the TrueType font. The - factor 6 should really be 4 (since PHPlot always used 4 as the default - line_spacing, this would give the natural font spacing by default). But - the text is too widely spaced with this value, and 6 was chosen to be - more compatible for typical font sizes. - -Visible Changes and Possible Incompatibilities: - -+ Line spacing - Multi-line TrueType titles and labels will have different inter-line - spacing. Since the text size affects the margin and plot area sizes, - this results in slightly different sized features on any plot with - multi-line TrueType text. - Previous versions of PHPlot used a default 4 pixels for inter-line - spacing of multi-line TrueType text, regardless of the font size. - PHPlot now uses the 'natural' font inter-line spacing, adjusted by a line - spacing parameter (per text type, with a global default). - - The same change can also increase the size of the legend box slightly. - -+ Internal changes were made to the way font information is stored. Anything - that directly references PHPlot internals regarding fonts will break. Usage - also changed for the internal functions to size and draw text (ProcessText*, - SizeText*) due to font data storage changes. - -+ Changes were made to internal class variables used to store label - formatting information. Anything relying on these internals may break. - - -Bug Fixes in 5.0.6: - -#1932571: Data-Data Plot fails with same X values - PHPlot will no longer hang if all X values are the same. But this is - interim fix to force the X range to 1 to prevent the hang. Eventually, - smarter automatic range code will handle this better. - Credit to andyl for finding this. - -#1891636: Misaligned TTF X Labels - PHPlot will now correctly line-up TrueType labels along the X axis. There - were small but very noticeable errors before, when the text had descenders - or lines with all short letters. - - ------------------------------------------------------------------------------ - -2008-01-13 Released 5.0.5 - -Overview: - -This is the current stable release of PHPlot. The emphasis of this release -is to improve text positioning, margin calculation, and error handling. - -Although this is considered a stable release, it has a large amount -of changed code compared to the previous release 5.0.4. Two of the more -complex components of PHPlot - text and margin calculations - were mostly -re-written in this release. You are advised to carefully test your own -applications with PHPlot-5.0.5 to see how your plots look. Refer to the -README.txt file included in the release for information on reporting problems. - -Starting with this release, PHPlot no longer supports PHP4, since the PHP -group officially declared end-of-life for PHP4 as of 31 December 2007. -PHPlot-5.0.5 was tested only with PHP-5.2.5 and we are unlikely to address -any issues using PHPlot with older versions of PHP. - -The PHPlot reference manual has been updated to match this release. The -manual is available as a separate download from Sourceforge. The manual is -now also now available for on-line viewing at http://phplot.sourceforge.net - -The callback feature added in 5.0.4 is now documented in the reference -manual. It is still considered experimental and subject to change, however. - - - -Visible Changes and Possible Incompatibilities: - -+ Dropped support for PHP4. - -+ Eliminated remaining order-dependent behavior related to margins and -text. PHPlot should now do nothing at all, except record parameters, until -you draw the graph with DrawGraph. I believe this was always the intended -behavior of PHPlot, but over time perhaps various pre-calculations and -dependencies crept in. Fixing this simplifies processing and should lead to -more consistent behavior. - -+ The rewritten margin calculation code now uses actual sizes of all tick -and data labels and tick marks, rather than guesses. Margins collapse to -remove unused elements, but a minimum margin (currently fixed at 15 pixels) -is applied so the plot edges don't get to close to the image edges. The -result is that most graphs with auto-calculated margins will change in -appearance. It most cases, the margins get slightly smaller. In other -cases, earlier releases mis-calculated the margins, so this release will -produce much neater margins. - -+ The X and Y titles are now offset out from the plot area, not in from the -image area. For auto-calculated margins this should not make any -difference, but if you use SetMarginsPixels or SetPlotAreaPixels to set -larger margins, the axis titles will move in closer to the plot with this -release. - -+ Changes were made to PHPlot internals, including removal of some class -variables and functions, and addition of new variables and functions. -These are documented in the ChangeLog. Relying on any internal variables -or functions in an application using PHPlot is unwise. The following -internal functions were removed: - SetImageArea() DrawDotSeries() DrawLineSeries() CalcXHeights() - CalcYWidths() DrawLabels() InitImage() DrawDashedLine() - These were marked 'deprecated', were undocumented and unmaintained. - TTFBBoxSize() - This was replaced with SizeText(). - -+ Line spacing set with SetLineSpacing() now affects TTF text as well as -GD text. Previously, it only affected GD text. The default line spacing -happens to be usable for TTF text. - -+ Changes were made to error handling. PHPlot will now trigger a user-level -error after producing an error image, instead of exiting. If no error -handler has been set, it will exit, as before. But now the error message -should also get logged, or written to the standard error stream, depending -on the SAPI in use. You can now establish an error handler to catch most -PHPlot errors and do some cleanup before exit. - -+ PHPlot no longer accepts some invalid option values (such as a substring -of a valid value, or empty strings) passed to functions. If your -application aborts in CheckOption with PHPlot-5.0.5 but 'worked' with -previous releases, them you were probably using an invalid option value. - - - -Bug Fixes in 5.0.5: - -#945439: x_tick_label_height not set correctly - Exact sizes of labels are now used to calculate margins. - -#1813070: Bad position for multi-line TrueType text - Fixed as part of text functions rewrite. Use correct basepoint - (lower left of each line) when positioning text lines. - -#1813071: Wrong title height for multi-line TTF text - Fixed as part of text functions rewrite: calculate height of - multi-line text correctly. Also now uses the line-spacing setting. - -#1813474: DrawText alignment arguments wrong - Fixed so 'top' and 'bottom' now have the usual meaning: top means - align top of text with reference, bottom means align bottom of text. - This was switched before. Changed every internal caller to compensate. - -#1816844: Fix order dependency for setting titles - Defer processing of title strings until DrawGraph(), - so it doesn't matter if fonts, etc. are set before or after. - -#1819668: Horiz. align multi-line text: GD vs TTF - The text functions were rewritten to draw TTF text line-by-line, - like GD text, and correctly align each line. - -#1823774: Default Font Path and Error Message - Error handling has been improved to make sure a message is logged, in - addition to the error image, and use error_trigger rather than exit. - -#1826513: FIXME in DrawLegend: Max label length - The actual size needed for legend text is now used. - -#1827263: Spoiled up pie-chart if $val is close to zero - Fixed by skipping over any segment that rounds to 0 degrees of - arc. (The GD function uses integer angles only, and 0 degrees - means draw a complete circle.) - -#1836528: Insufficient checking of parameter values - Rewrote validator function to reject improper parameter values. - -#1843012: Make margins, drawing consistent - Margin code logic was rewritten and checked for consistency. - -#1856207: Margin error with 'xaxis'/'yaxis' position - Margin space is now allocated for ticks and labels if their position - is 'xaxis' or 'yaxis' and the axis is at the plot edge. This is not - a perfect fix (the axis could be close but not at the edge). - - ------------------------------------------------------------------------------ - -2007-10-20 Released 5.0.4 - -Overview: - -This is the latest stable release of PHPlot. We are abandoning the 'rc' -version naming style, because we don't consider these last releases -'release candidate' versions. As we continue to make changes to PHPlot, -we are not converging toward a final "5.0" release, however we do consider -these releases stable and complete enough for production use. - -This release fixes a number of problems and introduces a few new features. - -The PHPlot reference manual has also been updated to match this release. -New material has been added documenting some of the PHPlot internals. -The manual is available as a separate download from Sourceforge. - - -Code Cleanup: - -Some code cleanup is going in to this release. It is hoped that these -changes will not impact any existing scripts using PHPlot, but will make -the PHPlot code itself easier to understand and maintain. - -PHPlot now avoids making changes outside its own class definition. There -are no longer any functions defined outside the class, nor any constants. -Three constants (MINY MAXY TOTY) were removed, and 2 functions were removed -(see Visible Changes below). Also PHPlot no longer sets the PHP error -reporting level to E_ALL. Although we highly recommend setting error -reporting to E_ALL in your php.ini file or scripts, it is not right for -PHPlot to assume that you want it. - - -Visible Changes and Possible Incompatibilities: - -Arrays containing color and style information are used with several PHPlot -functions to control the plot style array. These functions are: - SetPointShapes, SetPointSizes, SetLineWidths, SetLineStyles, - SetDataColors, SetDataBorderColors, and SetErrorBarColors. -The arrays passed to these functions MUST used sequential integer 0-based -indexes. This is what the PHP manual calls "Usual integer indices (starting -from zero, increasing by one)". This is the type of array you get in PHP by -default if you use array() without specifying key values, or use the -empty-bracket assignment operator to add values onto an array. In previous -versions of PHPlot, some of these functions would also work with -string-indexed or non-sequentially-indexed arrays, but this was not clearly -defined. Starting with PHPlot-5.0.4, only arrays with "usual integer -indices" work, and other array indexes will cause errors. - -Some internal-use-only functions have had their usage changed or been removed. -If you are using functions that are not documented in the PHPlot Function -Reference in the manual, your code may have to be changed. - -As part of the code cleanup, two functions which were defined outside the -PHPlot class were removed: array_pad_array(), and array_merge_php4(). -If your code used these, you need to fix your code. - -The routines which accept a color name, value, or array now check for a valid -color name. If you specify a color name which is not in your current color -table, PHPlot will draw an error and exit. Previously, PHP would report an -index error, continue, and get a 'headers already sent' message. - - -Bug Fixes in 5.0.4: - -#1813021: Miss-positioned right-justified vertical GD text. - Fixed DrawText() to correctly position 90 degree right-justified text - drawn in a fixed GD font. This could be seen with 90 degree Y tick labels. - -#1790441 Removed destructor/shutdown function, and no longer recommend - using reference assignment when creating a PHPlot object. This was - interfering with memory usage. - Credit to annajilly for analysis. - -#1779115 SetLegendWorld() failed because of undefined variables. The - required order dependency was too hard to meet. This is now fixed. - You can now use SetLegendWorld anywhere before DrawGraph. - -#1726810 (feature request, but actually a bug fix) Ignore empty strings - as data labels when doing time or data label formatting. These would - previously produce errors or bad formatting. Now you can omit labels - as needed even with time and data formatting. - Credit to exgerhardr for finding this. - -#1605555 Y data labels used wrong font and not formatted (bar charts only). - -#1208054 Localization of number formatting in 'data' format type. PHPlot - will attempt to format the numbers in a way appropriate to your locale. - You can also force the formatting with the new function SetNumberFormat. - Credit to David Hernández Sanz. - -#937944 X/Y Tick counts: PHPlot could draw one two few Y tick counts, and - one too many X tick counts. This is not a perfect fix, and more work is - needed here, but this fixes an error case in both X and Y values. - - -New Features in 5.0.4: - -New function SetLegendStyle allows control of the alignment of text and - color boxes within the legend. Also allows removing the color boxes. - Based on bug #1208054. - Credit to David Hernández Sanz. - -New function SetNumberFormat. See bug report #1208054 above. - -Callbacks are added. PHPlot can call back your functions while generating the - plot. This is experimental, and documented only in the file "Callbacks". - Credit to annajilly for the idea and design. - ------------------------------------------------------------------------------ - -2006-11-13 Released 5.0rc3 - -Overview: - -This is an interim release. It has been a long time since the previous -release 5.0rc2, and there have been a lot of changes. There are still more -changes likely to go in before we have "5.0", but there are enough for now. - -The PHPlot Reference Manual has also been released, and is available as a -separate download from Sourceforge. PHPlot users and developers are -strongly encouraged to read the manual. - -This release does not include the "doc/" and "examples/" directories of -previous releases. The Reference Manual contains more complete and -up-to-date information and examples, and I am unable to maintain the doc/ -and examples/ files while also maintaining the Reference Manual. If you -need those files, they can be accessed with the Sourceforge web CVS -browser. - - -New Features: - -The emphasis for this release is bug fixing, so there are few new features. - -+ You can now suppress lines or points on individual plots in a linepoints - graph. This feature was added because I needed a graph with several - linepoints lines, but also with a solid line showing an "80% goal". - Use SetPointShapes with the value 'none' in the array to suppress the - point markers for that plot (and only draw the line). - Use SetLineStyles with the value 'none' in the array to suppress the - line for that plot (and only draw the point markers). - [Bug # 1594458] - -+ Bar charts can have data labels above the bar with the value. Turn - these on with SetYDataLabelPos('plotin'). This is somewhat experimental, - since there isn't a lot of room for labels on top of the bars and you - may find the results are not useful. - - -Visible Changes: - -Here are the more significant changes in this release. These are changes -which may affect existing scripts and output from PHPlot. See the -ChangeLog file for information about all changes and bug fixes. - -+ A bug fix on bar chart bar borders results in black borders around the - bars if shading is turned off. The border was previously covered up, - but was supposed to be there. If you need borderless, unshaded bars, - you need to use SetDataBorderColors to make the borders the same colors - as the bars. [Bug # 1096197] - -+ TrueType font pathname handling was fixed. You no longer need to use - SetUseTTF(True). You can either use full paths to the font files with - SetDefaultTTFont() and SetFont(), or you can call SetTTFPath() to point - to a directory of font files, and then use simple font filenames without - paths in SetDefaultTTFont() and SetFont(). - [Bug # 1144644 plus several others] - -+ There have been several fixes regarding automatically calculated ranges - and scales. The result is that you may see less extra space and fewer - tick marks in some cases. - -+ A fix was made to bar and stackedbar graph bar widths in order to get - the X axis labels to properly center. As part of the fix, the bar widths - now match between the two graph types. (Before this fix, the bars were - narrower in bar graphs compared to the same data plotted as a stacked - bar.) As a result, bar graph bars will now be drawn with wider bars, and - stackedbar graph bars will be narrower. You can adjust this with the new - class variable bar_extra_space. [Bug # 1437912] - -+ Dot shapes and sizes were off by 1 or 2 slots in the array of shapes or - sizes. After the fix, you may get different dot shapes or sizes per - plot line. [Bug # 1096194] - - -Testing: - -Since its output is visual (graphics), and it has so many interconnected -modes and options, PHPlot is difficult to test. But at least we are now -trying. I have a collection of PHPlot scripts (currently about 60) and a -script to run through them. The script automatically checks that: - 1) Nothing was written to the standard error stream; - 2) An image file of size greater than 0 was written; - 3) Neither the test script nor PHPlot did exit(). This catches cases - where PHPlot aborts with DrawError(). - -The automated test is an easy way to check for serious regression, but you -really need to inspect the output files to validate PHPlot. This takes a -little time, and it is easy to overlook problems. - -The real issue is test coverage. Just as we can be sure that future -PHPlot releases will pass the test collection, we can also be sure that -future bug reports will be written against untested cases. - --------------------- - -2006-11-08 PHPlot on Sourceforge has a new maintainer: lbayuk - --------------------- - -2004-10-24 Released 5.0rc2 - --------------------- - diff --git a/gosa-core/include/phplot-5.1.2/README.txt b/gosa-core/include/phplot-5.1.2/README.txt deleted file mode 100644 index 03471bfba..000000000 --- a/gosa-core/include/phplot-5.1.2/README.txt +++ /dev/null @@ -1,156 +0,0 @@ -This is the README file for PHPlot -Last updated for PHPlot-5.1.2 on 2010-06-29 -The project web site is http://sourceforge.net/projects/phplot/ -The project home page is http://phplot.sourceforge.net/ ------------------------------------------------------------------------------ - -OVERVIEW: - -PHPlot is a PHP class for creating scientific and business charts. - -The release documentation contains only summary information. For more -complete information, download the PHPlot Reference Manual from the -Sourceforge project web site. You can also view the manual online at -http://phplot.sourceforge.net - -For important changes in this release, see the NEWS.txt file. - - -CONTENTS: - - COPYING . . . . . . . . . . . . LGPL 2.1 License file - ChangeLog . . . . . . . . . . . Lists changes to the sources - HorizontalBars.txt . . . . . . . Experimental feature documentation - NEWS.txt . . . . . . . . . . . . Highlights changes in releases - README.txt . . . . . . . . . . This file - contrib . . . . . . . . . . . . "Contributed" directory, add-ons - phplot.php . . . . . . . . . . The main PHPlot source file - phplot_data.php . . . . . . . . Auxiliary and extended functions - rgb.inc.php . . . . . . . . . . Optional extended color table - -REQUIREMENTS: - -You need a recent version of PHP5. Usually, we recommend you use the latest -stable release, however due to problems with PHP-5.3.2 and PHP-5.2.13 you -are advised to use the previous releases if possible. The problems are -specific to TrueType font (TTF) text. If you are not using TTF text, you -may use PHP-5.3.2 or 5.2.13. (The PHP team already has a fix for this TTF -problem in PHP-5.3.3 development snapshots, so the fix should be in the -next releases PHP-5.3.3 and PHP-5.2.14.) - -This version of PHPlot has been tested with PHP-5.3.1 and PHP-5.2.12 on -Linux, and with PHP-5.3.1 on Windows/XP. The PHPlot Test Suite currently -contains 432 test cases. - -You need the GD extension to PHP either built in to PHP or loaded as a -module. Refer to the PHP documentation for more information - see the -Image Functions chapter in the PHP Manual. We test PHPlot only with the -PHP-supported, bundled GD library. - -If you want to display PHPlot charts on a web site, you need a PHP-enabled -web server. You can also use the PHP CLI interface without a web server. - -PHPlot supports TrueType fonts, but does not include any TrueType font -files. If you want to use TrueType fonts on your charts, you need to have -TrueType support in GD, and some TrueType font files. By default, PHPlot -uses a simple font which is built in to the GD library. - - -INSTALLATION: - -Unpack the distribution. (If you are reading this file, you have probably -already done that.) - -Installation of PHPlot simply involves copying three script files somewhere -your PHP application scripts will be able to find them. The scripts are: - phplot.php - phplot_data.php - rgb.inc.php -(Only phplot.php is necessary for most graphs.) -Make sure the permissions on these files allow the web server to read them. - -The ideal place is a directory outside your web server document area, -and on your PHP include path. You can add to the include path in the PHP -configuration file; consult the PHP manual for details. - - -KNOWN ISSUES: - -Here are some of the problems we know about in PHPlot. See the bug tracker -on the PHPlot project web site for more information. - -#1795969 The automatic range calculation for Y values needs to be rewritten. - This is especially a problem with small offset ranges (e.g. Y=[999:1001]). - You can use SetPlotAreaWorld to set a specific range instead. - -#1605558 Wide/Custom dashed lines don't work well - This is partially a GD issue, partially PHPlot's fault. - -#2919086 Improve tick interval calculations - Tick interval calculations should try for intervals of 1, 2, or 5 times - a power of 10. - -PHP Bugs #51207, #51094, and others: These are PHP bugs, not PHPlot, -on rendering of TrueType font (TTF) text in PHP-5.3.2 and 5.2.13. - - -If you think you found a problem with PHPlot, or want to ask questions or -provide feedback, please use the Help and Discussion forum at - http://sourceforge.net/projects/phplot/ -If you are sure you have found a bug, you can report it on the Bug tracker -at the same web site. There is also a Features Request tracker. - - -TESTING: - -You can test your installation by creating the following two files somewhere -in your web document area. First, the HTML file: - ------------- simpleplot.html ---------------------------- - - -Hello, PHPlot! - - -

PHPlot Test

- - - ---------------------------------------------------------- - -Second, in the same directory, the image file producing PHP script file. -Depending on where you installed phplot.php, you may need to specify a path -in the 'require' line below. - ------------- simpleplot.php ----------------------------- -SetDataValues($data); -$plot->SetDataType('data-data'); -$plot->DrawGraph(); ---------------------------------------------------------- - -Access the URL to 'simpleplot.html' in your web browser. If you see a -simple graph, you have successfully installed PHPlot. If you see no -graph, check your web server error log for more information. - - -COPYRIGHT and LICENSE: - -PHPlot is Copyright (C) 1998-2010 Afan Ottenheimer - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; -version 2.1 of the License. - -This software is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this software; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/gosa-core/include/phplot-5.1.2/contrib/README.txt b/gosa-core/include/phplot-5.1.2/contrib/README.txt deleted file mode 100644 index 3c6322520..000000000 --- a/gosa-core/include/phplot-5.1.2/contrib/README.txt +++ /dev/null @@ -1,31 +0,0 @@ -This is the README for PHPlot Contributed Code -The project web site is http://sourceforge.net/projects/phplot/ -Last updated on 2009-12-08 ------------------------------------------------------------------------------ - -The PHPlot Contributed Code directory contains code you might find useful -with PHPlot, but that doesn't quite belong as part of PHPlot itself. - -You will have to read the comments in the code files, and see the example -files, to determine what these do and if they are useful to you. None of -these functions is documented in the PHPlot Reference Manual. - -You may include or paste these functions into your own scripts. Check the -files for details, but some of these are considered "public domain" with no -usage or license restrictions. - ------------------------------------------------------------------------------ -Contents: - -prune_labels: Reduce the number of labels along the X axis - prune_labels.php . . . . . . . . . . . . Code - prune_labels.example.php . . . . . . . . Example - prune_labels.test.php . . . . . . . . . Test - -color_range: Create a gradient color map for data colors - color_range.php . . . . . . . . . . . . Code - color_range.example.php . . . . . . . . Example - color_range.test1.php . . . . . . . . . Image creation test - color_range.test2.php . . . . . . . . . Unit test - ------------------------------------------------------------------------------ diff --git a/gosa-core/include/phplot-5.1.2/contrib/color_range.example.php b/gosa-core/include/phplot-5.1.2/contrib/color_range.example.php deleted file mode 100644 index d29978b77..000000000 --- a/gosa-core/include/phplot-5.1.2/contrib/color_range.example.php +++ /dev/null @@ -1,35 +0,0 @@ -SetTitle('Example - Bar Chart with gradient colors'); -$p->SetDataType('text-data'); -$p->SetDataValues($data); -$p->SetPlotAreaWorld(0, 0, $x_values, 100); - -# This isn't necessary, as we do know how many data sets (bars_per_group): -$n_data = count_data_sets($data, 'text-data'); -# Make a gradient color map: -$colors = color_range($p->SetRGBColor('SkyBlue'), - $p->SetRGBColor('DarkGreen'), $n_data); -$p->SetDataColors($colors); -$p->SetXTickLabelPos('none'); -$p->SetXTickPos('none'); -$p->SetPlotType('bars'); -$p->DrawGraph(); diff --git a/gosa-core/include/phplot-5.1.2/contrib/color_range.php b/gosa-core/include/phplot-5.1.2/contrib/color_range.php deleted file mode 100755 index 65437ed37..000000000 --- a/gosa-core/include/phplot-5.1.2/contrib/color_range.php +++ /dev/null @@ -1,100 +0,0 @@ - - "I wrote this code to calculate the range of colors between 2 colors - to plot using the range from color_a to color_b..." - - I have changed the code and repackaged it, but the idea is the same. - Given 2 colors and number of data sets, computes an array of colors - that make up a gradient between the two provided colors, for use - with SetDataColors(). - - Provides the following functions: - $colors = color_range($color_a, $color_b, $n_intervals) - Returns a color array for SetDataColors. - - $n = count_data_sets($data, $data_type) - Counts the number of data sets in a data array. - This can be used to provide $n_intervals in color_range(). -*/ - - - -/* - Fill a color map with a gradient step between two colors. - Arguments: - $color_a : Starting color for the gradient. Array of (r, g, b) - $color_b : Ending color for the gradient. Array of (r, g, b) - $n_steps : Total number of color steps, including color_a and color_b. - - Returns: A color map array with n_steps colors in the form - $colors[i][3], suitable for SetDataColors(). - - Notes: - You may use the PHPlot internal function $plot->SetRGBColor($color) - to convert a color name or #rrggbb notation into the required array - of 3 values (r, g, b) for color_a and color_b. - -*/ -function color_range($color_a, $color_b, $n_steps) -{ - if ($n_steps < 2) $n_steps = 2; - $nc = $n_steps - 1; - # Note: $delta[] and $current[] are kept as floats. $colors is integers. - for ($i = 0; $i < 3; $i++) - $delta[$i] = ($color_b[$i] - $color_a[$i]) / $nc; - $current = $color_a; - for ($col = 0; $col < $nc; $col++) { - for ($i = 0; $i < 3; $i++) { - $colors[$col][$i] = (int)$current[$i]; - $current[$i] += $delta[$i]; - } - } - $colors[$nc] = $color_b; # Make sure the last color is exact. - return $colors; -} - - -/* - Determine the number of data sets (plot lines, bars per group, pie - segments, etc.) contained in a data array. - This can be used to determine n_steps for $color_range. - - Arguments: - $data : PHPlot data array - $data_type : PHPlot data type, describing $data. (e.g. 'data-data') - Returns: The number of data sets in the data array. - Notes: - This has to scan the entire data array. Don't use this unless you - really don't have a better way to determine the number of data sets. - - This does NOT require that the data array be integer indexed. - -*/ -function count_data_sets($data, $data_type) -{ - - if ($data_type == 'text-data-single') - return count($data); # Pie chart, 1 segment per record - - # Get the longest data record: - $max_row = 0; - foreach ($data as $row) - if (($n = count($row)) > $max_row) $max_row = $n; - - if ($data_type == 'text-data') - return ($max_row - 1); # Each record is (label Y1 Y2...) - - if ($data_type == 'data-data') - return ($max_row - 2); # Each record is (label X Y1 Y2...) - - if ($data_type == 'data-data-error') - return (($max_row - 2) / 3); # Each record is (label X Y1 Y1+ Y1-...) - - # Not a recognized data type... Just return something sane. - return $max_row; -} diff --git a/gosa-core/include/phplot-5.1.2/contrib/color_range.test1.php b/gosa-core/include/phplot-5.1.2/contrib/color_range.test1.php deleted file mode 100644 index 661f591ea..000000000 --- a/gosa-core/include/phplot-5.1.2/contrib/color_range.test1.php +++ /dev/null @@ -1,55 +0,0 @@ -SetTitle('Example - pruned data labels'); -$p->SetDataType('data-data'); -$p->SetDataValues($data); -$p->SetXLabelType('time', '%Y-%m-%d'); -$p->SetXLabelAngle(90); -$p->SetXDataLabelPos('plotdown'); -$p->SetXTickLabelPos('none'); -$p->SetXTickPos('none'); -$p->SetDrawXGrid(False); -$p->SetDrawYGrid(False); -$p->SetPlotType('lines'); -$p->DrawGraph(); diff --git a/gosa-core/include/phplot-5.1.2/contrib/prune_labels.php b/gosa-core/include/phplot-5.1.2/contrib/prune_labels.php deleted file mode 100644 index 5f272e52c..000000000 --- a/gosa-core/include/phplot-5.1.2/contrib/prune_labels.php +++ /dev/null @@ -1,36 +0,0 @@ - 0) $data[$i][0] = ''; - if (++$k >= $m) $k = 0; - } -} diff --git a/gosa-core/include/phplot-5.1.2/contrib/prune_labels.test.php b/gosa-core/include/phplot-5.1.2/contrib/prune_labels.test.php deleted file mode 100644 index 6d3bbb263..000000000 --- a/gosa-core/include/phplot-5.1.2/contrib/prune_labels.test.php +++ /dev/null @@ -1,41 +0,0 @@ - $non_blank labels\n"; - echo substr($line, 0, 80) . "\n"; # Only show first 80 chars. -} - -/* Test cases for prune_labels */ -for ($n = 7; $n <= 1000; $n *= 2) test($n, 10); -for ($g = 5; $g <= 40; $g++) test(72, $g); -# Edge cases -test(80, 41); -test(80, 40); -test(80, 39); diff --git a/gosa-core/include/phplot-5.1.2/phplot.php b/gosa-core/include/phplot-5.1.2/phplot.php deleted file mode 100644 index e914570c7..000000000 --- a/gosa-core/include/phplot-5.1.2/phplot.php +++ /dev/null @@ -1,5873 +0,0 @@ - - * - * Maintainer (2006-present) - * - * - * Requires PHP 5.2.x or later. (PHP 4 is unsupported as of Jan 2008) - */ - -class PHPlot { - - /* Declare class variables which are initialized to static values. Many more class variables - * are used, defined as needed, but are unset by default. - * All these are declared as public. While it is tempting to make them private or protected, this - * is avoided for two reasons. First, it will break existing code, since all member variables - * were public in PHP4 and who knows what internal variables people used. Second, it makes - * testing harder and less effective. Nevertheless, your code should not modify these. - */ - - public $is_inline = FALSE; // FALSE = Sends headers, TRUE = sends just raw image data - public $browser_cache = FALSE; // FALSE = Sends headers for browser to not cache the image, - // (only if is_inline = FALSE also) - public $print_image = TRUE; // DrawGraph calls PrintImage. See SetPrintImage - public $background_done = FALSE; // TRUE after background image is drawn once - - public $safe_margin = 5; // Extra margin used in several places, in pixels - - public $x_axis_position = ''; // Where to draw both axis (world coordinates), - public $y_axis_position = ''; // leave blank for X axis at 0 and Y axis at left of plot. - - public $xscale_type = 'linear'; // linear, log - public $yscale_type = 'linear'; - -//Fonts - public $use_ttf = FALSE; // Use True Type Fonts by default? - public $ttf_path = '.'; // Default path to look in for TT Fonts. - public $default_ttfont = 'benjamingothic.ttf'; - public $line_spacing = 4; // Controls line spacing of multi-line labels - - // Label angles: 0 or 90 degrees for fixed fonts, any for TTF - public $x_label_angle = 0; // For X tick labels - // public $x_data_label_angle; // For X data labels; defaults to x_label_angle - see CheckLabels() - public $y_label_angle = 0; // For Y tick labels - public $y_data_label_angle = 0; // For Y data labels - -//Formats - public $file_format = 'png'; - public $output_file = ''; // For output to a file instead of stdout - -//Data - public $data_type = 'text-data'; // Structure of the data array - public $plot_type= 'linepoints'; // bars, lines, linepoints, area, points, pie, thinbarline, squared - - public $label_scale_position = 0.5; // Shifts data labels in pie charts. 1 = top, 0 = bottom - public $group_frac_width = 0.7; // Bars use this fraction (0 to 1) of a group's space - public $bar_extra_space = 0.5; // Number of extra bar's worth of space in a group - public $bar_width_adjust = 1; // 1 = bars of normal width, must be > 0 - -// Titles - public $title_txt = ''; - - public $x_title_txt = ''; - public $x_title_pos = 'none'; // plotdown, plotup, both, none - - public $y_title_txt = ''; - public $y_title_pos = 'none'; // plotleft, plotright, both, none - - -//Labels - // There are two types of labels in PHPlot: - // Tick labels: they follow the grid, next to ticks in axis. - // they are drawn at grid drawing time, by DrawXTicks() and DrawYTicks() - // Data labels: they follow the data points, and can be placed on the axis or the plot (x/y) - // they are drawn at graph plotting time, by Draw*DataLabel(), called by DrawLines(), etc. - // Draw*DataLabel() also draws H/V lines to datapoints depending on draw_*_data_label_lines - // Tick Labels - // Tick and Data label positions are not initialized, because PHPlot needs to tell if they - // defaulted or are set by the user. See CheckLabels() for details. The variables and - // effective defaults are shown here in comments (but CheckLabels adjusts the defaults). - // public $x_tick_label_pos = 'plotdown'; // X tick label position - // public $y_tick_label_pos = 'plotleft'; // Y tick label position - // public $x_data_label_pos = 'plotdown'; // X data label position - // public $y_data_label_pos = 'none'; // Y data label position - - public $draw_x_data_label_lines = FALSE; // Draw a line from the data point to the axis? - - // Label format controls: (for tick, data and plot labels) - // Unset by default, these array members are used as needed for 'x' (x tick labels), 'xd' (x data - // labels), 'y' (y tick labels), and 'yd' (y data labels). - // type, precision, prefix, suffix, time_format, printf_format, custom_callback, custom_arg. - // These replace the former: x_label_type, x_time_format, x_precision (similar for y), data_units_text. - public $label_format = array('x' => array(), 'xd' => array(), 'y' => array(), 'yd' => array()); - // data_units_text is retained for backward compatibility, because there was never a function - // to set it. Use the 'suffix' argument to Set[XY]LabelType instead. - public $data_units_text = ''; // Units text for 'data' labels (i.e: '¤', '$', etc.) - -// Legend - public $legend = ''; // An array with legend titles - // These variables are unset to take default values: - // public $legend_x_pos; // User-specified upper left coordinates of legend box - // public $legend_y_pos; - // public $legend_xy_world; // If set, legend_x/y_pos are world coords, else pixel coords - // public $legend_text_align; // left or right, Unset means right - // public $legend_colorbox_align; // left, right, or none; Unset means same as text_align - -//Ticks - public $x_tick_length = 5; // tick length in pixels for upper/lower axis - public $y_tick_length = 5; // tick length in pixels for left/right axis - - public $x_tick_cross = 3; // ticks cross x axis this many pixels - public $y_tick_cross = 3; // ticks cross y axis this many pixels - - public $x_tick_pos = 'plotdown'; // plotdown, plotup, both, xaxis, none - public $y_tick_pos = 'plotleft'; // plotright, plotleft, both, yaxis, none - - public $num_x_ticks = ''; - public $num_y_ticks = ''; - - public $x_tick_inc = ''; // Set num_x_ticks or x_tick_inc, not both. - public $y_tick_inc = ''; // Set num_y_ticks or y_tick_inc, not both. - - public $skip_top_tick = FALSE; - public $skip_bottom_tick = FALSE; - public $skip_left_tick = FALSE; - public $skip_right_tick = FALSE; - -//Grid Formatting - // public $draw_x_grid = FALSE; // Default is False except for swapped data type - // public $draw_y_grid = TRUE; // Default is True except for swapped data type - - public $dashed_grid = TRUE; - public $grid_at_foreground = FALSE; // Chooses whether to draw the grid below or above the graph - -//Colors and styles (all colors can be array (R,G,B) or named color) - public $color_array = 'small'; // 'small', 'large' or array (define your own colors) - // See rgb.inc.php and SetRGBArray() - public $i_border = array(194, 194, 194); - public $plot_bg_color = 'white'; - public $bg_color = 'white'; - public $label_color = 'black'; - public $text_color = 'black'; - public $grid_color = 'black'; - public $light_grid_color = 'gray'; - public $tick_color = 'black'; - public $title_color = 'black'; - public $default_colors = array( // The default colors for data and error bars - 'SkyBlue', 'green', 'orange', 'blue', 'red', 'DarkGreen', 'purple', 'peru', - 'cyan', 'salmon', 'SlateBlue', 'YellowGreen', 'magenta', 'aquamarine1', 'gold', 'violet'); - - // data_colors and error_bar_colors are initialized to default_colors by SetDefaultStyles. - // public $data_colors; // Data colors - // public $error_bar_colors; // Error bar colors - // data_border_colors is initialized to black by SetDefaultStyles. - // public $data_border_colors; // Data border colors - - public $line_widths = 1; // single value or array - public $line_styles = array('solid', 'solid', 'dashed'); // single value or array - public $dashed_style = '2-4'; // colored dots-transparent dots - - public $point_sizes = array(6); // Array of sizes for points. See CheckPointParams() - public $point_shapes = array( // Array of point shapes. See SetPointShapes() and DrawDot() - 'diamond', 'dot', 'delta', 'home', 'yield', 'box', 'circle', 'up', 'down', 'cross' - ); - - public $error_bar_size = 5; // right and left size of tee - public $error_bar_shape = 'tee'; // 'tee' or 'line' - public $error_bar_line_width = 1; // single value (or array TODO) - - public $plot_border_type = 'sides'; // left, right, top, bottom, sides, none, full; or array - public $image_border_type = 'none'; // 'raised', 'plain', 'none' - // public $image_border_width; // NULL, 0, or unset for default. Default depends on type. - - public $shading = 5; // 0 for no shading, > 0 is size of shadows in pixels - - public $draw_plot_area_background = FALSE; - public $draw_broken_lines = FALSE; // Tells not to draw lines for missing Y data. - - public $data_colors_alpha = 0; // Default alpha for data colors. See SetDataColors() - - -//Miscellaneous - public $callbacks = array( // Valid callback reasons (see SetCallBack) - 'draw_setup' => NULL, - 'draw_image_background' => NULL, - 'draw_plotarea_background' => NULL, - 'draw_titles' => NULL, - 'draw_axes' => NULL, - 'draw_graph' => NULL, - 'draw_border' => NULL, - 'draw_legend' => NULL, - 'draw_all' => NULL, - 'debug_textbox' => NULL, // For testing/debugging text box alignment - 'debug_scale' => NULL, // For testing/debugging scale setup - ); - - -////////////////////////////////////////////////////// -//BEGIN CODE -////////////////////////////////////////////////////// - - /*! - * Constructor: Setup img resource, colors and size of the image, and font sizes. - * - * \param which_width int Image width in pixels. - * \param which_height int Image height in pixels. - * \param which_output_file string Filename for output. - * \param which_input_file string Path to a file to be used as background. - */ - function PHPlot($which_width=600, $which_height=400, $which_output_file=NULL, $which_input_file=NULL) - { - $this->SetRGBArray($this->color_array); - - if ($which_output_file) - $this->SetOutputFile($which_output_file); - - if ($which_input_file) - $this->SetInputFile($which_input_file); - else { - $this->image_width = $which_width; - $this->image_height = $which_height; - - $this->img = ImageCreate($this->image_width, $this->image_height); - if (! $this->img) - return $this->PrintError('PHPlot(): Could not create image resource.'); - } - - $this->SetDefaultStyles(); - $this->SetDefaultFonts(); - } - - /*! - * Reads an image file. Stores width and height, and returns the image - * resource. On error, calls PrintError and returns False. - * This is used by the constructor via SetInputFile, and by tile_img(). - */ - protected function GetImage($image_filename, &$width, &$height) - { - $error = ''; - $size = getimagesize($image_filename); - if (!$size) { - $error = "Unable to query image file $image_filename"; - } else { - $image_type = $size[2]; - switch($image_type) { - case IMAGETYPE_GIF: - $img = @ ImageCreateFromGIF ($image_filename); - break; - case IMAGETYPE_PNG: - $img = @ ImageCreateFromPNG ($image_filename); - break; - case IMAGETYPE_JPEG: - $img = @ ImageCreateFromJPEG ($image_filename); - break; - default: - $error = "Unknown image type ($image_type) for image file $image_filename"; - break; - } - } - if (empty($error) && !$img) { - # getimagesize is OK, but GD won't read it. Maybe unsupported format. - $error = "Failed to read image file $image_filename"; - } - if (!empty($error)) { - return $this->PrintError("GetImage(): $error"); - } - $width = $size[0]; - $height = $size[1]; - return $img; - } - - /*! - * Selects an input file to be used as background for the whole graph. - * This resets the graph size to the image's size. - * Note: This is used by the constructor. It is deprecated for direct use. - */ - function SetInputFile($which_input_file) - { - $im = $this->GetImage($which_input_file, $this->image_width, $this->image_height); - if (!$im) - return FALSE; // GetImage already produced an error message. - - // Deallocate any resources previously allocated - if (isset($this->img)) - imagedestroy($this->img); - - $this->img = $im; - - // Do not overwrite the input file with the background color. - $this->background_done = TRUE; - - return TRUE; - } - -///////////////////////////////////////////// -////////////// COLORS -///////////////////////////////////////////// - - /* - * Returns a GD color index value to a color specified as for SetRGBColor(). - * This works with both palette and truecolor images. - * $which_color : The color specification. See SetRGBColor for formats. - * $alpha : Optional default Alpha value, if $which_color does not include alpha. - * Returns a GD color index, or NULL on error. - * Note: For palette images, this is an index into the color map. - * For truecolor images, this is a 32 bit value 0xAARRGGBB. But this difference - * is internal to GD. - */ - function SetIndexColor($which_color, $alpha = 0) - { - list ($r, $g, $b, $a) = $this->SetRGBColor($which_color, $alpha); //Translate to RGBA - if (!isset($r)) return NULL; - return ImageColorResolveAlpha($this->img, $r, $g, $b, $a); - } - - /* - * Returns an index to a slightly darker color than the one requested. - * This works with both palette and truecolor images. - * $which_color : The color specification. See SetRGBColor for formats. - * $alpha : Optional default Alpha value, if $which_color does not include alpha. - * Returns a GD color index, or NULL on error. - */ - protected function SetIndexDarkColor($which_color, $alpha = 0) - { - list ($r, $g, $b, $a) = $this->SetRGBColor($which_color, $alpha); - if (!isset($r)) return NULL; - $r = max(0, $r - 0x30); - $g = max(0, $g - 0x30); - $b = max(0, $b - 0x30); - return ImageColorResolveAlpha($this->img, $r, $g, $b, $a); - } - - /*! - * Sets/reverts all colors and styles to their defaults. - */ - protected function SetDefaultStyles() - { - /* Some of the Set*() functions use default values when they get no parameters. */ - $this->SetDefaultDashedStyle($this->dashed_style); - $this->SetImageBorderColor($this->i_border); - $this->SetPlotBgColor($this->plot_bg_color); - $this->SetBackgroundColor($this->bg_color); - $this->SetLabelColor($this->label_color); - $this->SetTextColor($this->text_color); - $this->SetGridColor($this->grid_color); - $this->SetLightGridColor($this->light_grid_color); - $this->SetTickColor($this->tick_color); - $this->SetTitleColor($this->title_color); - $this->SetDataColors(); - $this->SetErrorBarColors(); - $this->SetDataBorderColors(); - return TRUE; - } - - - /* - * - */ - function SetBackgroundColor($which_color) - { - $this->bg_color= $which_color; - $this->ndx_bg_color= $this->SetIndexColor($this->bg_color); - return isset($this->ndx_bg_color); - } - - /* - * - */ - function SetPlotBgColor($which_color) - { - $this->plot_bg_color= $which_color; - $this->ndx_plot_bg_color= $this->SetIndexColor($this->plot_bg_color); - return isset($this->ndx_plot_bg_color); - } - - /* - * - */ - function SetTitleColor($which_color) - { - $this->title_color= $which_color; - $this->ndx_title_color= $this->SetIndexColor($this->title_color); - return isset($this->ndx_title_color); - } - - /* - * - */ - function SetTickColor ($which_color) - { - $this->tick_color= $which_color; - $this->ndx_tick_color= $this->SetIndexColor($this->tick_color); - return isset($this->ndx_tick_color); - } - - - /* - * Do not use. Use SetTitleColor instead. - */ - function SetLabelColor ($which_color) - { - $this->label_color = $which_color; - $this->ndx_title_color= $this->SetIndexColor($this->label_color); - return isset($this->ndx_title_color); - } - - - /* - * - */ - function SetTextColor ($which_color) - { - $this->text_color= $which_color; - $this->ndx_text_color= $this->SetIndexColor($this->text_color); - return isset($this->ndx_text_color); - } - - - /* - * - */ - function SetLightGridColor ($which_color) - { - $this->light_grid_color= $which_color; - $this->ndx_light_grid_color= $this->SetIndexColor($this->light_grid_color); - return isset($this->ndx_light_grid_color); - } - - - /* - * - */ - function SetGridColor ($which_color) - { - $this->grid_color = $which_color; - $this->ndx_grid_color= $this->SetIndexColor($this->grid_color); - return isset($this->ndx_grid_color); - } - - - /* - * - */ - function SetImageBorderColor($which_color) - { - $this->i_border = $which_color; - $this->ndx_i_border = $this->SetIndexColor($this->i_border); - $this->ndx_i_border_dark = $this->SetIndexDarkColor($this->i_border); - return isset($this->ndx_i_border); - } - - - /* - * - */ - function SetTransparentColor($which_color) - { - $ndx = $this->SetIndexColor($which_color); - if (!isset($ndx)) - return FALSE; - ImageColorTransparent($this->img, $ndx); - return TRUE; - } - - - /*! - * Sets the array of colors to be used. It can be user defined, a small predefined one - * or a large one included from 'rgb.inc.php'. - * - * \param which_color_array If an array, the used as color array. If a string can - * be one of 'small' or 'large'. - */ - function SetRGBArray ($which_color_array) - { - if ( is_array($which_color_array) ) { // User defined array - $this->rgb_array = $which_color_array; - return TRUE; - } elseif ($which_color_array == 'small') { // Small predefined color array - $this->rgb_array = array( - 'white' => array(255, 255, 255), - 'snow' => array(255, 250, 250), - 'PeachPuff' => array(255, 218, 185), - 'ivory' => array(255, 255, 240), - 'lavender' => array(230, 230, 250), - 'black' => array( 0, 0, 0), - 'DimGrey' => array(105, 105, 105), - 'gray' => array(190, 190, 190), - 'grey' => array(190, 190, 190), - 'navy' => array( 0, 0, 128), - 'SlateBlue' => array(106, 90, 205), - 'blue' => array( 0, 0, 255), - 'SkyBlue' => array(135, 206, 235), - 'cyan' => array( 0, 255, 255), - 'DarkGreen' => array( 0, 100, 0), - 'green' => array( 0, 255, 0), - 'YellowGreen' => array(154, 205, 50), - 'yellow' => array(255, 255, 0), - 'orange' => array(255, 165, 0), - 'gold' => array(255, 215, 0), - 'peru' => array(205, 133, 63), - 'beige' => array(245, 245, 220), - 'wheat' => array(245, 222, 179), - 'tan' => array(210, 180, 140), - 'brown' => array(165, 42, 42), - 'salmon' => array(250, 128, 114), - 'red' => array(255, 0, 0), - 'pink' => array(255, 192, 203), - 'maroon' => array(176, 48, 96), - 'magenta' => array(255, 0, 255), - 'violet' => array(238, 130, 238), - 'plum' => array(221, 160, 221), - 'orchid' => array(218, 112, 214), - 'purple' => array(160, 32, 240), - 'azure1' => array(240, 255, 255), - 'aquamarine1' => array(127, 255, 212) - ); - return TRUE; - } elseif ($which_color_array === 'large') { // Large color array - if (!@include('rgb.inc.php')) { - return $this->PrintError("SetRGBArray(): Large color map could not be loaded\n" - . "from 'rgb.inc.php'."); - } - $this->rgb_array = $ColorArray; - } else { // Default to black and white only. - $this->rgb_array = array('white' => array(255, 255, 255), 'black' => array(0, 0, 0)); - } - - return TRUE; - } - - /* - * Parse a color description and return the color component values. - * Arguments: - * $color_asked : The desired color description, in one of these forms: - * Component notation: array(R, G, B) or array(R, G, B, A) with each - * in the range described below for the return value. - * Examples: (255,255,0) (204,0,0,30) - * Hex notation: "#RRGGBB" or "#RRGGBBAA" where each pair is a 2 digit hex number. - * Examples: #FF00FF (magenta) #0000FF40 (Blue with alpha=64/127) - * Named color in the current colormap, with optional suffix ":alpha" for alpha value. - * Examples: blue red:60 yellow:20 - * $alpha : optional default alpha value. This is applied to the color if it doesn't - * already have an alpha value. If not supplied, colors are opaque (alpha=0) by default. - * - * Returns an array describing a color as (R, G, B, Alpha). - * R, G, and B are integers 0-255, and Alpha is 0 (opaque) to 127 (transparent). - */ - function SetRGBColor($color_asked, $alpha = 0) - { - if (empty($color_asked)) { - $ret_val = array(0, 0, 0); - - } elseif (is_array($color_asked) && (($n = count($color_asked)) == 3 || $n == 4) ) { - // Already an array of 3 or 4 elements: - $ret_val = $color_asked; - - } elseif (preg_match('/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/i', - $color_asked, $ss)) { - // #RRGGBB or #RRGGBBAA notation: - $ret_val = array(hexdec($ss[1]), hexdec($ss[2]), hexdec($ss[3])); - if (isset($ss[4])) $ret_val[] = hexdec($ss[4]); - - } elseif (isset($this->rgb_array[$color_asked])) { - // Color by name: - $ret_val = $this->rgb_array[$color_asked]; - - } elseif (preg_match('/(.+):([\d]+)$/', $color_asked, $ss) - && isset($this->rgb_array[$ss[1]])) { - // Color by name with ":alpha" suffix, alpha is a decimal number: - $ret_val = $this->rgb_array[$ss[1]]; - $ret_val[3] = (int)$ss[2]; - - } else { - return $this->PrintError("SetRGBColor(): Color '$color_asked' is not valid."); - } - - // Append alpha if not already provided for: - if (count($ret_val) == 3) - $ret_val[] = $alpha; - return $ret_val; - } - - /*! - * Sets the colors for the data, with optional default alpha value (for PHPlot_truecolor only) - * Cases are: - * SetDataColors(array(...)) : Use the supplied array as the color map. - * SetDataColors(colorname) : Use an array of just colorname as the color map. - * SetDataColors() or SetDataColors(NULL) : Load default color map if no color map is already set. - * SetDataColors('') or SetDataColors(False) : Load default color map (even if one is already set). - */ - function SetDataColors($which_data = NULL, $which_border = NULL, $alpha = NULL) - { - if (is_array($which_data)) { - $this->data_colors = $which_data; // Use supplied array - } elseif (!empty($which_data)) { - $this->data_colors = array($which_data); // Use supplied single color - } elseif (empty($this->data_colors) || !is_null($which_data)) { - $this->data_colors = $this->default_colors; // Use default color array - } // Else do nothing: which_data is NULL or missing and a color array is already set. - - // If an alpha value is supplied, use it as the new default. Need to save and restore - // this because the color indexes will be regenerated when the arrays are padded. - if (!empty($alpha)) - $this->data_colors_alpha = $alpha; - - $i = 0; - foreach ($this->data_colors as $col) { - $ndx = $this->SetIndexColor($col, $this->data_colors_alpha); - if (!isset($ndx)) - return FALSE; - $this->ndx_data_colors[$i] = $ndx; - $this->ndx_data_dark_colors[$i] = $this->SetIndexDarkColor($col, $this->data_colors_alpha); - $i++; - } - - // For past compatibility: - return $this->SetDataBorderColors($which_border); - } // function SetDataColors() - - - /*! - * Set the colors for the bars and stacked bars outlines. - * Argument usage is similar to SetDataColors(), except the default is just black. - */ - function SetDataBorderColors($which_br = NULL) - { - if (is_array($which_br)) { - $this->data_border_colors = $which_br; // Use supplied array - } elseif (!empty($which_br)) { - $this->data_border_colors = array($which_br); // Use supplied single color - } elseif (empty($this->data_border_colors) || !is_null($which_br)) { - $this->data_border_colors = array('black'); // Use default - } // Else do nothing: which_br is NULL or missing and a color array is already set. - - $i = 0; - foreach($this->data_border_colors as $col) { - $ndx = $this->SetIndexColor($col); - if (!isset($ndx)) - return FALSE; - $this->ndx_data_border_colors[$i] = $ndx; - $i++; - } - return TRUE; - } // function SetDataBorderColors() - - - /*! - * Sets the colors for the data error bars. - * Argument usage is the same as SetDataColors(). - */ - function SetErrorBarColors($which_err = NULL) - { - if (is_array($which_err)) { - $this->error_bar_colors = $which_err; // Use supplied array - } elseif (!empty($which_err)) { - $this->error_bar_colors = array($which_err); // Use supplied single color - } elseif (empty($this->error_bar_colors) || !is_null($which_err)) { - $this->error_bar_colors = $this->default_colors; // Use default color array - } // Else do nothing: which_err is NULL or missing and a color array is already set. - - $i = 0; - foreach($this->error_bar_colors as $col) { - $ndx = $this->SetIndexColor($col); - if (!isset($ndx)) - return FALSE; - $this->ndx_error_bar_colors[$i] = $ndx; - $i++; - } - return TRUE; - } // function SetErrorBarColors() - - - /*! - * Sets the default dashed style. - * \param which_style A string specifying order of colored and transparent dots, - * i.e: '4-3' means 4 colored, 3 transparent; - * '2-3-1-2' means 2 colored, 3 transparent, 1 colored, 2 transparent. - */ - function SetDefaultDashedStyle($which_style) - { - // String: "numcol-numtrans-numcol-numtrans..." - $asked = explode('-', $which_style); - - if (count($asked) < 2) { - return $this->PrintError("SetDefaultDashedStyle(): Wrong parameter '$which_style'."); - } - - // Build the string to be eval()uated later by SetDashedStyle() - $this->default_dashed_style = 'array( '; - - $t = 0; - foreach($asked as $s) { - if ($t % 2 == 0) { - $this->default_dashed_style .= str_repeat('$which_ndxcol,', $s); - } else { - $this->default_dashed_style .= str_repeat('IMG_COLOR_TRANSPARENT,', $s); - } - $t++; - } - // Remove trailing comma and add closing parenthesis - $this->default_dashed_style = substr($this->default_dashed_style, 0, -1); - $this->default_dashed_style .= ')'; - - return TRUE; - } - - - /*! - * Sets the style before drawing a dashed line. Defaults to $this->default_dashed_style - * \param which_ndxcol Color index to be used. - */ - protected function SetDashedStyle($which_ndxcol) - { - // See SetDefaultDashedStyle() to understand this. - eval ("\$style = $this->default_dashed_style;"); - return imagesetstyle($this->img, $style); - } - - - /*! - * Sets line widths on a per-line basis. - */ - function SetLineWidths($which_lw=NULL) - { - if (is_null($which_lw)) { - // Do nothing, use default value. - } else if (is_array($which_lw)) { - // Did we get an array with line widths? - $this->line_widths = $which_lw; - } else { - $this->line_widths = array($which_lw); - } - return TRUE; - } - - /*! - * - */ - function SetLineStyles($which_ls=NULL) - { - if (is_null($which_ls)) { - // Do nothing, use default value. - } else if ( is_array($which_ls)) { - // Did we get an array with line styles? - $this->line_styles = $which_ls; - } else { - $this->line_styles = ($which_ls) ? array($which_ls) : array('solid'); - } - return TRUE; - } - - -///////////////////////////////////////////// -////////////// TEXT and FONTS -///////////////////////////////////////////// - - - /*! - * Controls the line spacing of multi-line labels. - * For GD text, this is the number of pixels between lines. - * For TTF text, it controls line spacing in proportion to the normal - * spacing defined by the font. - */ - function SetLineSpacing($which_spc) - { - $this->line_spacing = $which_spc; - return TRUE; - } - - - /*! - * Select the default font type to use. - * $which_ttf : True to default to TrueType, False to default to GD (fixed) fonts. - * This also resets all font settings to the defaults. - */ - function SetUseTTF($which_ttf) - { - $this->use_ttf = $which_ttf; - return $this->SetDefaultFonts(); - } - - /*! - * Sets the directory name to look into for TrueType fonts. - */ - function SetTTFPath($which_path) - { - // Maybe someone needs really dynamic config. He'll need this: - // clearstatcache(); - - if (is_dir($which_path) && is_readable($which_path)) { - $this->ttf_path = $which_path; - return TRUE; - } - return $this->PrintError("SetTTFPath(): $which_path is not a valid path."); - } - - /*! - * Sets the default TrueType font and updates all fonts to that. - * The default font might be a full path, or relative to the TTFPath, - * so let SetFont check that it exists. - * Side effects: Enables use of TrueType fonts as the default font type, - * and resets all font settings. - */ - function SetDefaultTTFont($which_font) - { - $this->default_ttfont = $which_font; - return $this->SetUseTTF(TRUE); - } - - /*! - * Sets fonts to their defaults - */ - protected function SetDefaultFonts() - { - // TTF: - if ($this->use_ttf) { - return $this->SetFont('generic', '', 8) - && $this->SetFont('title', '', 14) - && $this->SetFont('legend', '', 8) - && $this->SetFont('x_label', '', 6) - && $this->SetFont('y_label', '', 6) - && $this->SetFont('x_title', '', 10) - && $this->SetFont('y_title', '', 10); - } - // Fixed GD Fonts: - return $this->SetFont('generic', 2) - && $this->SetFont('title', 5) - && $this->SetFont('legend', 2) - && $this->SetFont('x_label', 1) - && $this->SetFont('y_label', 1) - && $this->SetFont('x_title', 3) - && $this->SetFont('y_title', 3); - } - - /* - * Select a fixed (GD) font for an element. - * This allows using a fixed font, even with SetUseTTF(True). - * $which_elem : The element whose font is to be changed. - * One of: title legend generic x_label y_label x_title y_title - * $which_font : A GD font number 1-5 - * $which_spacing (optional) : Line spacing factor - */ - function SetFontGD($which_elem, $which_font, $which_spacing = NULL) - { - if ($which_font < 1 || 5 < $which_font) { - return $this->PrintError(__FUNCTION__ . ': Font size must be 1, 2, 3, 4 or 5'); - } - if (!$this->CheckOption($which_elem, - 'generic, title, legend, x_label, y_label, x_title, y_title', - __FUNCTION__)) { - return FALSE; - } - - # Store the font parameters: name/size, char cell height and width. - $this->fonts[$which_elem] = array('ttf' => FALSE, - 'font' => $which_font, - 'height' => ImageFontHeight($which_font), - 'width' => ImageFontWidth($which_font), - 'line_spacing' => $which_spacing); - return TRUE; - } - - /* - * Select a TrueType font for an element. - * This allows using a TrueType font, even with SetUseTTF(False). - * $which_elem : The element whose font is to be changed. - * One of: title legend generic x_label y_label x_title y_title - * $which_font : A TrueType font filename or pathname. - * $which_size : Font point size. - * $which_spacing (optional) : Line spacing factor - */ - function SetFontTTF($which_elem, $which_font, $which_size = 12, $which_spacing = NULL) - { - if (!$this->CheckOption($which_elem, - 'generic, title, legend, x_label, y_label, x_title, y_title', - __FUNCTION__)) { - return FALSE; - } - - # Empty font name means use the default font. - if (empty($which_font)) - $which_font = $this->default_ttfont; - $path = $which_font; - - # First try the font name directly, if not then try with path. - if (!is_file($path) || !is_readable($path)) { - $path = $this->ttf_path . DIRECTORY_SEPARATOR . $which_font; - if (!is_file($path) || !is_readable($path)) { - return $this->PrintError(__FUNCTION__ . ": Can't find TrueType font $which_font"); - } - } - - # Calculate the font height and inherent line spacing. TrueType fonts have this information - # internally, but PHP/GD has no way to directly access it. So get the bounding box size of - # an upper-case character without descenders, and the baseline-to-baseline height. - # Note: In practice, $which_size = $height, maybe +/-1 . But which_size is in points, - # and height is in pixels, and someday GD may be able to tell the difference. - # The character width is saved too, but not used by the normal text drawing routines - it - # isn't necessarily a fixed-space font. It is used in DrawLegend. - $bbox = ImageTTFBBox($which_size, 0, $path, "E"); - $height = $bbox[1] - $bbox[5]; - $width = $bbox[2] - $bbox[0]; - $bbox = ImageTTFBBox($which_size, 0, $path, "E\nE"); - $spacing = $bbox[1] - $bbox[5] - 2 * $height; - - # Store the font parameters: - $this->fonts[$which_elem] = array('ttf' => TRUE, - 'font' => $path, - 'size' => $which_size, - 'height' => $height, - 'width' => $width, - 'spacing' => $spacing, - 'line_spacing' => $which_spacing); - return TRUE; - } - - - /* - * Select Fixed/TrueType font for an element. Which type of font is - * selected depends on the $use_ttf class variable (see SetUseTTF()). - * Before PHPlot supported mixing font types, only this function and - * SetUseTTF were available to select an overall font type, but now - * SetFontGD() and SetFontTTF() can be used for mixing font types. - * $which_elem : The element whose font is to be changed. - * One of: title legend generic x_label y_label x_title y_title - * $which_font : A number 1-5 for fixed fonts, or a TrueType font. - * $which_size : Ignored for Fixed fonts, point size for TrueType. - * $which_spacing (optional) : Line spacing factor - */ - function SetFont($which_elem, $which_font, $which_size = 12, $line_spacing = NULL) - { - if ($this->use_ttf) - return $this->SetFontTTF($which_elem, $which_font, $which_size, $line_spacing); - return $this->SetFontGD($which_elem, $which_font, $line_spacing); - } - - /* - * Return the inter-line spacing for a font. - * This is an internal function, used by ProcessText* and DrawLegend. - * $font : A font array variable. - * Returns: Spacing, in pixels, between text lines. - */ - protected function GetLineSpacing($font) - { - # Use the per-font line spacing preference, if set, else the global value: - if (isset($font['line_spacing'])) - $line_spacing = $font['line_spacing']; - else - $line_spacing = $this->line_spacing; - - # For GD fonts, that is the spacing in pixels. - # For TTF, adjust based on the 'natural' font spacing (see SetFontTTF): - if ($font['ttf']) { - $line_spacing = (int)($line_spacing * $font['spacing'] / 6.0); - } - return $line_spacing; - } - - /*! - * Text drawing and sizing functions: - * ProcessText is meant for use only by DrawText and SizeText. - * ProcessText(True, ...) - Draw a block of text - * ProcessText(False, ...) - Just return ($width, $height) of - * the orthogonal bounding box containing the text. - * ProcessText is further split into separate functions for GD and TTF - * text, due to the size of the code. - * - * Horizontal and vertical alignment are relative to the drawing. That is: - * vertical text (90 deg) gets centered along Y position with - * v_align = 'center', and adjusted to the right of X position with - * h_align = 'right'. Another way to look at this is to say - * that text rotation happens first, then alignment. - * - * Original multiple lines code submitted by Remi Ricard. - * Original vertical code submitted by Marlin Viss. - * - * Text routines rewritten by ljb to fix alignment and position problems. - * Here is my explanation and notes. More information and pictures will be - * placed in the PHPlot Reference Manual. - * - * + Process TTF text one line at a time, not as a block. (See below) - * + Flipped top vs bottom vertical alignment. The usual interpretation - * is: bottom align means bottom of the text is at the specified Y - * coordinate. For some reason, PHPlot did left/right the correct way, - * but had top/bottom reversed. I fixed it, and left the default valign - * argument as bottom, but the meaning of the default value changed. - * - * For GD font text, only single-line text is handled by GD, and the - * basepoint is the upper left corner of each text line. - * For TTF text, multi-line text could be handled by GD, with the text - * basepoint at the lower left corner of the first line of text. - * (Behavior of TTF drawing routines on multi-line text is not documented.) - * But you cannot do left/center/right alignment on each line that way, - * or proper line spacing. - * Therefore, for either text type, we have to break up the text into - * lines and position each line independently. - * - * There are 9 alignment modes: Horizontal = left, center, or right, and - * Vertical = top, center, or bottom. Alignment is interpreted relative to - * the image, not as the text is read. This makes sense when you consider - * for example X axis labels. They need to be centered below the marks - * (center, top alignment) regardless of the text angle. - * 'Bottom' alignment really means baseline alignment. - * - * GD font text is supported (by libgd) at 0 degrees and 90 degrees only. - * Multi-line or single line text works with any of the 9 alignment modes. - * - * TTF text can be at any angle. The 9 alignment modes work for all angles, - * but the results might not be what you expect for multi-line text. See - * the PHPlot Reference Manual for pictures and details. In short, alignment - * applies to the orthogonal (aligned with X and Y axes) bounding box that - * contains the text, and to each line in the multi-line text box. Since - * alignment is relative to the image, 45 degree multi-line text aligns - * differently from 46 degree text. - * - * Note that PHPlot allows multi-line text for the 3 titles, and they - * are only drawn at 0 degrees (main and X titles) or 90 degrees (Y title). - * Data labels can also be multi-line, and they can be drawn at any angle. - * -ljb 2007-11-03 - * - */ - - /* - * ProcessTextGD() - Draw or size GD fixed-font text. - * This is intended for use only by ProcessText(). - * $draw_it : True to draw the text, False to just return the orthogonal width and height. - * $font : PHPlot font array (with 'ttf' = False) - see SetFontGD() - * $angle : Text angle in degrees. GD only supports 0 and 90. We treat >= 45 as 90, else 0. - * $x, $y : Reference point for the text (ignored if !$draw_it) - * $color : GD color index to use for drawing the text (ignored if !$draw_it) - * $text : The text to draw or size. Put a newline between lines. - * $h_factor : Horizontal alignment factor: 0(left), .5(center), or 1(right) (ignored if !$draw_it) - * $v_factor : Vertical alignment factor: 0(top), .5(center), or 1(bottom) (ignored if !$draw_it) - * Returns: True, if drawing text, or an array of ($width, $height) if not. - */ - protected function ProcessTextGD($draw_it, $font, $angle, $x, $y, $color, $text, $h_factor, $v_factor) - { - # Extract font parameters: - $font_number = $font['font']; - $font_width = $font['width']; - $font_height = $font['height']; - $line_spacing = $this->GetLineSpacing($font); - - # Break up the text into lines, trim whitespace, find longest line. - # Save the lines and length for drawing below. - $longest = 0; - foreach (explode("\n", $text) as $each_line) { - $lines[] = $line = trim($each_line); - $line_lens[] = $line_len = strlen($line); - if ($line_len > $longest) $longest = $line_len; - } - $n_lines = count($lines); - - # Width, height are based on font size and longest line, line count respectively. - # These are relative to the text angle. - $total_width = $longest * $font_width; - $total_height = $n_lines * $font_height + ($n_lines - 1) * $line_spacing; - - if (!$draw_it) { - if ($angle < 45) return array($total_width, $total_height); - return array($total_height, $total_width); - } - - $interline_step = $font_height + $line_spacing; // Line-to-line step - - if ($angle >= 45) { - // Vertical text (90 degrees): - // (Remember the alignment convention with vertical text) - // For 90 degree text, alignment factors change like this: - $temp = $v_factor; - $v_factor = $h_factor; - $h_factor = 1 - $temp; - - $draw_func = 'ImageStringUp'; - - // Rotation matrix "R" for 90 degrees (with Y pointing down): - $r00 = 0; $r01 = 1; - $r10 = -1; $r11 = 0; - - } else { - // Horizontal text (0 degrees): - $draw_func = 'ImageString'; - - // Rotation matrix "R" for 0 degrees: - $r00 = 1; $r01 = 0; - $r10 = 0; $r11 = 1; - } - - // Adjust for vertical alignment (horizontal text) or horizontal alignment (vertical text): - $factor = (int)($total_height * $v_factor); - $xpos = $x - $r01 * $factor; - $ypos = $y - $r11 * $factor; - - # Debug callback provides the bounding box: - if ($this->GetCallback('debug_textbox')) { - if ($angle >= 45) { - $bbox_width = $total_height; - $bbox_height = $total_width; - $px = $xpos; - $py = $ypos - (1 - $h_factor) * $total_width; - } else { - $bbox_width = $total_width; - $bbox_height = $total_height; - $px = $xpos - $h_factor * $total_width; - $py = $ypos; - } - $this->DoCallback('debug_textbox', $px, $py, $bbox_width, $bbox_height); - } - - for ($i = 0; $i < $n_lines; $i++) { - - // Adjust for alignment of this line within the text block: - $factor = (int)($line_lens[$i] * $font_width * $h_factor); - $x = $xpos - $r00 * $factor; - $y = $ypos - $r10 * $factor; - - // Call ImageString or ImageStringUp: - $draw_func($this->img, $font_number, $x, $y, $lines[$i], $color); - - // Step to the next line of text. This is a rotation of (x=0, y=interline_spacing) - $xpos += $r01 * $interline_step; - $ypos += $r11 * $interline_step; - } - return TRUE; - } - - - /* - * ProcessTextTTF() - Draw or size TTF text. - * This is intended for use only by ProcessText(). - * $draw_it : True to draw the text, False to just return the orthogonal width and height. - * $font : PHPlot font array (with 'ttf' = True) - see SetFontTTF() - * $angle : Text angle in degrees. - * $x, $y : Reference point for the text (ignored if !$draw_it) - * $color : GD color index to use for drawing the text (ignored if !$draw_it) - * $text : The text to draw or size. Put a newline between lines. - * $h_factor : Horizontal alignment factor: 0(left), .5(center), or 1(right) (ignored if !$draw_it) - * $v_factor : Vertical alignment factor: 0(top), .5(center), or 1(bottom) (ignored if !$draw_it) - * Returns: True, if drawing text, or an array of ($width, $height) if not. - */ - protected function ProcessTextTTF($draw_it, $font, $angle, $x, $y, $color, $text, $h_factor, $v_factor) - { - # Extract font parameters (see SetFontTTF): - $font_file = $font['font']; - $font_size = $font['size']; - $font_height = $font['height']; - $line_spacing = $this->GetLineSpacing($font); - - # Break up the text into lines, trim whitespace. - # Calculate the total width and height of the text box at 0 degrees. - # Save the trimmed lines and their widths for later when drawing. - # To get uniform spacing, don't use the actual line heights. - # Total height = Font-specific line heights plus inter-line spacing. - # Total width = width of widest line. - # Last Line Descent is the offset from the bottom to the text baseline. - # Note: For some reason, ImageTTFBBox uses (-1,-1) as the reference point. - # So 1+bbox[1] is the baseline to bottom distance. - $total_width = 0; - $lastline_descent = 0; - foreach (explode("\n", $text) as $each_line) { - $lines[] = $line = trim($each_line); - $bbox = ImageTTFBBox($font_size, 0, $font_file, $line); - $line_widths[] = $width = $bbox[2] - $bbox[0]; - if ($width > $total_width) $total_width = $width; - $lastline_descent = 1 + $bbox[1]; - } - $n_lines = count($lines); - $total_height = $n_lines * $font_height + ($n_lines - 1) * $line_spacing; - - # Calculate the rotation matrix for the text's angle. Remember that GD points Y down, - # so the sin() terms change sign. - $theta = deg2rad($angle); - $cos_t = cos($theta); - $sin_t = sin($theta); - $r00 = $cos_t; $r01 = $sin_t; - $r10 = -$sin_t; $r11 = $cos_t; - - # Make a bounding box of the right size, with upper left corner at (0,0). - # By convention, the point order is: LL, LR, UR, UL. - # Note this is still working with the text at 0 degrees. - # When sizing text (SizeText), use the overall size with descenders. - # This tells the caller how much room to leave for the text. - # When drawing text (DrawText), use the size without descenders - that - # is, down to the baseline. This is for accurate positioning. - $b[0] = 0; - if ($draw_it) { - $b[1] = $total_height; - } else { - $b[1] = $total_height + $lastline_descent; - } - $b[2] = $total_width; $b[3] = $b[1]; - $b[4] = $total_width; $b[5] = 0; - $b[6] = 0; $b[7] = 0; - - # Rotate the bounding box, then offset to the reference point: - for ($i = 0; $i < 8; $i += 2) { - $x_b = $b[$i]; - $y_b = $b[$i+1]; - $c[$i] = $x + $r00 * $x_b + $r01 * $y_b; - $c[$i+1] = $y + $r10 * $x_b + $r11 * $y_b; - } - - # Get an orthogonal (aligned with X and Y axes) bounding box around it, by - # finding the min and max X and Y: - $bbox_ref_x = $bbox_max_x = $c[0]; - $bbox_ref_y = $bbox_max_y = $c[1]; - for ($i = 2; $i < 8; $i += 2) { - $x_b = $c[$i]; - if ($x_b < $bbox_ref_x) $bbox_ref_x = $x_b; - elseif ($bbox_max_x < $x_b) $bbox_max_x = $x_b; - $y_b = $c[$i+1]; - if ($y_b < $bbox_ref_y) $bbox_ref_y = $y_b; - elseif ($bbox_max_y < $y_b) $bbox_max_y = $y_b; - } - $bbox_width = $bbox_max_x - $bbox_ref_x; - $bbox_height = $bbox_max_y - $bbox_ref_y; - - if (!$draw_it) { - # Return the bounding box, rounded up (so it always contains the text): - return array((int)ceil($bbox_width), (int)ceil($bbox_height)); - } - - $interline_step = $font_height + $line_spacing; // Line-to-line step - - # Calculate the offsets from the supplied reference point to the - # upper-left corner of the text. - # Start at the reference point at the upper left corner of the bounding - # box (bbox_ref_x, bbox_ref_y) then adjust it for the 9 point alignment. - # h,v_factor are 0,0 for top,left, .5,.5 for center,center, 1,1 for bottom,right. - # $off_x = $bbox_ref_x + $bbox_width * $h_factor - $x; - # $off_y = $bbox_ref_y + $bbox_height * $v_factor - $y; - # Then use that offset to calculate back to the supplied reference point x, y - # to get the text base point. - # $qx = $x - $off_x; - # $qy = $y - $off_y; - # Reduces to: - $qx = 2 * $x - $bbox_ref_x - $bbox_width * $h_factor; - $qy = 2 * $y - $bbox_ref_y - $bbox_height * $v_factor; - - # Check for debug callback. Don't calculate bounding box unless it is wanted. - if ($this->GetCallback('debug_textbox')) { - # Calculate the orthogonal bounding box coordinates for debug testing. - - # qx, qy is upper left corner relative to the text. - # Calculate px,py: upper left corner (absolute) of the bounding box. - # There are 4 equation sets for this, depending on the quadrant: - if ($sin_t > 0) { - if ($cos_t > 0) { - # Quadrant: 0d - 90d: - $px = $qx; $py = $qy - $total_width * $sin_t; - } else { - # Quadrant: 90d - 180d: - $px = $qx + $total_width * $cos_t; $py = $qy - $bbox_height; - } - } else { - if ($cos_t < 0) { - # Quadrant: 180d - 270d: - $px = $qx - $bbox_width; $py = $qy + $total_height * $cos_t; - } else { - # Quadrant: 270d - 360d: - $px = $qx + $total_height * $sin_t; $py = $qy; - } - } - $this->DoCallback('debug_textbox', $px, $py, $bbox_width, $bbox_height); - } - - # Since alignment is applied after rotation, which parameter is used - # to control alignment of each line within the text box varies with - # the angle. - # Angle (degrees): Line alignment controlled by: - # -45 < angle <= 45 h_align - # 45 < angle <= 135 reversed v_align - # 135 < angle <= 225 reversed h_align - # 225 < angle <= 315 v_align - if ($cos_t >= $sin_t) { - if ($cos_t >= -$sin_t) $line_align_factor = $h_factor; - else $line_align_factor = $v_factor; - } else { - if ($cos_t >= -$sin_t) $line_align_factor = 1-$v_factor; - else $line_align_factor = 1-$h_factor; - } - - # Now we have the start point, spacing and in-line alignment factor. - # We are finally ready to start drawing the text, line by line. - for ($i = 0; $i < $n_lines; $i++) { - - # For drawing TTF text, the reference point is the left edge of the - # text baseline (not the lower left corner of the bounding box). - # The following also adjusts for horizontal (relative to - # the text) alignment of the current line within the box. - # What is happening is rotation of this vector by the text angle: - # (x = (total_width - line_width) * factor, y = font_height) - - $width_factor = ($total_width - $line_widths[$i]) * $line_align_factor; - $rx = $qx + $r00 * $width_factor + $r01 * $font_height; - $ry = $qy + $r10 * $width_factor + $r11 * $font_height; - - # Finally, draw the text: - ImageTTFText($this->img, $font_size, $angle, $rx, $ry, $color, $font_file, $lines[$i]); - - # Step to position of next line. - # This is a rotation of (x=0,y=height+line_spacing) by $angle: - $qx += $r01 * $interline_step; - $qy += $r11 * $interline_step; - } - return True; - } - - /* - * ProcessText() - Wrapper for ProcessTextTTF() and ProcessTextGD(). See notes above. - * This is intended for use from within PHPlot only, and only by DrawText() and SizeText(). - * $draw_it : True to draw the text, False to just return the orthogonal width and height. - * $font : PHPlot font array, or NULL or empty string to use 'generic' - * $angle : Text angle in degrees - * $x, $y : Reference point for the text (ignored if !$draw_it) - * $color : GD color index to use for drawing the text (ignored if !$draw_it) - * $text : The text to draw or size. Put a newline between lines. - * $halign : Horizontal alignment: left, center, or right (ignored if !$draw_it) - * $valign : Vertical alignment: top, center, or bottom (ignored if !$draw_it) - * Note: Alignment is relative to the image, not the text. - * Returns: True, if drawing text, or an array of ($width, $height) if not. - */ - protected function ProcessText($draw_it, $font, $angle, $x, $y, $color, $text, $halign, $valign) - { - # Empty text case: - if ($text === '') { - if ($draw_it) return TRUE; - return array(0, 0); - } - - # Calculate width and height offset factors using the alignment args: - if ($valign == 'top') $v_factor = 0; - elseif ($valign == 'center') $v_factor = 0.5; - else $v_factor = 1.0; # 'bottom' - if ($halign == 'left') $h_factor = 0; - elseif ($halign == 'center') $h_factor = 0.5; - else $h_factor = 1.0; # 'right' - - # Apply a default font. This is mostly for external (callback) users. - if (empty($font)) $font = $this->fonts['generic']; - - if ($font['ttf']) { - return $this->ProcessTextTTF($draw_it, $font, $angle, $x, $y, $color, $text, $h_factor, $v_factor); - } - return $this->ProcessTextGD($draw_it, $font, $angle, $x, $y, $color, $text, $h_factor, $v_factor); - } - - - /* - * Draws a block of text. See comments above before ProcessText(). - * $which_font : PHPlot font array, or NULL or empty string to use 'generic' - * $which_angle : Text angle in degrees - * $which_xpos, $which_ypos: Reference point for the text - * $which_color : GD color index to use for drawing the text - * $which_text : The text to draw, with newlines (\n) between lines. - * $which_halign : Horizontal (relative to the image) alignment: left, center, or right. - * $which_valign : Vertical (relative to the image) alignment: top, center, or bottom. - */ - function DrawText($which_font, $which_angle, $which_xpos, $which_ypos, $which_color, $which_text, - $which_halign = 'left', $which_valign = 'bottom') - { - return $this->ProcessText(True, - $which_font, $which_angle, $which_xpos, $which_ypos, - $which_color, $which_text, $which_halign, $which_valign); - } - - /* - * Returns the size of block of text. This is the orthogonal width and height of a bounding - * box aligned with the X and Y axes of the text. Only for angle=0 is this the actual - * width and height of the text block, but for any angle it is the amount of space needed - * to contain the text. - * $which_font : PHPlot font array, or NULL or empty string to use 'generic' - * $which_angle : Text angle in degrees - * $which_text : The text to draw, with newlines (\n) between lines. - * Returns a two element array with: $width, $height. - * This is just a wrapper for ProcessText() - see above. - */ - function SizeText($which_font, $which_angle, $which_text) - { - // Color, position, and alignment are not used when calculating the size. - return $this->ProcessText(False, - $which_font, $which_angle, 0, 0, 1, $which_text, '', ''); - } - - -///////////////////////////////////////////// -/////////// INPUT / OUTPUT CONTROL -///////////////////////////////////////////// - - /*! - * Sets output file format. - */ - function SetFileFormat($format) - { - $asked = $this->CheckOption($format, 'jpg, png, gif, wbmp', __FUNCTION__); - if (!$asked) return False; - switch ($asked) { - case 'jpg': - $format_test = IMG_JPG; - break; - case 'png': - $format_test = IMG_PNG; - break; - case 'gif': - $format_test = IMG_GIF; - break; - case 'wbmp': - $format_test = IMG_WBMP; - break; - } - if (!(imagetypes() & $format_test)) { - return $this->PrintError("SetFileFormat(): File format '$format' not supported"); - } - $this->file_format = $asked; - return TRUE; - } - - - /*! - * Selects an input file to be used as graph background and scales or tiles this image - * to fit the sizes. - * \param input_file string Path to the file to be used (jpeg, png and gif accepted) - * \param mode string 'centeredtile', 'tile', 'scale' (the image to the graph's size) - */ - function SetBgImage($input_file, $mode='centeredtile') - { - $this->bgmode = $this->CheckOption($mode, 'tile, centeredtile, scale', __FUNCTION__); - $this->bgimg = $input_file; - return (boolean)$this->bgmode; - } - - /*! - * Selects an input file to be used as plot area background and scales or tiles this image - * to fit the sizes. - * \param input_file string Path to the file to be used (jpeg, png and gif accepted) - * \param mode string 'centeredtile', 'tile', 'scale' (the image to the graph's size) - */ - function SetPlotAreaBgImage($input_file, $mode='tile') - { - $this->plotbgmode = $this->CheckOption($mode, 'tile, centeredtile, scale', __FUNCTION__); - $this->plotbgimg = $input_file; - return (boolean)$this->plotbgmode; - } - - - /*! - * Sets the name of the file to be used as output file. - */ - function SetOutputFile($which_output_file) - { - $this->output_file = $which_output_file; - return TRUE; - } - - /*! - * Sets the output image as 'inline', that is: no Content-Type headers are sent - * to the browser. Needed if you want to embed the images. - */ - function SetIsInline($which_ii) - { - $this->is_inline = (bool)$which_ii; - return TRUE; - } - - - /*! - * Performs the actual outputting of the generated graph. - */ - function PrintImage() - { - // Browser cache stuff submitted by Thiemo Nagel - if ( (! $this->browser_cache) && (! $this->is_inline)) { - header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); - header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT'); - header('Cache-Control: no-cache, must-revalidate'); - header('Pragma: no-cache'); - } - - switch($this->file_format) { - case 'png': - if (! $this->is_inline) { - Header('Content-type: image/png'); - } - if ($this->is_inline && $this->output_file != '') { - ImagePng($this->img, $this->output_file); - } else { - ImagePng($this->img); - } - break; - case 'jpg': - if (! $this->is_inline) { - Header('Content-type: image/jpeg'); - } - if ($this->is_inline && $this->output_file != '') { - ImageJPEG($this->img, $this->output_file); - } else { - ImageJPEG($this->img); - } - break; - case 'gif': - if (! $this->is_inline) { - Header('Content-type: image/gif'); - } - if ($this->is_inline && $this->output_file != '') { - ImageGIF($this->img, $this->output_file); - } else { - ImageGIF($this->img); - } - - break; - case 'wbmp': // wireless bitmap, 2 bit. - if (! $this->is_inline) { - Header('Content-type: image/wbmp'); - } - if ($this->is_inline && $this->output_file != '') { - ImageWBMP($this->img, $this->output_file); - } else { - ImageWBMP($this->img); - } - - break; - default: - return $this->PrintError('PrintImage(): Please select an image type!'); - } - return TRUE; - } - - /*! - * Error handling for 'fatal' errors: - * $error_message Text of the error message - * Standard output from PHPlot is expected to be an image file, such as - * when handling an tag browser request. So it is not permitted to - * output text to standard output. (You should have display_errors=off) - * Here is how PHPlot handles fatal errors: - * + Write the error message into an image, and output the image. - * + If no image can be output, write nothing and produce an HTTP - * error header. - * + Trigger a user-level error containing the error message. - * If no error handler was set up, the script will log the - * error and exit with non-zero status. - * - * PrintError() and DrawError() are now equivalent. Both are provided for - * compatibility. (In earlier releases, PrintError sent the message to - * stdout only, and DrawError sent it in an image only.) - * - * This function does not return, unless the calling script has set up - * an error handler which does not exit. In that case, PrintError will - * return False. But not all of PHPlot will handle this correctly, so - * it is probably a bad idea for an error handler to return. - */ - protected function PrintError($error_message) - { - // Be sure not to loop recursively, e.g. PrintError - PrintImage - PrintError. - if (isset($this->in_error)) return FALSE; - $this->in_error = TRUE; - - // Output an image containing the error message: - if (!empty($this->img)) { - $ypos = $this->image_height/2; - $xpos = $this->image_width/2; - $bgcolor = ImageColorResolve($this->img, 255, 255, 255); - $fgcolor = ImageColorResolve($this->img, 0, 0, 0); - ImageFilledRectangle($this->img, 0, 0, $this->image_width, $this->image_height, $bgcolor); - - // Switch to built-in fonts, in case of error with TrueType fonts: - $this->SetUseTTF(FALSE); - - $this->DrawText($this->fonts['generic'], 0, $xpos, $ypos, $fgcolor, - wordwrap($error_message), 'center', 'center'); - - $this->PrintImage(); - } elseif (! $this->is_inline) { - Header('HTTP/1.0 500 Internal Server Error'); - } - trigger_error($error_message, E_USER_ERROR); - unset($this->in_error); - return FALSE; # In case error handler returns, rather than doing exit(). - } - - /*! - * Display an error message and exit. - * This is provided for backward compatibility only. Use PrintError() instead. - * $error_message Text of the error message - * $where_x, $where_y Ignored, provided for compatibility. - */ - protected function DrawError($error_message, $where_x = NULL, $where_y = NULL) - { - return $this->PrintError($error_message); - } - -///////////////////////////////////////////// -/////////// LABELS -///////////////////////////////////////////// - - - /*! - * Sets position for X labels following data points. - */ - function SetXDataLabelPos($which_xdlp) - { - $which_xdlp = $this->CheckOption($which_xdlp, 'plotdown, plotup, both, xaxis, all, none', - __FUNCTION__); - if (!$which_xdlp) return FALSE; - $this->x_data_label_pos = $which_xdlp; - - return TRUE; - } - - /* - * Sets position for Y data labels. - * For bars and stackedbars, these are labels above the bars with the Y values. - * Accepted positions are: plotin, plotstack, none. - * For horizontal bars, these are the labels along the Y axis or sides. - * Accepted positions are: plotleft, plotright, both, none. - */ - function SetYDataLabelPos($which_ydlp) - { - $which_ydlp = $this->CheckOption($which_ydlp, 'plotin, plotstack, none, plotleft, plotright, both', - __FUNCTION__); - if (!$which_ydlp) return FALSE; - $this->y_data_label_pos = $which_ydlp; - - return TRUE; - } - - /*! - * Sets position for X labels following ticks (hence grid lines) - */ - function SetXTickLabelPos($which_xtlp) - { - $which_xtlp = $this->CheckOption($which_xtlp, 'plotdown, plotup, both, xaxis, all, none', - __FUNCTION__); - if (!$which_xtlp) return FALSE; - $this->x_tick_label_pos = $which_xtlp; - - return TRUE; - } - - /*! - * Sets position for Y labels following ticks (hence grid lines) - */ - function SetYTickLabelPos($which_ytlp) - { - $this->y_tick_label_pos = $this->CheckOption($which_ytlp, 'plotleft, plotright, both, yaxis, all, none', - __FUNCTION__); - return (boolean)$this->y_tick_label_pos; - } - - /*! - * Sets type for tick and data labels on X or Y axis. This is meant for use by - * SetXLabelType and SetYLabelType, but can also be called directly. - * $mode : 'x', 'y', 'xd', or 'yd' - which type of label to configure. - * 'x' and 'y' set the type for tick labels, and the default type for data labels - * if they are not separately configured. 'xd' and 'yd' set the type for data labels. - * $args : Variable arguments, passed as an array. - * [0] = $type (required) : Label type. 'data', 'time', 'printf', or 'custom'. - * For type 'data': - * [1] = $precision (optional). Numeric precision. Can also be set by SetPrecision[XY](). - * [2] = $prefix (optional) - prefix string for labels. - * [3] = $suffix (optional) - suffix string for labels. This replaces data_units_text. - * For type 'time': - * [1] = $format for strftime (optional). Can also be set by Set[XY]TimeFormat(). - * For type 'printf': - * [1] = $format (optional) for sprintf. - * For type 'custom': - * [1] = $callback (required) - Custom function or array of (instance,method) to call. - * [2] = $argument (optional) - Pass-through argument for the formatting function. - */ - protected function SetLabelType($mode, $args) - { - if (!$this->CheckOption($mode, 'x, y, xd, yd', __FUNCTION__)) - return FALSE; - - $type = isset($args[0]) ? $args[0] : ''; - $format =& $this->label_format[$mode]; // Shorthand reference to format storage variables - switch ($type) { - case 'data': - if (isset($args[1])) - $format['precision'] = $args[1]; - elseif (!isset($format['precision'])) - $format['precision'] = 1; - $format['prefix'] = isset($args[2]) ? $args[2] : ''; - $format['suffix'] = isset($args[3]) ? $args[3] : ''; - break; - - case 'time': - if (isset($args[1])) - $format['time_format'] = $args[1]; - elseif (!isset($format['time_format'])) - $format['time_format'] = '%H:%M:%S'; - break; - - case 'printf': - if (isset($args[1])) - $format['printf_format'] = $args[1]; - elseif (!isset($format['printf_format'])) - $format['printf_format'] = '%e'; - break; - - case 'custom': - if (isset($args[1])) { - $format['custom_callback'] = $args[1]; - $format['custom_arg'] = isset($args[2]) ? $args[2] : NULL; - } else { - $type = ''; // Error, 'custom' without a function, set to no-format mode. - } - break; - - case '': - case 'title': // Retained for backwards compatibility? - break; - - default: - $this->CheckOption($type, 'data, time, printf, custom', __FUNCTION__); - $type = ''; - } - $format['type'] = $type; - return (boolean)$type; - } - - - /* - * Select label formating for X tick labels, and for X data labels - * (unless SetXDataLabelType was called). - * See SetLabelType() for details. - */ - function SetXLabelType() // Variable arguments: $type, ... - { - $args = func_get_args(); - return $this->SetLabelType('x', $args); - } - - /* - * Select label formatting for X data labels, overriding SetXLabelType. - */ - function SetXDataLabelType() // Variable arguments: $type, ... - { - $args = func_get_args(); - return $this->SetLabelType('xd', $args); - } - - /* - * Select label formating for Y tick labels, and for Y data labels - * (unless SetYDataLabelType was called). - * See SetLabelType() for details. - */ - function SetYLabelType() // Variable arguments: $type, ... - { - $args = func_get_args(); - return $this->SetLabelType('y', $args); - } - - /* - * Select label formatting for Y data labels, overriding SetYLabelType. - */ - function SetYDataLabelType() // Variable arguments: $type, ... - { - $args = func_get_args(); - return $this->SetLabelType('yd', $args); - } - - function SetXTimeFormat($which_xtf) - { - $this->label_format['x']['time_format'] = $which_xtf; - return TRUE; - } - - function SetYTimeFormat($which_ytf) - { - $this->label_format['y']['time_format'] = $which_ytf; - return TRUE; - } - - function SetNumberFormat($decimal_point, $thousands_sep) - { - $this->decimal_point = $decimal_point; - $this->thousands_sep = $thousands_sep; - return TRUE; - } - - - function SetXLabelAngle($which_xla) - { - $this->x_label_angle = $which_xla; - return TRUE; - } - - function SetYLabelAngle($which_yla) - { - $this->y_label_angle = $which_yla; - return TRUE; - } - - // If used, this sets the angle for X Data Labels only, separately from tick labels. - function SetXDataLabelAngle($which_xdla) - { - $this->x_data_label_angle = $which_xdla; - return TRUE; - } - - // Sets the angle for Y Data Labels. Unlike X Data Labels, these default to zero. - function SetYDataLabelAngle($which_ydla) - { - $this->y_data_label_angle = $which_ydla; - return TRUE; - } - - -///////////////////////////////////////////// -/////////// MISC -///////////////////////////////////////////// - - /*! - * Checks the validity of an option. - * $which_opt String to check, such as the provided value of a function argument. - * $which_acc String of accepted choices. Must be lower-case, and separated - * by exactly ', ' (comma, space). - * $which_func Name of the calling function, for error messages. - * Returns the supplied option value, downcased and trimmed, if it is valid. - * Reports an error if the supplied option is not valid. - */ - protected function CheckOption($which_opt, $which_acc, $which_func) - { - $asked = strtolower(trim($which_opt)); - - # Look for the supplied value in a comma/space separated list. - if (strpos(", $which_acc,", ", $asked,") !== False) - return $asked; - - $this->PrintError("$which_func(): '$which_opt' not in available choices: '$which_acc'."); - return NULL; - } - - /* - * Checks the validity of an array of options. - * $opt Array or string to check. - * $acc String of accepted choices. Must be lower-case, and separated - * by exactly ', ' (comma, space). - * $func Name of the calling function, for error messages. - * Returns a array option value(s), downcased and trimmed, if all entries in $opt are valid. - * Reports an error if any supplied option is not valid. Returns NULL if the error handler returns. - */ - protected function CheckOptionArray($opt, $acc, $func) - { - $opt_array = (array)$opt; - $result = array(); - foreach ($opt_array as $option) { - $choice = $this->CheckOption($option, $acc, $func); - if (is_null($choice)) return NULL; // In case CheckOption error handler returns - $result[] = $choice; - } - return $result; - } - - /* - * Check compatibility of a plot type and data type. - * This is called by the plot-type-specific drawing functions. - * $valid_types String of supported data types. Multiple values must be - * separated by exactly ', ' (comma, space). - * Returns True if the type is valid for this plot. - * Reports an error if the data type is not value. If the error is handled and - * the handler returns, this returns False. - */ - protected function CheckDataType($valid_types) - { - if (strpos(", $valid_types,", ", $this->data_type,") !== False) - return TRUE; - - $this->PrintError("Data type '$this->data_type' is not valid for '$this->plot_type' plots." - . " Supported data type(s): '$valid_types'"); - return FALSE; - } - - /* - * Decode the data type into variables used to determine how to process a data array. - * Returns a numeric-indexed array with these elements in order: - * swapped_xy (boolean) True if Y is the independent variable, X dependent (e.g. horizontal bars). - * implied_x (boolean) True if data array has an implied X value for each set of Y. - * implied_y (boolean) True if data array has an implied Y value for each set of X. - * err_bars (boolean) True if data array contains error bars values for each point. - * Note these are not independent. implied_y means swapped_xy, and implied_x means !swapped_xy. - * Also some possibilities are reserved for future use: swapped_xy && !implied_y would be a - * future swapped X/Y equivalent to data-data or data-data-error. - */ - protected function DecodeDataType() - { - $swapped_xy = ($this->data_type == 'text-data-yx'); // Only swapped type available now - $implied_x = ($this->data_type == 'text-data'); - $implied_y = ($this->data_type == 'text-data-yx'); - $err_bars = ($this->data_type == 'data-data-error'); - - return array($swapped_xy, $implied_x, $implied_y, $err_bars); - } - - /*! - * \note Submitted by Thiemo Nagel - */ - function SetBrowserCache($which_browser_cache) - { - $this->browser_cache = $which_browser_cache; - return TRUE; - } - - /*! - * Whether to show the final image or not - */ - function SetPrintImage($which_pi) - { - $this->print_image = $which_pi; - return TRUE; - } - - /*! - * Sets the graph's legend. If argument is not an array, appends it to the legend. - */ - function SetLegend($which_leg) - { - if (is_array($which_leg)) { // use array - $this->legend = $which_leg; - } elseif (! is_null($which_leg)) { // append string - $this->legend[] = $which_leg; - } else { - return $this->PrintError("SetLegend(): argument must not be null."); - } - return TRUE; - } - - /*! - * Specifies the position of the legend's upper/leftmost corner, - * in pixel (device) coordinates. - */ - function SetLegendPixels($which_x, $which_y) - { - $this->legend_x_pos = $which_x; - $this->legend_y_pos = $which_y; - // Make sure this is unset, meaning we have pixel coords: - unset($this->legend_xy_world); - - return TRUE; - } - - /*! - * Specifies the position of the legend's upper/leftmost corner, - * in world (data space) coordinates. - * Since the scale factor to convert world to pixel coordinates - * is probably not available, set a flag and defer conversion - * to later. - */ - function SetLegendWorld($which_x, $which_y) - { - $this->legend_x_pos = $which_x; - $this->legend_y_pos = $which_y; - $this->legend_xy_world = True; - - return TRUE; - } - - /* - * Set legend text alignment, color box alignment, and style options - * $text_align accepts 'left' or 'right'. - * $colorbox_align accepts 'left', 'right', 'none', or missing/empty. If missing or empty, - * the same alignment as $text_align is used. Color box is positioned first. - * $style is reserved for future use. - */ - function SetLegendStyle($text_align, $colorbox_align = '', $style = '') - { - $this->legend_text_align = $this->CheckOption($text_align, 'left, right', __FUNCTION__); - if (empty($colorbox_align)) - $this->legend_colorbox_align = $this->legend_text_align; - else - $this->legend_colorbox_align = $this->CheckOption($colorbox_align, 'left, right, none', __FUNCTION__); - return ((boolean)$this->legend_text_align && (boolean)$this->legend_colorbox_align); - } - - /* - * Set border for the plot area. - * Accepted values are: left, right, top, bottom, sides, none, full or an array of those. - */ - function SetPlotBorderType($pbt) - { - $this->plot_border_type = $this->CheckOptionArray($pbt, 'left, right, top, bottom, sides, none, full', - __FUNCTION__); - return !empty($this->plot_border_type); - } - - /* - * Set border style for the image. - * Accepted values are: raised, plain, solid, none - * 'solid' is the same as 'plain' except it fixes the color (see DrawImageBorder) - */ - function SetImageBorderType($sibt) - { - $this->image_border_type = $this->CheckOption($sibt, 'raised, plain, solid, none', __FUNCTION__); - return (boolean)$this->image_border_type; - } - - /* - * Set border width for the image. - */ - function SetImageBorderWidth($width) - { - $this->image_border_width = $width; - return TRUE; - } - - /*! - * \param dpab bool - */ - function SetDrawPlotAreaBackground($dpab) - { - $this->draw_plot_area_background = (bool)$dpab; - return TRUE; - } - - - /*! - * \param dyg bool - */ - function SetDrawYGrid($dyg) - { - $this->draw_y_grid = (bool)$dyg; - return TRUE; - } - - - /*! - * \param dxg bool - */ - function SetDrawXGrid($dxg) - { - $this->draw_x_grid = (bool)$dxg; - return TRUE; - } - - - /*! - * \param ddg bool - */ - function SetDrawDashedGrid($ddg) - { - $this->dashed_grid = (bool)$ddg; - return TRUE; - } - - - /*! - * \param dxdl bool - */ - function SetDrawXDataLabelLines($dxdl) - { - $this->draw_x_data_label_lines = (bool)$dxdl; - return TRUE; - } - - /*! - * Sets the graph's title. - * TODO: add parameter to choose title placement: left, right, centered= - */ - function SetTitle($which_title) - { - $this->title_txt = $which_title; - return TRUE; - } - - /*! - * Sets the X axis title and position. - */ - function SetXTitle($which_xtitle, $which_xpos = 'plotdown') - { - if ($which_xtitle == '') - $which_xpos = 'none'; - - $this->x_title_pos = $this->CheckOption($which_xpos, 'plotdown, plotup, both, none', __FUNCTION__); - if (!$this->x_title_pos) return FALSE; - $this->x_title_txt = $which_xtitle; - return TRUE; - } - - - /*! - * Sets the Y axis title and position. - */ - function SetYTitle($which_ytitle, $which_ypos = 'plotleft') - { - if ($which_ytitle == '') - $which_ypos = 'none'; - - $this->y_title_pos = $this->CheckOption($which_ypos, 'plotleft, plotright, both, none', __FUNCTION__); - if (!$this->y_title_pos) return FALSE; - $this->y_title_txt = $which_ytitle; - return TRUE; - } - - /*! - * Sets the size of the drop shadow for bar and pie charts. - * \param which_s int Size in pixels. - */ - function SetShading($which_s) - { - $this->shading = (int)$which_s; - return TRUE; - } - - function SetPlotType($which_pt) - { - $this->plot_type = $this->CheckOption($which_pt, 'bars, stackedbars, lines, linepoints,' - . ' area, points, pie, thinbarline, squared, stackedarea', - __FUNCTION__); - return (boolean)$this->plot_type; - } - - /*! - * Sets the position of Y axis. - * \param pos int Position in world coordinates. - */ - function SetYAxisPosition($pos) - { - $this->y_axis_position = (int)$pos; - return TRUE; - } - - /*! - * Sets the position of X axis. - * \param pos int Position in world coordinates. - */ - function SetXAxisPosition($pos) - { - $this->x_axis_position = (int)$pos; - return TRUE; - } - - - function SetXScaleType($which_xst) - { - $this->xscale_type = $this->CheckOption($which_xst, 'linear, log', __FUNCTION__); - return (boolean)$this->xscale_type; - } - - function SetYScaleType($which_yst) - { - $this->yscale_type = $this->CheckOption($which_yst, 'linear, log', __FUNCTION__); - return (boolean)$this->yscale_type; - } - - function SetPrecisionX($which_prec) - { - return $this->SetXLabelType('data', $which_prec); - } - - function SetPrecisionY($which_prec) - { - return $this->SetYLabelType('data', $which_prec); - } - - function SetErrorBarLineWidth($which_seblw) - { - $this->error_bar_line_width = $which_seblw; - return TRUE; - } - - function SetLabelScalePosition($which_blp) - { - //0 to 1 - $this->label_scale_position = $which_blp; - return TRUE; - } - - function SetErrorBarSize($which_ebs) - { - //in pixels - $this->error_bar_size = $which_ebs; - return TRUE; - } - - /*! - * Can be one of: 'tee', 'line' - */ - function SetErrorBarShape($which_ebs) - { - $this->error_bar_shape = $this->CheckOption($which_ebs, 'tee, line', __FUNCTION__); - return (boolean)$this->error_bar_shape; - } - - /* - * Synchronize the point shape and point size arrays. - * This is called just before drawing any plot that needs 'points'. - */ - protected function CheckPointParams() - { - // Make both point_shapes and point_sizes the same size, by padding the smaller. - $ps = count($this->point_sizes); - $pt = count($this->point_shapes); - - if ($ps < $pt) { - $this->pad_array($this->point_sizes, $pt); - $this->point_counts = $pt; - } else if ($ps > $pt) { - $this->pad_array($this->point_shapes, $ps); - $this->point_counts = $ps; - } else { - $this->point_counts = $ps; - } - - // Note: PHPlot used to check and adjust point_sizes to be an even number here, - // for all 'diamond' and 'triangle' shapes. The reason for this having been - // lost, and the current maintainer seeing no sense it doing this for only - // some shapes, the code has been removed. But see what DrawDot() does. - } - - /*! - * Sets point shape for each data set via an array. - * For a list of valid shapes, see the CheckOption call below. - * The point shape and point sizes arrays are synchronized before drawing a graph - * that uses points. See CheckPointParams() - */ - function SetPointShapes($which_pt) - { - if (is_array($which_pt)) { - // Use provided array: - $this->point_shapes = $which_pt; - } elseif (!is_null($which_pt)) { - // Make the single value into an array: - $this->point_shapes = array($which_pt); - } - - // Validate all the shapes. This list must agree with DrawDot(). - foreach ($this->point_shapes as $shape) - { - if (!$this->CheckOption($shape, 'halfline, line, plus, cross, rect, circle, dot,' - . ' diamond, triangle, trianglemid, delta, yield, star, hourglass,' - . ' bowtie, target, box, home, up, down, none', __FUNCTION__)) - return FALSE; - } - return TRUE; - } - - /*! - * Sets the point size for point plots. - * The point shape and point sizes arrays are synchronized before drawing a graph - * that uses points. See CheckPointParams() - */ - function SetPointSizes($which_ps) - { - if (is_array($which_ps)) { - // Use provided array: - $this->point_sizes = $which_ps; - } elseif (!is_null($which_ps)) { - // Make the single value into an array: - $this->point_sizes = array($which_ps); - } - return TRUE; - } - - /*! - * Tells not to draw lines for missing Y data. Only works with 'lines' and 'squared' plots. - * \param bl bool - */ - function SetDrawBrokenLines($bl) - { - $this->draw_broken_lines = (bool)$bl; - return TRUE; - } - - - /* - * Set the data type, which defines the structure of the data array - * text-data: ('label', y1, y2, y3, ...) - * text-data-single: ('label', data), for some pie charts. - * data-data: ('label', x, y1, y2, y3, ...) - * data-data-error: ('label', x1, y1, e1+, e2-, y2, e2+, e2-, y3, e3+, e3-, ...) - * text-data-yx: ('label', x1, x2, x3, ...) - */ - function SetDataType($which_dt) - { - //The next four lines are for past compatibility. - if ($which_dt == 'text-linear') { $which_dt = 'text-data'; } - elseif ($which_dt == 'linear-linear') { $which_dt = 'data-data'; } - elseif ($which_dt == 'linear-linear-error') { $which_dt = 'data-data-error'; } - elseif ($which_dt == 'text-data-pie') { $which_dt = 'text-data-single'; } - - $this->data_type = $this->CheckOption($which_dt, 'text-data, text-data-single, '. - 'data-data, data-data-error, text-data-yx', - __FUNCTION__); - return (boolean)$this->data_type; - } - - /*! - * Copy the array passed as data values. We convert to numerical indexes, for its - * use for (or while) loops, which sometimes are faster. Performance improvements - * vary from 28% in DrawLines() to 49% in DrawArea() for plot drawing functions. - */ - function SetDataValues($which_dv) - { - $this->num_data_rows = count($which_dv); - $this->total_records = 0; // Perform some useful calculations. - $this->records_per_group = 1; - for ($i = 0, $recs = 0; $i < $this->num_data_rows; $i++) { - // Copy - $this->data[$i] = array_values($which_dv[$i]); // convert to numerical indices. - - // Compute some values - $recs = count($this->data[$i]); - $this->total_records += $recs; - - if ($recs > $this->records_per_group) - $this->records_per_group = $recs; - - $this->num_recs[$i] = $recs; - } - return TRUE; - } - - /*! - * Pad styles arrays for later use by plot drawing functions: - * This removes the need for $max_data_colors, etc. and $color_index = $color_index % $max_data_colors - * in DrawBars(), DrawLines(), etc. - */ - protected function PadArrays() - { - $this->pad_array($this->line_widths, $this->records_per_group); - $this->pad_array($this->line_styles, $this->records_per_group); - - $this->pad_array($this->data_colors, $this->records_per_group); - $this->pad_array($this->data_border_colors, $this->records_per_group); - $this->pad_array($this->error_bar_colors, $this->records_per_group); - - $this->SetDataColors(); - $this->SetDataBorderColors(); - $this->SetErrorBarColors(); - - return TRUE; - } - - /*! - * Pads an array with itself. This only works on 0-based sequential integer indexed arrays. - * \param arr array Original array (reference), or scalar. - * \param size int Minimum size of the resulting array. - * If $arr is a scalar, it will be converted first to a single element array. - * If $arr has at least $size elements, it is unchanged. - * Otherwise, append elements of $arr to itself until it reaches $size elements. - */ - protected function pad_array(&$arr, $size) - { - if (! is_array($arr)) { - $arr = array($arr); - } - $n = count($arr); - $base = 0; - while ($n < $size) $arr[$n++] = $arr[$base++]; - } - - /* - * Format a floating-point number. - * This is like PHP's number_format, but uses class variables for separators. - * The separators will default to locale-specific values, if available. - * Note: This method should be 'protected', but is called from test script(s). - */ - function number_format($number, $decimals=0) - { - if (!isset($this->decimal_point) || !isset($this->thousands_sep)) { - // Load locale-specific values from environment, unless disabled: - if (empty($this->locale_override)) - @setlocale(LC_ALL, ''); - // Fetch locale settings: - $locale = @localeconv(); - if (!empty($locale) && isset($locale['decimal_point']) && - isset($locale['thousands_sep'])) { - $this->decimal_point = $locale['decimal_point']; - $this->thousands_sep = $locale['thousands_sep']; - } else { - // Locale information not available. - $this->decimal_point = '.'; - $this->thousands_sep = ','; - } - } - return number_format($number, $decimals, $this->decimal_point, $this->thousands_sep); - } - - /* - * Register a callback (hook) function - * reason - A pre-defined name where a callback can be defined. - * function - The name of a function to register for callback, or an instance/method - * pair in an array (see 'callbacks' in the PHP reference manual). - * arg - Optional argument to supply to the callback function when it is triggered. - * (Often called "clientData") - * Returns: True if the callback reason is valid, else False. - */ - function SetCallback($reason, $function, $arg = NULL) - { - // Use array_key_exists because valid reason keys have NULL as value. - if (!array_key_exists($reason, $this->callbacks)) - return False; - $this->callbacks[$reason] = array($function, $arg); - return True; - } - - /* - * Return the name of a function registered for callback. See SetCallBack. - * reason - A pre-defined name where a callback can be defined. - * Returns the current callback function (name or array) for the given reason, - * or False if there was no active callback or the reason is not valid. - * Note you can safely test the return value with a simple 'if', as - * no valid function name evaluates to false. - */ - function GetCallback($reason) - { - if (isset($this->callbacks[$reason])) - return $this->callbacks[$reason][0]; - return False; - } - - /* - * Un-register (remove) a function registered for callback. - * reason - A pre-defined name where a callback can be defined. - * Returns: True if it was a valid callback reason, else False. - * Note: Returns True whether or not there was a callback registered. - */ - function RemoveCallback($reason) - { - if (!array_key_exists($reason, $this->callbacks)) - return False; - $this->callbacks[$reason] = NULL; - return True; - } - - /* - * Invoke a callback, if one is registered. - * Accepts a variable number of arguments >= 1: - * reason : A string naming the callback. - * ... : Zero or more additional arguments to be passed to the - * callback function, after the passthru argument: - * callback_function($image, $passthru, ...) - * Returns: nothing. - */ - protected function DoCallback() # Note: Variable arguments - { - $args = func_get_args(); - $reason = $args[0]; - if (!isset($this->callbacks[$reason])) - return; - list($function, $args[0]) = $this->callbacks[$reason]; - array_unshift($args, $this->img); - # Now args[] looks like: img, passthru, extra args... - call_user_func_array($function, $args); - } - - -////////////////////////////////////////////////////////// -/////////// DATA ANALYSIS, SCALING AND TRANSLATION -////////////////////////////////////////////////////////// - - /* - * Analyzes the data array and calculates the minimum and maximum values. - * In this function, IV refers to the independent variable, and DV the dependent variable. - * For most plots, IV is X and DV is Y. For swapped X/Y plots, IV is Y and DV is X. - * At the end of the function, IV and DV ranges get assigned into X or Y. - * - * Plot types 'stackedbars' and 'stackedarea' are special cases, because the bars or area always - * start at 0 (although they may be clipped below the X axis, if the axis is moved up), - * absolute values are used, and the Y values in each row accumulate. - * - * This calculates min_x, max_x, min_y, and max_y. It also calculates two arrays - * data_min[] and data_max[] with per-row min and max values. These are used for - * data label lines. For normal (unswapped) data, these are the Y range for each X. - * For swapped X/Y data, they are the X range for each Y. - * - * Note: This method should be 'protected', but is called from test script(s). - */ - function FindDataLimits() - { - # Determine how to process the data array: - list($swapped_xy, $implied_x, $implied_y, $err_bars) = $this->DecodeDataType(); - // process_iv is true if the data array contains independent variable values: - $process_iv = !($implied_x || $implied_y); - - # Special case processing for certain plot types: - $process_stacked = ($this->plot_type == 'stackedbars' || $this->plot_type == 'stackedarea'); - $abs_val = ($this->plot_type == 'area' || $this->plot_type == 'pie'); - - # These need to be initialized in case there are multiple plots and - # missing data points. - $this->data_min = array(); - $this->data_max = array(); - - # Independent values are in the data array or assumed? - if ($process_iv) { - $all_iv = array(); - } else { - $all_iv = array(0, $this->num_data_rows - 1); - } - - # Process all rows of data: - for ($i = 0; $i < $this->num_data_rows; $i++) { - $n_vals = $this->num_recs[$i]; - $j = 1; # Skips label at [0] - - if ($process_iv) { - $all_iv[] = (double)$this->data[$i][$j++]; - } - - if ($process_stacked) { - $all_dv = array(0, 0); # Min (always 0) and max - } else { - $all_dv = array(); - } - while ($j < $n_vals) { - if (is_numeric($this->data[$i][$j])) { - $val = (double)$this->data[$i][$j++]; - - if ($err_bars) { - $all_dv[] = $val + (double)$this->data[$i][$j++]; - $all_dv[] = $val - (double)$this->data[$i][$j++]; - } elseif ($process_stacked) { - $all_dv[1] += abs($val); - } elseif ($abs_val) { - $all_dv[] = abs($val); - } else { - $all_dv[] = $val; - } - } else { # Missing DV value - $j++; - if ($err_bars) $j += 2; - } - } - if (!empty($all_dv)) { - $this->data_min[$i] = min($all_dv); # Store per-row DV range - $this->data_max[$i] = max($all_dv); - } - } - - if ($swapped_xy) { - // Assign min and max for swapped X/Y plots: IV=Y and DV=X - $this->min_y = min($all_iv); - $this->max_y = max($all_iv); - if (empty($this->data_min)) { # Guard against regressive case: No X at all - $this->min_x = 0; - $this->max_x = 0; - } else { - $this->min_x = min($this->data_min); # Store global X range - $this->max_x = max($this->data_max); - } - } else { - // Assign min and max for normal plots: IV=X and DV=Y - $this->min_x = min($all_iv); - $this->max_x = max($all_iv); - if (empty($this->data_min)) { # Guard against regressive case: No Y at all - $this->min_y = 0; - $this->max_y = 0; - } else { - $this->min_y = min($this->data_min); # Store global Y range - $this->max_y = max($this->data_max); - } - } - - if ($this->GetCallback('debug_scale')) { - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'min_x' => $this->min_x, 'min_y' => $this->min_y, - 'max_x' => $this->max_x, 'max_y' => $this->max_y)); - } - return TRUE; - } - - /*! - * Calculates image margins on the fly from title positions and sizes, - * and tick labels positions and sizes. - * - * A picture of the locations of elements and spacing can be found in the - * PHPlot Reference Manual. - * - * Calculates the following (class variables unless noted): - * - * Plot area margins (see note below): - * y_top_margin - * y_bot_margin - * x_left_margin - * x_right_margin - * - * Title sizes (these are now local, not class variables, since they are not used elsewhere): - * title_height : Height of main title - * x_title_height : Height of X axis title, 0 if no X title - * y_title_width : Width of Y axis title, 0 if no Y title - * - * Tick/Data label offsets, relative to plot_area: - * x_label_top_offset, x_label_bot_offset, x_label_axis_offset - * y_label_left_offset, y_label_right_offset, y_label_axis_offset - * - * Title offsets, relative to plot area: - * x_title_top_offset, x_title_bot_offset - * y_title_left_offset, y_title_left_offset - * title_offset (for main title, relative to image edge) - * - * Note: The margins are calculated, but not stored, if margins or plot area were - * set by the user with SetPlotAreaPixels or SetMarginsPixels. The margin - * calculation is mixed in with the offset variables, so it doesn't seem worth the - * trouble to separate them. - * - * If the $maximize argument is true, we use the full image size, minus safe_margin - * and main title, for the plot. This is for pie charts which have no axes or X/Y titles. - */ - protected function CalcMargins($maximize) - { - // This is the line-to-line or line-to-text spacing: - $gap = $this->safe_margin; - // Initial margin on each side takes into account a possible image border. - // For compatibility, if border is 1 or 2, don't increase the margins. - $base_margin = max($gap, $this->GetImageBorderWidth() + 3); - $this->title_offset = $base_margin; // For use in DrawTitle - - // Minimum margin on each side. This reduces the chance that the - // right-most tick label (for example) will run off the image edge - // if there are no titles on that side. - $min_margin = 2 * $gap + $base_margin; - - // Calculate the title sizes: - list($unused, $title_height) = $this->SizeText($this->fonts['title'], 0, $this->title_txt); - list($unused, $x_title_height) = $this->SizeText($this->fonts['x_title'], 0, $this->x_title_txt); - list($y_title_width, $unused) = $this->SizeText($this->fonts['y_title'], 90, $this->y_title_txt); - - // Special case for maximum area usage with no X/Y titles or labels, only main title: - if ($maximize) { - if (!isset($this->x_left_margin)) - $this->x_left_margin = $base_margin; - if (!isset($this->x_right_margin)) - $this->x_right_margin = $base_margin; - if (!isset($this->y_top_margin)) { - $this->y_top_margin = $base_margin; - if ($title_height > 0) - $this->y_top_margin += $title_height + $gap; - } - if (!isset($this->y_bot_margin)) - $this->y_bot_margin = $base_margin; - - return TRUE; - } - - // Make local variables for these. (They get used a lot and I'm tired of this, this, this.) - $x_tick_label_pos = $this->x_tick_label_pos; - $x_data_label_pos = $this->x_data_label_pos; - $x_tick_pos = $this->x_tick_pos; - $x_tick_len = $this->x_tick_length; - $y_tick_label_pos = $this->y_tick_label_pos; - $y_tick_pos = $this->y_tick_pos; - $y_tick_len = $this->y_tick_length; - $y_data_label_pos = $this->y_data_label_pos; - - // For X/Y tick and label position of 'xaxis' or 'yaxis', determine if the axis happens to be - // on an edge of a plot. If it is, we need to account for the margins there. - if ($this->x_axis_position <= $this->plot_min_y) - $x_axis_pos = 'bottom'; - elseif ($this->x_axis_position >= $this->plot_max_y) - $x_axis_pos = 'top'; - else - $x_axis_pos = 'none'; - if ($this->y_axis_position <= $this->plot_min_x) - $y_axis_pos = 'left'; - elseif ($this->y_axis_position >= $this->plot_max_x) - $y_axis_pos = 'right'; - else - $y_axis_pos = 'none'; - - // Calculate the heights for X tick and data labels, and the max (used if they are overlaid): - $x_data_label_height = ($x_data_label_pos == 'none') ? 0 : $this->CalcMaxDataLabelSize('x'); - $x_tick_label_height = ($x_tick_label_pos == 'none') ? 0 : $this->CalcMaxTickLabelSize('x'); - $x_max_label_height = max($x_data_label_height, $x_tick_label_height); - - // Calculate the space needed above and below the plot for X tick and X data labels: - - // Above the plot: - $tick_labels_above = ($x_tick_label_pos == 'plotup' || $x_tick_label_pos == 'both' - || ($x_tick_label_pos == 'xaxis' && $x_axis_pos == 'top')); - $data_labels_above = ($x_data_label_pos == 'plotup' || $x_data_label_pos == 'both'); - if ($tick_labels_above) { - if ($data_labels_above) { - $label_height_above = $x_max_label_height; - } else { - $label_height_above = $x_tick_label_height; - } - } elseif ($data_labels_above) { - $label_height_above = $x_data_label_height; - } else { - $label_height_above = 0; - } - - // Below the plot: - $tick_labels_below = ($x_tick_label_pos == 'plotdown' || $x_tick_label_pos == 'both' - || ($x_tick_label_pos == 'xaxis' && $x_axis_pos == 'bottom')); - $data_labels_below = ($x_data_label_pos == 'plotdown' || $x_data_label_pos == 'both'); - if ($tick_labels_below) { - if ($data_labels_below) { - $label_height_below = $x_max_label_height; - } else { - $label_height_below = $x_tick_label_height; - } - } elseif ($data_labels_below) { - $label_height_below = $x_data_label_height; - } else { - $label_height_below = 0; - } - - // Calculate the width for Y tick and data labels, if on, and the max: - // Note CalcMaxDataLabelSize('y') returns 0 except for swapped X/Y plots. - $y_data_label_width = ($y_data_label_pos == 'none') ? 0 : $this->CalcMaxDataLabelSize('y'); - $y_tick_label_width = ($y_tick_label_pos == 'none') ? 0 : $this->CalcMaxTickLabelSize('y'); - $y_max_label_width = max($y_data_label_width, $y_tick_label_width); - - // Calculate the space needed left and right of the plot for Y tick and Y data labels: - // (Y data labels here are for swapped X/Y plots such has horizontal bars) - - // Left of the plot: - $tick_labels_left = ($y_tick_label_pos == 'plotleft' || $y_tick_label_pos == 'both' - || ($y_tick_label_pos == 'yaxis' && $y_axis_pos == 'left')); - $data_labels_left = ($y_data_label_pos == 'plotleft' || $y_data_label_pos == 'both'); - if ($tick_labels_left) { - if ($data_labels_left) { - $label_width_left = $y_max_label_width; - } else { - $label_width_left = $y_tick_label_width; - } - } elseif ($data_labels_left) { - $label_width_left = $y_data_label_width; - } else { - $label_width_left = 0; - } - - // Right of the plot: - $tick_labels_right = ($y_tick_label_pos == 'plotright' || $y_tick_label_pos == 'both' - || ($y_tick_label_pos == 'yaxis' && $y_axis_pos == 'right')); - $data_labels_right = ($y_data_label_pos == 'plotright' || $y_data_label_pos == 'both'); - if ($tick_labels_right) { - if ($data_labels_right) { - $label_width_right = $y_max_label_width; - } else { - $label_width_right = $y_tick_label_width; - } - } elseif ($data_labels_right) { - $label_width_right = $y_data_label_width; - } else { - $label_width_right = 0; - } - - ///////// Calculate margins: - - // Calculating Top and Bottom margins: - // y_top_margin: Main title, Upper X title, X ticks and tick labels, and X data labels: - // y_bot_margin: Lower title, ticks and tick labels, and data labels: - $top_margin = $base_margin; - $bot_margin = $base_margin; - $this->x_title_top_offset = $gap; - $this->x_title_bot_offset = $gap; - - // Space for main title? - if ($title_height > 0) - $top_margin += $title_height + $gap; - - // Space for X Title? - if ($x_title_height > 0) { - $pos = $this->x_title_pos; - if ($pos == 'plotup' || $pos == 'both') - $top_margin += $x_title_height + $gap; - if ($pos == 'plotdown' || $pos == 'both') - $bot_margin += $x_title_height + $gap; - } - - // Space for X Labels above the plot? - if ($label_height_above > 0) { - $top_margin += $label_height_above + $gap; - $this->x_title_top_offset += $label_height_above + $gap; - } - - // Space for X Labels below the plot? - if ($label_height_below > 0) { - $bot_margin += $label_height_below + $gap; - $this->x_title_bot_offset += $label_height_below + $gap; - } - - // Space for X Ticks above the plot? - if ($x_tick_pos == 'plotup' || $x_tick_pos == 'both' - || ($x_tick_pos == 'xaxis' && $x_axis_pos == 'top')) { - $top_margin += $x_tick_len; - $this->x_label_top_offset = $x_tick_len + $gap; - $this->x_title_top_offset += $x_tick_len; - } else { - // No X Ticks above the plot: - $this->x_label_top_offset = $gap; - } - - // Space for X Ticks below the plot? - if ($x_tick_pos == 'plotdown' || $x_tick_pos == 'both' - || ($x_tick_pos == 'xaxis' && $x_axis_pos == 'bottom')) { - $bot_margin += $x_tick_len; - $this->x_label_bot_offset = $x_tick_len + $gap; - $this->x_title_bot_offset += $x_tick_len; - } else { - // No X Ticks below the plot: - $this->x_label_bot_offset = $gap; - } - // Label offsets for on-axis ticks: - if ($x_tick_pos == 'xaxis') { - $this->x_label_axis_offset = $x_tick_len + $gap; - } else { - $this->x_label_axis_offset = $gap; - } - - // Calculating Left and Right margins: - // x_left_margin: Left Y title, Y ticks and tick labels: - // x_right_margin: Right Y title, Y ticks and tick labels: - $left_margin = $base_margin; - $right_margin = $base_margin; - $this->y_title_left_offset = $gap; - $this->y_title_right_offset = $gap; - - // Space for Y Title? - if ($y_title_width > 0) { - $pos = $this->y_title_pos; - if ($pos == 'plotleft' || $pos == 'both') - $left_margin += $y_title_width + $gap; - if ($pos == 'plotright' || $pos == 'both') - $right_margin += $y_title_width + $gap; - } - - // Space for Y Labels left of the plot? - if ($label_width_left > 0) { - $left_margin += $label_width_left + $gap; - $this->y_title_left_offset += $label_width_left + $gap; - } - - // Space for Y Labels right of the plot? - if ($label_width_right > 0) { - $right_margin += $label_width_right + $gap; - $this->y_title_right_offset += $label_width_right + $gap; - } - - // Space for Y Ticks left of plot? - if ($y_tick_pos == 'plotleft' || $y_tick_pos == 'both' - || ($y_tick_pos == 'yaxis' && $y_axis_pos == 'left')) { - $left_margin += $y_tick_len; - $this->y_label_left_offset = $y_tick_len + $gap; - $this->y_title_left_offset += $y_tick_len; - } else { - // No Y Ticks left of plot: - $this->y_label_left_offset = $gap; - } - - // Space for Y Ticks right of plot? - if ($y_tick_pos == 'plotright' || $y_tick_pos == 'both' - || ($y_tick_pos == 'yaxis' && $y_axis_pos == 'right')) { - $right_margin += $y_tick_len; - $this->y_label_right_offset = $y_tick_len + $gap; - $this->y_title_right_offset += $y_tick_len; - } else { - // No Y Ticks right of plot: - $this->y_label_right_offset = $gap; - } - - // Label offsets for on-axis ticks: - if ($x_tick_pos == 'yaxis') { - $this->y_label_axis_offset = $y_tick_len + $gap; - } else { - $this->y_label_axis_offset = $gap; - } - - // Apply the minimum margins and store in the object. - // Do not set margins which were user-defined (see note at top of function). - if (!isset($this->y_top_margin)) - $this->y_top_margin = max($min_margin, $top_margin); - if (!isset($this->y_bot_margin)) - $this->y_bot_margin = max($min_margin, $bot_margin); - if (!isset($this->x_left_margin)) - $this->x_left_margin = max($min_margin, $left_margin); - if (!isset($this->x_right_margin)) - $this->x_right_margin = max($min_margin, $right_margin); - - if ($this->GetCallback('debug_scale')) { - // (Too bad compact() doesn't work on class member variables...) - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'label_height_above' => $label_height_above, - 'label_height_below' => $label_height_below, - 'label_width_left' => $label_width_left, - 'label_width_right' => $label_width_right, - 'x_tick_len' => $x_tick_len, - 'y_tick_len' => $y_tick_len, - 'x_left_margin' => $this->x_left_margin, - 'x_right_margin' => $this->x_right_margin, - 'y_top_margin' => $this->y_top_margin, - 'y_bot_margin' => $this->y_bot_margin, - 'x_label_top_offset' => $this->x_label_top_offset, - 'x_label_bot_offset' => $this->x_label_bot_offset, - 'y_label_left_offset' => $this->y_label_left_offset, - 'y_label_right_offset' => $this->y_label_right_offset, - 'x_title_top_offset' => $this->x_title_top_offset, - 'x_title_bot_offset' => $this->x_title_bot_offset, - 'y_title_left_offset' => $this->y_title_left_offset, - 'y_title_right_offset' => $this->y_title_right_offset)); - } - - return TRUE; - } - - /* - * Calculate the plot area (device coordinates) from the margins. - * (This used to be part of SetPlotAreaPixels.) - * The margins might come from SetMarginsPixels, SetPlotAreaPixels, - * or CalcMargins. - */ - protected function CalcPlotAreaPixels() - { - $this->plot_area = array($this->x_left_margin, $this->y_top_margin, - $this->image_width - $this->x_right_margin, - $this->image_height - $this->y_bot_margin); - $this->plot_area_width = $this->plot_area[2] - $this->plot_area[0]; - $this->plot_area_height = $this->plot_area[3] - $this->plot_area[1]; - - $this->DoCallback('debug_scale', __FUNCTION__, $this->plot_area); - return TRUE; - } - - - /*! - * Set the margins in pixels (left, right, top, bottom) - * This determines the plot area, equivalent to SetPlotAreaPixels(). - * Deferred calculations now occur in CalcPlotAreaPixels(). - */ - function SetMarginsPixels($which_lm = NULL, $which_rm = NULL, $which_tm = NULL, $which_bm = NULL) - { - $this->x_left_margin = $which_lm; - $this->x_right_margin = $which_rm; - $this->y_top_margin = $which_tm; - $this->y_bot_margin = $which_bm; - - return TRUE; - } - - /*! - * Sets the limits for the plot area. - * This stores the margins, not the area. That may seem odd, but - * the idea is to make SetPlotAreaPixels and SetMarginsPixels two - * ways to accomplish the same thing, and the deferred calculations - * in CalcMargins and CalcPlotAreaPixels don't need to know which - * was used. - * (x1, y1) - Upper left corner of the plot area - * (x2, y2) - Lower right corner of the plot area - */ - function SetPlotAreaPixels($x1 = NULL, $y1 = NULL, $x2 = NULL, $y2 = NULL) - { - $this->x_left_margin = $x1; - if (isset($x2)) $this->x_right_margin = $this->image_width - $x2; - else unset($this->x_right_margin); - $this->y_top_margin = $y1; - if (isset($y2)) $this->y_bot_margin = $this->image_height - $y2; - else unset($this->y_bot_margin); - - return TRUE; - } - - /* - * Calculate the World Coordinate limits of the plot area. - * This goes with SetPlotAreaWorld, but the calculations are - * deferred until the graph is being drawn. - * Uses and sets: plot_min_x, plot_max_x, plot_min_y, plot_max_y - * These can be user-supplied or NULL to auto-calculate. - * Pre-requisites: FindDataLimits() calculates min_x, max_x, min_y, max_y - * which are the limits of the data to be plotted. - * - * Note: $implied_y and $swapped_xy are currently equivalent, but in the - * future there may be a data type with swapped X/Y and explicit Y values. - * The 4 code blocks below for plot_min_x, plot_max_x, plot_min_y, and - * plot_max_y already contain logic for this case. - * The general method is this: - * If any part of the range is user-defined (via SetPlotAreaWorld), - * use the user-defined value. - * Else, if this is an implicitly-defined independent variable, - * use the fixed range of 0 to (max+1). - * Else, if this is an explicitly-defined independent variable, - * use the exact data range (min to max). - * Else, this is the dependent variable, so define a range which - * includes and exceeds the data range by a bit. - */ - protected function CalcPlotAreaWorld() - { - list($swapped_xy, $implied_x, $implied_y) = $this->DecodeDataType(); - - if (isset($this->plot_min_x) && $this->plot_min_x !== '') - $xmin = $this->plot_min_x; // Use user-provided value - elseif ($implied_x) - $xmin = 0; // Implied X starts at zero - elseif ($swapped_xy) - // If X is the dependent variable, leave some room below. - $xmin = floor($this->min_x - abs($this->min_x) * 0.1); - else - $xmin = $this->min_x; // Otherwise just start at the min data X - - if (isset($this->plot_max_x) && $this->plot_max_x !== '') - $xmax = $this->plot_max_x; // Use user-provided value - elseif ($implied_x) - $xmax = $this->max_x + 1; // Implied X ends after last value - elseif ($swapped_xy) - // If X is the dependent variable, leave some room above. - $xmax = ceil($this->max_x + abs($this->max_x) * 0.1); - else - $xmax = $this->max_x; // Otherwise just end at the max data X - - if (isset($this->plot_min_y) && $this->plot_min_y !== '') - $ymin = $this->plot_min_y; // Use user-provided value - elseif ($implied_y) - $ymin = 0; // Implied Y starts at zero - elseif ($swapped_xy) - $ymin = $this->min_y; // Start at min data Y - else - // If Y is the dependent variable, leave some room below. - $ymin = floor($this->min_y - abs($this->min_y) * 0.1); - - if (isset($this->plot_max_y) && $this->plot_max_y !== '') - $ymax = $this->plot_max_y; // Use user-provided value - elseif ($implied_y) - $ymax = $this->max_y + 1; // Implied Y ends after last value - elseif ($swapped_xy) - $ymax = $this->max_y; // End at max data Y - else - // If Y is the dependent variable, leave some room above. - $ymax = ceil($this->max_y + abs($this->max_y) * 0.1); - - // Error checking - - if ($ymin == $ymax) - $ymax++; - if ($xmin == $xmax) - $xmax++; - - if ($this->yscale_type == 'log') { - if ($ymin <= 0) { - $ymin = 1; - } - if ($ymax <= 0) { - // Note: Error messages reference the user function, not this function. - return $this->PrintError('SetPlotAreaWorld(): Log plots need data greater than 0'); - } - } - - if ($ymax <= $ymin) { - return $this->PrintError('SetPlotAreaWorld(): Error in data - max not greater than min'); - } - - $this->plot_min_x = $xmin; - $this->plot_max_x = $xmax; - $this->plot_min_y = $ymin; - $this->plot_max_y = $ymax; - if ($this->GetCallback('debug_scale')) { - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'plot_min_x' => $this->plot_min_x, 'plot_min_y' => $this->plot_min_y, - 'plot_max_x' => $this->plot_max_x, 'plot_max_y' => $this->plot_max_y)); - } - - return TRUE; - } - - /*! - * Stores the desired World Coordinate range of the plot. - * The user calls this to force one or more of the range limits to - * specific values. Anything not set will be calculated in CalcPlotAreaWorld(). - */ - function SetPlotAreaWorld($xmin=NULL, $ymin=NULL, $xmax=NULL, $ymax=NULL) - { - $this->plot_min_x = $xmin; - $this->plot_max_x = $xmax; - $this->plot_min_y = $ymin; - $this->plot_max_y = $ymax; - return TRUE; - } //function SetPlotAreaWorld - - - /* - * Calculate the width (or height) of bars for bar plots. - * This calculates: - * record_bar_width : Allocated width for each bar (including gaps) - * actual_bar_width : Actual drawn width of each bar - * bar_adjust_gap : Gap on each side of each bar (0 if they touch) - * For the case $verticals=False, horizontal bars are being drawn, - * but the same variable names are used. Think of "bar_width" as being - * the width if you are standing on the Y axis looking towards positive X. - */ - protected function CalcBarWidths($verticals = True) - { - // group_width is the width of a group, including padding - if ($verticals) { - $group_width = $this->plot_area_width / $this->num_data_rows; - } else { - $group_width = $this->plot_area_height / $this->num_data_rows; - } - - // Actual number of bar spaces in the group. This includes the drawn bars, and - // 'bar_extra_space'-worth of extra bars. - // Note that 'records_per_group' includes the label, so subtract one to get - // the number of points in the group. 'stackedbars' have 1 bar space per group. - if ($this->plot_type == 'stackedbars') { - $num_spots = 1 + $this->bar_extra_space; - } else { - $num_spots = $this->records_per_group - 1 + $this->bar_extra_space; - } - - // record_bar_width is the width of each bar's allocated area. - // If bar_width_adjust=1 this is the width of the bar, otherwise - // the bar is centered inside record_bar_width. - // The equation is: - // group_frac_width * group_width = record_bar_width * num_spots - $this->record_bar_width = $this->group_frac_width * $group_width / $num_spots; - - // Note that the extra space due to group_frac_width and bar_extra_space will be - // evenly divided on each side of the group: the drawn bars are centered in the group. - - // Within each bar's allocated space, if bar_width_adjust=1 the bar fills the - // space, otherwise it is centered. - // This is the actual drawn bar width: - $this->actual_bar_width = $this->record_bar_width * $this->bar_width_adjust; - // This is the gap on each side of the bar (0 if bar_width_adjust=1): - $this->bar_adjust_gap = ($this->record_bar_width - $this->actual_bar_width) / 2; - - if ($this->GetCallback('debug_scale')) { - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'record_bar_width' => $this->record_bar_width, - 'actual_bar_width' => $this->actual_bar_width, - 'bar_adjust_gap' => $this->bar_adjust_gap)); - } - return TRUE; - } - - /* - * Calculate X and Y Axis Positions, world coordinates. - * This needs the min/max x/y range set by CalcPlotAreaWorld. - * It adjusts or sets x_axis_position and y_axis_position per the data. - * Empty string means the values need to be calculated; otherwise they - * are supplied but need to be validated against the World area. - * - * Note: This used to be in CalcTranslation, but CalcMargins needs it too. - * This does not calculate the pixel values of the axes. That happens in - * CalcTranslation, after scaling is set up (which has to happen after - * margins are set up). - */ - protected function CalcAxisPositions() - { - // If no user-provided Y axis position, default to axis on left side. - // Otherwise, make sure user-provided position is inside the plot area. - if ($this->y_axis_position === '') - $this->y_axis_position = $this->plot_min_x; - else - $this->y_axis_position = min(max($this->plot_min_x, $this->y_axis_position), $this->plot_max_x); - - // Validate user-provided X axis position, or auto-calculate if not: - if ($this->x_axis_position !== '') { - // User-provided X axis position: make sure it is inside the range. - $this->x_axis_position = min(max($this->plot_min_y, $this->x_axis_position), $this->plot_max_y); - } elseif ($this->yscale_type == 'log') { - // Always use 1 for X axis position on log scale plots. - $this->x_axis_position = 1; - } elseif ($this->plot_min_y <= 0 && 0 <= $this->plot_max_y) { - // Plot range includes Y=0, so use that for X axis: - $this->x_axis_position = 0; - } elseif ($this->plot_min_y > 0) { - // The entire Y range is > 0, so use the bottom for the X axis: - $this->x_axis_position = $this->plot_min_y; - } else { - // The entire Y range is < 0, so use the top for the X axis: - $this->x_axis_position = $this->plot_max_y; - } - - if ($this->GetCallback('debug_scale')) { - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'x_axis_position' => $this->x_axis_position, - 'y_axis_position' => $this->y_axis_position)); - } - - return TRUE; - } - - /*! - * Calculates scaling stuff... - */ - protected function CalcTranslation() - { - if ($this->plot_max_x - $this->plot_min_x == 0) { // Check for div by 0 - $this->xscale = 0; - } else { - if ($this->xscale_type == 'log') { - $this->xscale = ($this->plot_area_width)/(log10($this->plot_max_x) - log10($this->plot_min_x)); - } else { - $this->xscale = ($this->plot_area_width)/($this->plot_max_x - $this->plot_min_x); - } - } - - if ($this->plot_max_y - $this->plot_min_y == 0) { // Check for div by 0 - $this->yscale = 0; - } else { - if ($this->yscale_type == 'log') { - $this->yscale = ($this->plot_area_height)/(log10($this->plot_max_y) - log10($this->plot_min_y)); - } else { - $this->yscale = ($this->plot_area_height)/($this->plot_max_y - $this->plot_min_y); - } - } - // GD defines x = 0 at left and y = 0 at TOP so -/+ respectively - if ($this->xscale_type == 'log') { - $this->plot_origin_x = $this->plot_area[0] - ($this->xscale * log10($this->plot_min_x) ); - } else { - $this->plot_origin_x = $this->plot_area[0] - ($this->xscale * $this->plot_min_x); - } - if ($this->yscale_type == 'log') { - $this->plot_origin_y = $this->plot_area[3] + ($this->yscale * log10($this->plot_min_y)); - } else { - $this->plot_origin_y = $this->plot_area[3] + ($this->yscale * $this->plot_min_y); - } - - // Convert axis positions to device coordinates: - $this->y_axis_x_pixels = $this->xtr($this->y_axis_position); - $this->x_axis_y_pixels = $this->ytr($this->x_axis_position); - - if ($this->GetCallback('debug_scale')) { - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'xscale' => $this->xscale, 'yscale' => $this->yscale, - 'plot_origin_x' => $this->plot_origin_x, 'plot_origin_y' => $this->plot_origin_y, - 'y_axis_x_pixels' => $this->y_axis_x_pixels, - 'x_axis_y_pixels' => $this->x_axis_y_pixels)); - } - - return TRUE; - } // function CalcTranslation() - - - /*! - * Translate X world coordinate into pixel coordinate - * See CalcTranslation() for calculation of xscale. - */ - function xtr($x_world) - { - if ($this->xscale_type == 'log') { - $x_pixels = $this->plot_origin_x + log10($x_world) * $this->xscale ; - } else { - $x_pixels = $this->plot_origin_x + $x_world * $this->xscale ; - } - return round($x_pixels); - } - - - /*! - * Translate Y world coordinate into pixel coordinate. - * See CalcTranslation() for calculation of yscale. - */ - function ytr($y_world) - { - if ($this->yscale_type == 'log') { - //minus because GD defines y = 0 at top. doh! - $y_pixels = $this->plot_origin_y - log10($y_world) * $this->yscale ; - } else { - $y_pixels = $this->plot_origin_y - $y_world * $this->yscale ; - } - return round($y_pixels); - } - - /* A public interface to xtr and ytr. Translates (x,y) in world coordinates - * to (x,y) in device coordinates and returns them as an array. - * Usage is: list($x_pixel, $y_pixel) = $plot->GetDeviceXY($x_world, $y_world) - */ - function GetDeviceXY($x_world, $y_world) - { - if (!isset($this->xscale)) { - return $this->PrintError("GetDeviceXY() was called before translation factors were calculated"); - } - return array($this->xtr($x_world), $this->ytr($y_world)); - } - - /* - * Calculate tick parameters: Start, end, and delta values. This is used - * by both DrawXTicks() and DrawYTicks(). - * This currently uses the same simplistic method previously used by - * PHPlot (basically just range/10), but splitting this out into its - * own function is the first step in replacing the method. - * This is also used by CalcMaxTickSize() for CalcMargins(). - * - * $which : 'x' or 'y' : Which tick parameters to calculate - * - * Returns an array of 3 elements: tick_start, tick_end, tick_step - */ - protected function CalcTicks($which) - { - if ($which == 'x') { - $num_ticks = $this->num_x_ticks; - $tick_inc = $this->x_tick_inc; - $data_max = $this->plot_max_x; - $data_min = $this->plot_min_x; - $skip_lo = $this->skip_left_tick; - $skip_hi = $this->skip_right_tick; - } elseif ($which == 'y') { - $num_ticks = $this->num_y_ticks; - $tick_inc = $this->y_tick_inc; - $data_max = $this->plot_max_y; - $data_min = $this->plot_min_y; - $skip_lo = $this->skip_bottom_tick; - $skip_hi = $this->skip_top_tick; - } else { - return $this->PrintError("CalcTicks: Invalid usage ($which)"); - } - - if (!empty($tick_inc)) { - $tick_step = $tick_inc; - } elseif (!empty($num_ticks)) { - $tick_step = ($data_max - $data_min) / $num_ticks; - } else { - $tick_step = ($data_max - $data_min) / 10; - } - - // NOTE: When working with floats, because of approximations when adding $tick_step, - // the value may not quite reach the end, or may exceed it very slightly. - // So apply a "fudge" factor. - $tick_start = (double)$data_min; - $tick_end = (double)$data_max + ($data_max - $data_min) / 10000.0; - - if ($skip_lo) - $tick_start += $tick_step; - - if ($skip_hi) - $tick_end -= $tick_step; - - return array($tick_start, $tick_end, $tick_step); - } - - /* - * Calculate the size of the biggest tick label. This is used by CalcMargins(). - * For 'x' ticks, it returns the height . For 'y' ticks, it returns the width. - * This means height along Y, or width along X - not relative to the text angle. - * That is what we need to calculate the needed margin space. - * (Previous versions of PHPlot estimated this, using the maximum X or Y value, - * or maybe the longest string. That doesn't work. -10 is longer than 9, etc. - * So this gets the actual size of each label, slow as that may be. - */ - protected function CalcMaxTickLabelSize($which) - { - list($tick_start, $tick_end, $tick_step) = $this->CalcTicks($which); - - if ($which == 'x') { - $font = $this->fonts['x_label']; - $angle = $this->x_label_angle; - } elseif ($which == 'y') { - $font = $this->fonts['y_label']; - $angle = $this->y_label_angle; - } else { - return $this->PrintError("CalcMaxTickLabelSize: Invalid usage ($which)"); - } - - $max_width = 0; - $max_height = 0; - - // Loop over ticks, same as DrawXTicks and DrawYTicks: - // Avoid cumulative round-off errors from $val += $delta - $n = 0; - $tick_val = $tick_start; - while ($tick_val <= $tick_end) { - $tick_label = $this->FormatLabel($which, $tick_val); - list($width, $height) = $this->SizeText($font, $angle, $tick_label); - if ($width > $max_width) $max_width = $width; - if ($height > $max_height) $max_height = $height; - $tick_val = $tick_start + ++$n * $tick_step; - } - if ($this->GetCallback('debug_scale')) { - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'which' => $which, 'height' => $max_height, 'width' => $max_width)); - } - - if ($which == 'x') - return $max_height; - return $max_width; - } - - /* - * Calculate the size of the biggest data label. This is used by CalcMargins(). - * For $which='x', it returns the height of labels along the top or bottom. - * For $which='y', it returns the width of labels along the left or right sides. - * There is only one set of data labels (the first position in each data record). - * They normally go along the top or bottom (or both). If the data type indicates - * X/Y swapping (which is used for horizontal bar charts), the data labels go - * along the sides instead. So CalcMaxDataLabelSize('x') returns 0 if the - * data is X/Y swapped, and CalcMaxDataLabelSize('y') returns 0 if the data is - * is not X/Y swapped. - */ - protected function CalcMaxDataLabelSize($which = 'x') - { - list($swapped_xy) = $this->DecodeDataType(); - if ($which == 'x') { - if ($swapped_xy) - return 0; // Shortcut: labels aren't on top/bottom. - $font = $this->fonts['x_label']; - $angle = $this->x_data_label_angle; - $format_code = 'xd'; - } elseif ($which == 'y') { - if (!$swapped_xy) - return 0; // Shortcut: labels aren't on left/right. - $font = $this->fonts['y_label']; - $angle = $this->y_data_label_angle; - $format_code = 'yd'; - } else { - return $this->PrintError("CalcMaxDataLabelSize: Invalid usage ($which)"); - } - $max_width = 0; - $max_height = 0; - - // Loop over all data labels and find the biggest: - for ($i = 0; $i < $this->num_data_rows; $i++) { - $label = $this->FormatLabel($format_code, $this->data[$i][0]); - list($width, $height) = $this->SizeText($font, $angle, $label); - if ($width > $max_width) $max_width = $width; - if ($height > $max_height) $max_height = $height; - } - if ($this->GetCallback('debug_scale')) { - $this->DoCallback('debug_scale', __FUNCTION__, array( - 'height' => $max_height, 'width' => $max_width)); - } - - if ($swapped_xy) - return $max_width; - return $max_height; - } - - /* - * Set grid control defaults. - * X grid defaults off, Y grid defaults on, except the reverse is true - * with swapped graphs such as horizontal bars. - */ - protected function CalcGridSettings() - { - list($swapped_xy) = $this->DecodeDataType(); - if (!isset($this->draw_x_grid)) - $this->draw_x_grid = $swapped_xy; - if (!isset($this->draw_y_grid)) - $this->draw_y_grid = !$swapped_xy; - } - - /* - * Helper for CheckLabels() - determine if there are any non-empty labels. - * Returns True if all data labels are empty, else False. - */ - protected function CheckLabelsAllEmpty() - { - for ($i = 0; $i < $this->num_data_rows; $i++) - if ($this->data[$i][0] !== '') return False; - return True; - } - - /* - * Check and set label parameters. This handles deferred processing for label - * positioning and other label-related parameters. - * Copy label_format from 'x' to 'xd', and 'y' to 'yd', if not already set. - * Set x_data_label_angle from x_label_angle, if not already set. - * Apply defaults to X and Y tick and data label positions. - * Note: the label strings in the data array are used as X data labels in - * the normal case, but as Y data labels in the swapped X/Y case. - */ - protected function CheckLabels() - { - // The X and Y data labels are formatted the same as X and Y tick labels, - // unless overridden. Check and apply defaults for FormatLabel here: - if (empty($this->label_format['xd']) && !empty($this->label_format['x'])) - $this->label_format['xd'] = $this->label_format['x']; - if (empty($this->label_format['yd']) && !empty($this->label_format['y'])) - $this->label_format['yd'] = $this->label_format['y']; - - // The X tick label angle setting controls X data label angles too, - // unless overridden. Check and apply the default here: - if (!isset($this->x_data_label_angle)) - $this->x_data_label_angle = $this->x_label_angle; - // Note: Y data label angle defaults to zero, unlike X, - // for compatibility with older releases. - - list($swapped_xy) = $this->DecodeDataType(); // Determine if X->Y or Y->X. - - // X Label position fixups, for x_data_label_pos and x_tick_label_pos: - if ($swapped_xy) { - // Just apply defaults - there is no position conflict for X labels. - if (!isset($this->x_tick_label_pos)) - $this->x_tick_label_pos = 'plotdown'; - if (!isset($this->x_data_label_pos)) - $this->x_data_label_pos = 'none'; - } else { - // Apply defaults but do not allow conflict between tick and data labels. - if (isset($this->x_data_label_pos)) { - if (!isset($this->x_tick_label_pos)) { - // Case: data_label_pos is set, tick_label_pos needs a default: - if ($this->x_data_label_pos == 'none') - $this->x_tick_label_pos = 'plotdown'; - else - $this->x_tick_label_pos = 'none'; - } - } elseif (isset($this->x_tick_label_pos)) { - // Case: tick_label_pos is set, data_label_pos needs a default: - if ($this->x_tick_label_pos == 'none') - $this->x_data_label_pos = 'plotdown'; - else - $this->x_data_label_pos = 'none'; - } else { - // Case: Neither tick_label_pos nor data_label_pos is set. - // We do not want them to be both on (as PHPlot used to do in this case). - // Turn on data labels if any were supplied, else tick labels. - if ($this->CheckLabelsAllEmpty()) { - $this->x_data_label_pos = 'none'; - $this->x_tick_label_pos = 'plotdown'; - } else { - $this->x_data_label_pos = 'plotdown'; - $this->x_tick_label_pos = 'none'; - } - } - } - - // Y Label position fixups, for y_data_label_pos and y_tick_label_pos: - if (!$swapped_xy) { - // Just apply defaults - there is no position conflict. - if (!isset($this->y_tick_label_pos)) - $this->y_tick_label_pos = 'plotleft'; - if (!isset($this->y_data_label_pos)) - $this->y_data_label_pos = 'none'; - } else { - // Apply defaults but do not allow conflict between tick and data labels. - if (isset($this->y_data_label_pos)) { - if (!isset($this->y_tick_label_pos)) { - // Case: data_label_pos is set, tick_label_pos needs a default: - if ($this->y_data_label_pos == 'none') - $this->y_tick_label_pos = 'plotleft'; - else - $this->y_tick_label_pos = 'none'; - } - } elseif (isset($this->y_tick_label_pos)) { - // Case: tick_label_pos is set, data_label_pos needs a default: - if ($this->y_tick_label_pos == 'none') - $this->y_data_label_pos = 'plotleft'; - else - $this->y_data_label_pos = 'none'; - } else { - // Case: Neither tick_label_pos nor data_label_pos is set. - // Turn on data labels if any were supplied, else tick labels. - if ($this->CheckLabelsAllEmpty()) { - $this->y_data_label_pos = 'none'; - $this->y_tick_label_pos = 'plotleft'; - } else { - $this->y_data_label_pos = 'plotleft'; - $this->y_tick_label_pos = 'none'; - } - } - } - return TRUE; - } - - /*! - * Formats a tick or data label. - * which_pos - 'x', 'xd', 'y', or 'yd', selects formatting controls. - * x, y are for tick labels; xd, yd are for data labels. - * which_lab - String to format as a label. - * Credits: Time formatting suggested by Marlin Viss - * Custom formatting suggested by zer0x333 - * Notes: - * Type 'title' is obsolete and retained for compatibility. - * Class variable 'data_units_text' is retained as a suffix for 'data' type formatting for - * backward compatibility. Since there was never a function/method to set it, there - * could be somebody out there who sets it directly in the object. - */ - protected function FormatLabel($which_pos, $which_lab) - { - // Assign a reference shortcut to the label format controls. - // Note CheckLabels() made sure the 'xd' and 'yd' arrays are set. - $format =& $this->label_format[$which_pos]; - - // Don't format empty strings (especially as time or numbers), or if no type was set. - if ($which_lab !== '' && !empty($format['type'])) { - switch ($format['type']) { - case 'title': // Note: This is obsolete - $which_lab = @ $this->data[$which_lab][0]; - break; - case 'data': - $which_lab = $format['prefix'] - . $this->number_format($which_lab, $format['precision']) - . $this->data_units_text // Obsolete - . $format['suffix']; - break; - case 'time': - $which_lab = strftime($format['time_format'], $which_lab); - break; - case 'printf': - $which_lab = sprintf($format['printf_format'], $which_lab); - break; - case 'custom': - $which_lab = call_user_func($format['custom_callback'], $which_lab, $format['custom_arg']); - break; - - } - } - return $which_lab; - } //function FormatLabel - -///////////////////////////////////////////// -/////////////// TICKS -///////////////////////////////////////////// - - /*! - * Use either this or SetNumXTicks() to set where to place x tick marks - */ - function SetXTickIncrement($which_ti='') - { - $this->x_tick_inc = $which_ti; - if (!empty($which_ti)) { - $this->num_x_ticks = ''; //either use num_x_ticks or x_tick_inc, not both - } - return TRUE; - } - - /*! - * Use either this or SetNumYTicks() to set where to place y tick marks - */ - function SetYTickIncrement($which_ti='') - { - $this->y_tick_inc = $which_ti; - if (!empty($which_ti)) { - $this->num_y_ticks = ''; //either use num_y_ticks or y_tick_inc, not both - } - return TRUE; - } - - - function SetNumXTicks($which_nt) - { - $this->num_x_ticks = $which_nt; - if (!empty($which_nt)) { - $this->x_tick_inc = ''; //either use num_x_ticks or x_tick_inc, not both - } - return TRUE; - } - - function SetNumYTicks($which_nt) - { - $this->num_y_ticks = $which_nt; - if (!empty($which_nt)) { - $this->y_tick_inc = ''; //either use num_y_ticks or y_tick_inc, not both - } - return TRUE; - } - - /*! - * - */ - function SetYTickPos($which_tp) - { - $this->y_tick_pos = $this->CheckOption($which_tp, 'plotleft, plotright, both, yaxis, none', __FUNCTION__); - return (boolean)$this->y_tick_pos; - } - /*! - * - */ - function SetXTickPos($which_tp) - { - $this->x_tick_pos = $this->CheckOption($which_tp, 'plotdown, plotup, both, xaxis, none', __FUNCTION__); - return (boolean)$this->x_tick_pos; - } - - /*! - * \param skip bool - */ - function SetSkipTopTick($skip) - { - $this->skip_top_tick = (bool)$skip; - return TRUE; - } - - /*! - * \param skip bool - */ - function SetSkipBottomTick($skip) - { - $this->skip_bottom_tick = (bool)$skip; - return TRUE; - } - - /*! - * \param skip bool - */ - function SetSkipLeftTick($skip) - { - $this->skip_left_tick = (bool)$skip; - return TRUE; - } - - /*! - * \param skip bool - */ - function SetSkipRightTick($skip) - { - $this->skip_right_tick = (bool)$skip; - return TRUE; - } - - function SetXTickLength($which_xln) - { - $this->x_tick_length = $which_xln; - return TRUE; - } - - function SetYTickLength($which_yln) - { - $this->y_tick_length = $which_yln; - return TRUE; - } - - function SetXTickCrossing($which_xc) - { - $this->x_tick_cross = $which_xc; - return TRUE; - } - - function SetYTickCrossing($which_yc) - { - $this->y_tick_cross = $which_yc; - return TRUE; - } - - -///////////////////////////////////////////// -//////////////////// GENERIC DRAWING -///////////////////////////////////////////// - - /*! - * Fills the background. - * Note: This method should be 'protected', but is called from test script(s). - */ - function DrawBackground() - { - // Don't draw this twice if drawing two plots on one image - if (! $this->background_done) { - if (isset($this->bgimg)) { // If bgimg is defined, use it - $this->tile_img($this->bgimg, 0, 0, $this->image_width, $this->image_height, $this->bgmode); - } else { // Else use solid color - ImageFilledRectangle($this->img, 0, 0, $this->image_width, $this->image_height, - $this->ndx_bg_color); - } - $this->background_done = TRUE; - } - return TRUE; - } - - - /*! - * Fills the plot area background. - */ - protected function DrawPlotAreaBackground() - { - if (isset($this->plotbgimg)) { - $this->tile_img($this->plotbgimg, $this->plot_area[0], $this->plot_area[1], - $this->plot_area_width, $this->plot_area_height, $this->plotbgmode); - } - else { - if ($this->draw_plot_area_background) { - ImageFilledRectangle($this->img, $this->plot_area[0], $this->plot_area[1], - $this->plot_area[2], $this->plot_area[3], $this->ndx_plot_bg_color); - } - } - - return TRUE; - } - - - /* - * Tiles an image at some given coordinates. - * - * $file string Filename of the picture to be used as tile. - * $xorig int X coordinate of the plot where the tile is to begin. - * $yorig int Y coordinate of the plot where the tile is to begin. - * $width int Width of the area to be tiled. - * $height int Height of the area to be tiled. - * $mode string One of 'centeredtile', 'tile', 'scale'. - */ - protected function tile_img($file, $xorig, $yorig, $width, $height, $mode) - { - $im = $this->GetImage($file, $tile_width, $tile_height); - if (!$im) - return FALSE; // GetImage already produced an error message. - - if ($mode == 'scale') { - imagecopyresampled($this->img, $im, $xorig, $yorig, 0, 0, $width, $height, - $tile_width, $tile_height); - return TRUE; - } - - if ($mode == 'centeredtile') { - $x0 = - floor($tile_width/2); // Make the tile look better - $y0 = - floor($tile_height/2); - } else { // Accept anything else as $mode == 'tile' - $x0 = 0; - $y0 = 0; - } - - // Actually draw the tile - - // But first on a temporal image. - $tmp = imagecreate($width, $height); - if (! $tmp) - return $this->PrintError('tile_img(): Could not create image resource.'); - - for ($x = $x0; $x < $width; $x += $tile_width) - for ($y = $y0; $y < $height; $y += $tile_height) - imagecopy($tmp, $im, $x, $y, 0, 0, $tile_width, $tile_height); - - // Copy the temporal image onto the final one. - imagecopy($this->img, $tmp, $xorig, $yorig, 0,0, $width, $height); - - // Free resources - imagedestroy($tmp); - imagedestroy($im); - - return TRUE; - } // function tile_img - - - /* - * Return the image border width. - * This is used by CalcMargins() and DrawImageBorder(). - */ - protected function GetImageBorderWidth() - { - if ($this->image_border_type == 'none') - return 0; // No border - if (!empty($this->image_border_width)) - return $this->image_border_width; // Specified border width - if ($this->image_border_type == 'raised') - return 2; // Default for raised border is 2 pixels. - return 1; // Default for other border types is 1 pixel. - } - - /* - * Draws a border around the final image. - * Note: 'plain' draws a flat border using the dark shade of the border color. - * This probably should have been written to use the actual border color, but - * it is too late to fix it without changing plot appearances. Therefore a - * new type 'solid' was added to use the SetImageBorderColor color. - */ - protected function DrawImageBorder() - { - if ($this->image_border_type == 'none') - return TRUE; // Early test for default case. - $width = $this->GetImageBorderWidth(); - $color1 = $this->ndx_i_border; - $color2 = $this->ndx_i_border_dark; - $ex = $this->image_width - 1; - $ey = $this->image_height - 1; - switch ($this->image_border_type) { - case 'raised': - // Top and left lines use border color, right and bottom use the darker shade. - // Drawing order matters in the upper right and lower left corners. - for ($i = 0; $i < $width; $i++, $ex--, $ey--) { - imageline($this->img, $i, $i, $ex, $i, $color1); // Top - imageline($this->img, $ex, $i, $ex, $ey, $color2); // Right - imageline($this->img, $i, $i, $i, $ey, $color1); // Left - imageline($this->img, $i, $ey, $ex, $ey, $color2); // Bottom - } - break; - case 'plain': // See note above re colors - $color1 = $color2; - // Fall through - case 'solid': - for ($i = 0; $i < $width; $i++, $ex--, $ey--) { - imagerectangle($this->img, $i, $i, $ex, $ey, $color1); - } - break; - default: - return $this->PrintError("DrawImageBorder(): unknown image_border_type: '$this->image_border_type'"); - } - return TRUE; - } - - - /* - * Draws the main title on the graph. - * The title must not be drawn more than once (in the case of multiple plots - * on the image), because TTF text antialiasing makes it look bad. - */ - protected function DrawTitle() - { - if (isset($this->title_done) || $this->title_txt === '') - return TRUE; - - // Center of the image: - $xpos = $this->image_width / 2; - - // Place it at almost at the top - $ypos = $this->title_offset; - - $this->DrawText($this->fonts['title'], 0, $xpos, $ypos, - $this->ndx_title_color, $this->title_txt, 'center', 'top'); - - $this->title_done = TRUE; - return TRUE; - } - - - /*! - * Draws the X-Axis Title - */ - protected function DrawXTitle() - { - if ($this->x_title_pos == 'none') - return TRUE; - - // Center of the plot - $xpos = ($this->plot_area[2] + $this->plot_area[0]) / 2; - - // Upper title - if ($this->x_title_pos == 'plotup' || $this->x_title_pos == 'both') { - $ypos = $this->plot_area[1] - $this->x_title_top_offset; - $this->DrawText($this->fonts['x_title'], 0, $xpos, $ypos, $this->ndx_title_color, - $this->x_title_txt, 'center', 'bottom'); - } - // Lower title - if ($this->x_title_pos == 'plotdown' || $this->x_title_pos == 'both') { - $ypos = $this->plot_area[3] + $this->x_title_bot_offset; - $this->DrawText($this->fonts['x_title'], 0, $xpos, $ypos, $this->ndx_title_color, - $this->x_title_txt, 'center', 'top'); - } - return TRUE; - } - - /*! - * Draws the Y-Axis Title - */ - protected function DrawYTitle() - { - if ($this->y_title_pos == 'none') - return TRUE; - - // Center the title vertically to the plot area - $ypos = ($this->plot_area[3] + $this->plot_area[1]) / 2; - - if ($this->y_title_pos == 'plotleft' || $this->y_title_pos == 'both') { - $xpos = $this->plot_area[0] - $this->y_title_left_offset; - $this->DrawText($this->fonts['y_title'], 90, $xpos, $ypos, $this->ndx_title_color, - $this->y_title_txt, 'right', 'center'); - } - if ($this->y_title_pos == 'plotright' || $this->y_title_pos == 'both') { - $xpos = $this->plot_area[2] + $this->y_title_right_offset; - $this->DrawText($this->fonts['y_title'], 90, $xpos, $ypos, $this->ndx_title_color, - $this->y_title_txt, 'left', 'center'); - } - - return TRUE; - } - - - /* - * \note Horizontal grid lines overwrite horizontal axis with y=0, so call this first, then DrawXAxis() - */ - protected function DrawYAxis() - { - // Draw ticks, labels and grid, if any - $this->DrawYTicks(); - - // Draw Y axis at X = y_axis_x_pixels - ImageLine($this->img, $this->y_axis_x_pixels, $this->plot_area[1], - $this->y_axis_x_pixels, $this->plot_area[3], $this->ndx_grid_color); - - return TRUE; - } - - /* - * - */ - protected function DrawXAxis() - { - // Draw ticks, labels and grid - $this->DrawXTicks(); - - /* This tick and label tend to overlap with regular Y Axis labels, - * as Mike Pullen pointed out. - * - //Draw Tick and Label for X axis - if (! $this->skip_bottom_tick) { - $ylab =$this->FormatLabel('y', $this->x_axis_position); - $this->DrawYTick($ylab, $this->x_axis_y_pixels); - } - */ - //Draw X Axis at Y = x_axis_y_pixels - ImageLine($this->img, $this->plot_area[0]+1, $this->x_axis_y_pixels, - $this->plot_area[2]-1, $this->x_axis_y_pixels, $this->ndx_grid_color); - - return TRUE; - } - - /*! - * Draw one Y tick mark and its tick label. Called from DrawYTicks() and DrawXAxis() - */ - protected function DrawYTick($which_ylab, $which_ypix) - { - // Ticks on Y axis - if ($this->y_tick_pos == 'yaxis') { - ImageLine($this->img, $this->y_axis_x_pixels - $this->y_tick_length, $which_ypix, - $this->y_axis_x_pixels + $this->y_tick_cross, $which_ypix, $this->ndx_tick_color); - } - - // Ticks to the left of the Plot Area - if (($this->y_tick_pos == 'plotleft') || ($this->y_tick_pos == 'both') ) { - ImageLine($this->img, $this->plot_area[0] - $this->y_tick_length, $which_ypix, - $this->plot_area[0] + $this->y_tick_cross, $which_ypix, $this->ndx_tick_color); - } - - // Ticks to the right of the Plot Area - if (($this->y_tick_pos == 'plotright') || ($this->y_tick_pos == 'both') ) { - ImageLine($this->img, $this->plot_area[2] + $this->y_tick_length, $which_ypix, - $this->plot_area[2] - $this->y_tick_cross, $which_ypix, $this->ndx_tick_color); - } - - // Labels on Y axis - if ($this->y_tick_label_pos == 'yaxis') { - $this->DrawText($this->fonts['y_label'], $this->y_label_angle, - $this->y_axis_x_pixels - $this->y_label_axis_offset, $which_ypix, - $this->ndx_text_color, $which_ylab, 'right', 'center'); - } - - // Labels to the left of the plot area - if ($this->y_tick_label_pos == 'plotleft' || $this->y_tick_label_pos == 'both') { - $this->DrawText($this->fonts['y_label'], $this->y_label_angle, - $this->plot_area[0] - $this->y_label_left_offset, $which_ypix, - $this->ndx_text_color, $which_ylab, 'right', 'center'); - } - // Labels to the right of the plot area - if ($this->y_tick_label_pos == 'plotright' || $this->y_tick_label_pos == 'both') { - $this->DrawText($this->fonts['y_label'], $this->y_label_angle, - $this->plot_area[2] + $this->y_label_right_offset, $which_ypix, - $this->ndx_text_color, $which_ylab, 'left', 'center'); - } - return TRUE; - } // Function DrawYTick() - - - /*! - * Draws Grid, Ticks and Tick Labels along Y-Axis - * Ticks and ticklabels can be left of plot only, right of plot only, - * both on the left and right of plot, or crossing a user defined Y-axis - */ - protected function DrawYTicks() - { - // Sets the line style for IMG_COLOR_STYLED lines (grid) - if ($this->dashed_grid) { - $this->SetDashedStyle($this->ndx_light_grid_color); - $style = IMG_COLOR_STYLED; - } else { - $style = $this->ndx_light_grid_color; - } - - // Calculate the tick start, end, and step: - list($y_start, $y_end, $delta_y) = $this->CalcTicks('y'); - - // Loop, avoiding cumulative round-off errors from $y_tmp += $delta_y - $n = 0; - $y_tmp = $y_start; - while ($y_tmp <= $y_end) { - $ylab = $this->FormatLabel('y', $y_tmp); - $y_pixels = $this->ytr($y_tmp); - - // Horizontal grid line - if ($this->draw_y_grid) { - ImageLine($this->img, $this->plot_area[0]+1, $y_pixels, $this->plot_area[2]-1, $y_pixels, $style); - } - - // Draw tick mark(s) - $this->DrawYTick($ylab, $y_pixels); - - // Step to next Y, without accumulating error - $y_tmp = $y_start + ++$n * $delta_y; - } - return TRUE; - } // function DrawYTicks - - /*! - * Draw one X tick mark and its tick label. - */ - protected function DrawXTick($which_xlab, $which_xpix) - { - // Ticks on X axis - if ($this->x_tick_pos == 'xaxis') { - ImageLine($this->img, $which_xpix, $this->x_axis_y_pixels - $this->x_tick_cross, - $which_xpix, $this->x_axis_y_pixels + $this->x_tick_length, $this->ndx_tick_color); - } - - // Ticks on top of the Plot Area - if ($this->x_tick_pos == 'plotup' || $this->x_tick_pos == 'both') { - ImageLine($this->img, $which_xpix, $this->plot_area[1] - $this->x_tick_length, - $which_xpix, $this->plot_area[1] + $this->x_tick_cross, $this->ndx_tick_color); - } - - // Ticks on bottom of Plot Area - if ($this->x_tick_pos == 'plotdown' || $this->x_tick_pos == 'both') { - ImageLine($this->img, $which_xpix, $this->plot_area[3] + $this->x_tick_length, - $which_xpix, $this->plot_area[3] - $this->x_tick_cross, $this->ndx_tick_color); - } - - // Label on X axis - if ($this->x_tick_label_pos == 'xaxis') { - $this->DrawText($this->fonts['x_label'], $this->x_label_angle, - $which_xpix, $this->x_axis_y_pixels + $this->x_label_axis_offset, - $this->ndx_text_color, $which_xlab, 'center', 'top'); - } - - // Label on top of the Plot Area - if ($this->x_tick_label_pos == 'plotup' || $this->x_tick_label_pos == 'both') { - $this->DrawText($this->fonts['x_label'], $this->x_label_angle, - $which_xpix, $this->plot_area[1] - $this->x_label_top_offset, - $this->ndx_text_color, $which_xlab, 'center', 'bottom'); - } - - // Label on bottom of the Plot Area - if ($this->x_tick_label_pos == 'plotdown' || $this->x_tick_label_pos == 'both') { - $this->DrawText($this->fonts['x_label'], $this->x_label_angle, - $which_xpix, $this->plot_area[3] + $this->x_label_bot_offset, - $this->ndx_text_color, $which_xlab, 'center', 'top'); - } - return TRUE; - } - - /*! - * Draws Grid, Ticks and Tick Labels along X-Axis - * Ticks and tick labels can be down of plot only, up of plot only, - * both on up and down of plot, or crossing a user defined X-axis - * - * \note Original vertical code submitted by Marlin Viss - */ - protected function DrawXTicks() - { - // Sets the line style for IMG_COLOR_STYLED lines (grid) - if ($this->dashed_grid) { - $this->SetDashedStyle($this->ndx_light_grid_color); - $style = IMG_COLOR_STYLED; - } else { - $style = $this->ndx_light_grid_color; - } - - // Calculate the tick start, end, and step: - list($x_start, $x_end, $delta_x) = $this->CalcTicks('x'); - - // Loop, avoiding cumulative round-off errors from $x_tmp += $delta_x - $n = 0; - $x_tmp = $x_start; - while ($x_tmp <= $x_end) { - $xlab = $this->FormatLabel('x', $x_tmp); - $x_pixels = $this->xtr($x_tmp); - - // Vertical grid lines - if ($this->draw_x_grid) { - ImageLine($this->img, $x_pixels, $this->plot_area[1], $x_pixels, $this->plot_area[3], $style); - } - - // Draw tick mark(s) - $this->DrawXTick($xlab, $x_pixels); - - // Step to next X, without accumulating error - $x_tmp = $x_start + ++$n * $delta_x; - } - return TRUE; - } // function DrawXTicks - - - /* - * Draw a border around the plot area. See SetPlotBorderType. - * Note: SetPlotBorderType sets plot_border_type to an array, but - * it won't be an array if it defaults or is set directly (backward compatibility). - */ - protected function DrawPlotBorder() - { - $pbt = (array)$this->plot_border_type; - $sides = 0; // Bitmap: 1=left 2=top 4=right 8=bottom - $map = array('left' => 1, 'plotleft' => 1, 'right' => 4, 'plotright' => 4, 'top' => 2, - 'bottom' => 8, 'both' => 5, 'sides' => 5, 'full' => 15, 'none' => 0); - foreach ($pbt as $option) $sides |= $map[$option]; - if ($sides == 15) { // Border on all 4 sides - imagerectangle($this->img, $this->plot_area[0], $this->plot_area[1], - $this->plot_area[2], $this->plot_area[3], $this->ndx_grid_color); - } else { - if ($sides & 1) // Left - imageline($this->img, $this->plot_area[0], $this->plot_area[1], - $this->plot_area[0], $this->plot_area[3], $this->ndx_grid_color); - if ($sides & 2) // Top - imageline($this->img, $this->plot_area[0], $this->plot_area[1], - $this->plot_area[2], $this->plot_area[1], $this->ndx_grid_color); - if ($sides & 4) // Right - imageline($this->img, $this->plot_area[2], $this->plot_area[1], - $this->plot_area[2], $this->plot_area[3], $this->ndx_grid_color); - if ($sides & 8) // Bottom - imageline($this->img, $this->plot_area[0], $this->plot_area[3], - $this->plot_area[2], $this->plot_area[3], $this->ndx_grid_color); - } - return TRUE; - } - - - /*! - * Draws the data label associated with a point in the plot at specified x/y world position. - * This is currently only used for Y data labels for bar charts. - */ - protected function DrawDataLabel($which_font, $which_angle, $x_world, $y_world, $which_color, $which_text, - $which_halign = 'center', $which_valign = 'bottom', $x_adjustment=0, $y_adjustment=0) - { - $this->DrawText($which_font, $which_angle, - $this->xtr($x_world) + $x_adjustment, $this->ytr($y_world) + $y_adjustment, - $which_color, $this->FormatLabel('yd', $which_text), $which_halign, $which_valign); - - return TRUE; - } - - /*! - * Draws the data label associated with a point in the plot. - * This is different from x_labels drawn by DrawXTicks() and care - * should be taken not to draw both, as they'd probably overlap. - * Calling of this function in DrawLines(), etc is decided after x_data_label_pos value. - * Leave the last parameter out, to avoid the drawing of vertical lines, no matter - * what the setting is (for plots that need it, like DrawSquared()) - */ - protected function DrawXDataLabel($xlab, $xpos, $row=FALSE) - { - $xlab = $this->FormatLabel('xd', $xlab); - - // Labels below the plot area - if ($this->x_data_label_pos == 'plotdown' || $this->x_data_label_pos == 'both') - $this->DrawText($this->fonts['x_label'], $this->x_data_label_angle, - $xpos, $this->plot_area[3] + $this->x_label_bot_offset, - $this->ndx_text_color, $xlab, 'center', 'top'); - - // Labels above the plot area - if ($this->x_data_label_pos == 'plotup' || $this->x_data_label_pos == 'both') - $this->DrawText($this->fonts['x_label'], $this->x_data_label_angle, - $xpos, $this->plot_area[1] - $this->x_label_top_offset, - $this->ndx_text_color, $xlab, 'center', 'bottom'); - - // $row=0 means this is the first row. $row=FALSE means don't do any rows. - if ($row !== FALSE && $this->draw_x_data_label_lines) - $this->DrawXDataLine($xpos, $row); - return TRUE; - } - - /* - * Draw a data label along the Y axis or side. - * This is only used by horizontal bar charts. - */ - protected function DrawYDataLabel($ylab, $ypos) - { - $ylab = $this->FormatLabel('yd', $ylab); - - // Labels left of the plot area - if ($this->y_data_label_pos == 'plotleft' || $this->y_data_label_pos == 'both') - $this->DrawText($this->fonts['y_label'], $this->y_data_label_angle, - $this->plot_area[0] - $this->y_label_left_offset, $ypos, - $this->ndx_text_color, $ylab, 'right', 'center'); - - // Labels right of the plot area - if ($this->y_data_label_pos == 'plotright' || $this->y_data_label_pos == 'both') - $this->DrawText($this->fonts['y_label'], $this->y_data_label_angle, - $this->plot_area[2] + $this->y_label_right_offset, $ypos, - $this->ndx_text_color, $ylab, 'left', 'center'); - return TRUE; - } - - /*! - * Draws Vertical lines from data points up and down. - * Which lines are drawn depends on the value of x_data_label_pos, - * and whether this is at all done or not, on draw_x_data_label_lines - * - * \param xpos int position in pixels of the line. - * \param row int index of the data row being drawn. - */ - protected function DrawXDataLine($xpos, $row) - { - // Sets the line style for IMG_COLOR_STYLED lines (grid) - if($this->dashed_grid) { - $this->SetDashedStyle($this->ndx_light_grid_color); - $style = IMG_COLOR_STYLED; - } else { - $style = $this->ndx_light_grid_color; - } - - // Lines from the bottom up - if ($this->x_data_label_pos == 'both') { - ImageLine($this->img, $xpos, $this->plot_area[3], $xpos, $this->plot_area[1], $style); - } - // Lines from the bottom of the plot up to the max Y value at this X: - else if ($this->x_data_label_pos == 'plotdown' && isset($this->data_max[$row])) { - $ypos = $this->ytr($this->data_max[$row]); - ImageLine($this->img, $xpos, $ypos, $xpos, $this->plot_area[3], $style); - } - // Lines from the top of the plot down to the min Y value at this X: - else if ($this->x_data_label_pos == 'plotup' && isset($this->data_min[$row])) { - $ypos = $this->ytr($this->data_min[$row]); - ImageLine($this->img, $xpos, $this->plot_area[1], $xpos, $ypos, $style); - } - return TRUE; - } - - - /*! - * Draws the graph legend - * - * \note Base code submitted by Marlin Viss - */ - protected function DrawLegend() - { - $font = &$this->fonts['legend']; - - // Find maximum legend label line width. - $max_width = 0; - foreach ($this->legend as $line) { - list($width, $unused) = $this->SizeText($font, 0, $line); - if ($width > $max_width) $max_width = $width; - } - - // Use the font parameters to size the color boxes: - $char_w = $font['width']; - $char_h = $font['height']; - $line_spacing = $this->GetLineSpacing($font); - - // Normalize text alignment and colorbox alignment variables: - $text_align = isset($this->legend_text_align) ? $this->legend_text_align : 'right'; - $colorbox_align = isset($this->legend_colorbox_align) ? $this->legend_colorbox_align : 'right'; - - // Sizing parameters: - $v_margin = $char_h/2; // Between vertical borders and labels - $dot_height = $char_h + $line_spacing; // Height of the small colored boxes - // Overall legend box width e.g.: | space colorbox space text space | - // where colorbox and each space are 1 char width. - if ($colorbox_align != 'none') { - $width = $max_width + 4 * $char_w; - $draw_colorbox = True; - } else { - $width = $max_width + 2 * $char_w; - $draw_colorbox = False; - } - - //////// Calculate box position - // User-defined position specified? - if ( !isset($this->legend_x_pos) || !isset($this->legend_y_pos)) { - // No, use default - $box_start_x = $this->plot_area[2] - $width - $this->safe_margin; - $box_start_y = $this->plot_area[1] + $this->safe_margin; - } elseif (isset($this->legend_xy_world)) { - // User-defined position in world-coordinates (See SetLegendWorld). - $box_start_x = $this->xtr($this->legend_x_pos); - $box_start_y = $this->ytr($this->legend_y_pos); - unset($this->legend_xy_world); - } else { - // User-defined position in pixel coordinates. - $box_start_x = $this->legend_x_pos; - $box_start_y = $this->legend_y_pos; - } - - // Lower right corner - $box_end_y = $box_start_y + $dot_height*(count($this->legend)) + 2*$v_margin; - $box_end_x = $box_start_x + $width; - - // Draw outer box - ImageFilledRectangle($this->img, $box_start_x, $box_start_y, $box_end_x, $box_end_y, $this->ndx_bg_color); - ImageRectangle($this->img, $box_start_x, $box_start_y, $box_end_x, $box_end_y, $this->ndx_grid_color); - - $color_index = 0; - $max_color_index = count($this->ndx_data_colors) - 1; - - // Calculate color box and text horizontal positions. - if (!$draw_colorbox) { - if ($text_align == 'left') - $x_pos = $box_start_x + $char_w; - else - $x_pos = $box_end_x - $char_w; - } elseif ($colorbox_align == 'left') { - $dot_left_x = $box_start_x + $char_w; - $dot_right_x = $dot_left_x + $char_w; - if ($text_align == 'left') - $x_pos = $dot_left_x + 2 * $char_w; - else - $x_pos = $box_end_x - $char_w; - } else { - $dot_left_x = $box_end_x - 2 * $char_w; - $dot_right_x = $dot_left_x + $char_w; - if ($text_align == 'left') - $x_pos = $box_start_x + $char_w; - else - $x_pos = $dot_left_x - $char_w; - } - - // Calculate starting position of first text line. The bottom of each color box - // lines up with the bottom (baseline) of its text line. - $y_pos = $box_start_y + $v_margin + $dot_height; - - foreach ($this->legend as $leg) { - // Draw text with requested alignment: - $this->DrawText($font, 0, $x_pos, $y_pos, $this->ndx_text_color, $leg, $text_align, 'bottom'); - if ($draw_colorbox) { - // Draw a box in the data color - $y1 = $y_pos - $dot_height + 1; - $y2 = $y_pos - 1; - ImageFilledRectangle($this->img, $dot_left_x, $y1, $dot_right_x, $y2, - $this->ndx_data_colors[$color_index]); - // Draw a rectangle around the box - ImageRectangle($this->img, $dot_left_x, $y1, $dot_right_x, $y2, - $this->ndx_text_color); - } - $y_pos += $dot_height; - - $color_index++; - if ($color_index > $max_color_index) - $color_index = 0; - } - return TRUE; - } // Function DrawLegend() - - -///////////////////////////////////////////// -//////////////////// PLOT DRAWING -///////////////////////////////////////////// - - - /*! - * Draws a pie chart. Data is 'text-data', 'data-data', or 'text-data-single'. - * - * For text-data-single, the data array contains records with an ignored label, - * and one Y value. Each record defines a sector of the pie, as a portion of - * the sum of all Y values. - * - * For text-data and data-data, the data array contains records with an ignored label, - * an ignored X value (for data-data only), and N (N>=1) Y values per record. - * The pie chart will be produced with N segments. The relative size of the first - * sector of the pie is the sum of the first Y data value in each record, etc. - * - * Note: With text-data-single, the data labels could be used, but are not currently. - * - * If there are no valid data points > 0 at all, just draw nothing. It may seem more correct to - * raise an error, but all of the other plot types handle it this way implicitly. DrawGraph - * checks for an empty data array, but this is different: a non-empty data array with no Y values, - * or all Y=0. - */ - protected function DrawPieChart() - { - if (!$this->CheckDataType('text-data, text-data-single, data-data')) - return FALSE; - - $xpos = $this->plot_area[0] + $this->plot_area_width/2; - $ypos = $this->plot_area[1] + $this->plot_area_height/2; - $diameter = min($this->plot_area_width, $this->plot_area_height); - $radius = $diameter/2; - - if ($this->data_type == 'text-data') { - // Get sum of each column - One pie slice per column: - $num_slices = $this->records_per_group - 1; // records_per_group is the maximum row size - if ($num_slices < 1) return TRUE; // Give up early if there is no data at all. - $sumarr = array_fill(0, $num_slices, 0); - for ($i = 0; $i < $this->num_data_rows; $i++) { - for ($j = 1; $j < $this->num_recs[$i]; $j++) { // Skip label at [0] - if (is_numeric($this->data[$i][$j])) - $sumarr[$j-1] += abs($this->data[$i][$j]); - } - } - } elseif ($this->data_type == 'text-data-single') { - // Or only one column per row, one pie slice per row: - $num_slices = $this->num_data_rows; - if ($num_slices < 1) return TRUE; // Give up early if there is no data at all. - $sumarr = array_fill(0, $num_slices, 0); - for ($i = 0; $i < $num_slices; $i++) { - // $legend[$i] = $this->data[$i][0]; // Note: Labels are not used yet - if (is_numeric($this->data[$i][1])) - $sumarr[$i] = abs($this->data[$i][1]); - } - } else { // $this->data_type == 'data-data' - $num_slices = $this->records_per_group - 2; // records_per_group is the maximum row size - if ($num_slices < 1) return TRUE; // Give up early if there is no data at all. - $sumarr = array_fill(0, $num_slices, 0); - for ($i = 0; $i < $this->num_data_rows; $i++) { - for ($j = 2; $j < $this->num_recs[$i]; $j++) { // Skip label at [0] an X and [1] - if (is_numeric($this->data[$i][$j])) - $sumarr[$j-2] += abs($this->data[$i][$j]); - } - } - } - - $total = array_sum($sumarr); - - if ($total == 0) { - // There are either no valid data points, or all are 0. - // See top comment about why not to make this an error. - return TRUE; - } - - if ($this->shading) { - $diam2 = $diameter / 2; - } else { - $diam2 = $diameter; - } - $max_data_colors = count ($this->data_colors); - - // Use the Y label format precision, with default value: - if (isset($this->label_format['y']['precision'])) - $precision = $this->label_format['y']['precision']; - else - $precision = 1; - - - for ($h = $this->shading; $h >= 0; $h--) { - $color_index = 0; - $start_angle = 0; - $end_angle = 0; - for ($j = 0; $j < $num_slices; $j++) { - $val = $sumarr[$j]; - - // For shaded pies: the last one (at the top of the "stack") has a brighter color: - if ($h == 0) - $slicecol = $this->ndx_data_colors[$color_index]; - else - $slicecol = $this->ndx_data_dark_colors[$color_index]; - - $label_txt = $this->number_format(($val / $total * 100), $precision) . '%'; - $val = 360 * ($val / $total); - - // NOTE that imagefilledarc measures angles CLOCKWISE (go figure why), - // so the pie chart would start clockwise from 3 o'clock, would it not be - // for the reversal of start and end angles in imagefilledarc() - // Also note ImageFilledArc only takes angles in integer degrees, and if the - // the start and end angles match then you get a full circle not a zero-width - // pie. This is bad. So skip any zero-size wedge. On the other hand, we cannot - // let cumulative error from rounding to integer result in missing wedges. So - // keep the running total as a float, and round the angles. It should not - // be necessary to check that the last wedge ends at 360 degrees. - $start_angle = $end_angle; - $end_angle += $val; - // This method of conversion to integer - truncate after reversing it - was - // chosen to match the implicit method of PHPlot<=5.0.4 to get the same slices. - $arc_start_angle = (int)(360 - $start_angle); - $arc_end_angle = (int)(360 - $end_angle); - - if ($arc_start_angle > $arc_end_angle) { - $mid_angle = deg2rad($end_angle - ($val / 2)); - - // Draw the slice - ImageFilledArc($this->img, $xpos, $ypos+$h, $diameter, $diam2, - $arc_end_angle, $arc_start_angle, - $slicecol, IMG_ARC_PIE); - - // Draw the labels only once - if ($h == 0) { - // Draw the outline - if (! $this->shading) - ImageFilledArc($this->img, $xpos, $ypos+$h, $diameter, $diam2, - $arc_end_angle, $arc_start_angle, - $this->ndx_grid_color, IMG_ARC_PIE | IMG_ARC_EDGED |IMG_ARC_NOFILL); - - - // The '* 1.2' trick is to get labels out of the pie chart so there are more - // chances they can be seen in small sectors. - $label_x = $xpos + ($diameter * 1.2 * cos($mid_angle)) * $this->label_scale_position; - $label_y = $ypos+$h - ($diam2 * 1.2 * sin($mid_angle)) * $this->label_scale_position; - - $this->DrawText($this->fonts['generic'], 0, $label_x, $label_y, $this->ndx_grid_color, - $label_txt, 'center', 'center'); - } - } - if (++$color_index >= $max_data_colors) - $color_index = 0; - } // end for - } // end for - return TRUE; - } - - - /* - * Draw the points and errors bars for an error plot of types points and linepoints - * Supports only data-data-error format, with each row of the form - * array("title", x, y1, error1+, error1-, y2, error2+, error2-, ...) - * Note: plot type and data type were already checked by the calling function. - */ - protected function DrawDotsError() - { - // Adjust the point shapes and point sizes arrays: - $this->CheckPointParams(); - - // Suppress duplicate X data labels in linepoints mode; let DrawLinesError() do them. - $do_labels = ($this->plot_type != 'linepoints'); - - for($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) { - $record = 1; // Skip record #0 (title) - - $x_now = $this->data[$row][$record++]; // Read it, advance record index - - $x_now_pixels = $this->xtr($x_now); // Absolute coordinates. - - // Draw X Data labels? - if ($this->x_data_label_pos != 'none' && $do_labels) - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row); - - // Now go for Y, E+, E- - for ($idx = 0; $record < $this->num_recs[$row]; $idx++) { - if (is_numeric($this->data[$row][$record])) { // Allow for missing Y data - - // Y: - $y_now = $this->data[$row][$record++]; - $this->DrawDot($x_now, $y_now, $idx, $this->ndx_data_colors[$idx]); - - // Error + - $val = $this->data[$row][$record++]; - $this->DrawYErrorBar($x_now, $y_now, $val, $this->error_bar_shape, - $this->ndx_error_bar_colors[$idx]); - // Error - - $val = $this->data[$row][$record++]; - $this->DrawYErrorBar($x_now, $y_now, -$val, $this->error_bar_shape, - $this->ndx_error_bar_colors[$idx]); - } else { - $record += 3; // Skip over missing Y and its error values - } - } - } - return TRUE; - } // function DrawDotsError() - - - /* - * Draw the points for plots of type points and linepoints - * Supported data types: - * - data-data ("title", x, y1, y2, y3, ...) - * - text-data ("title", y1, y2, y3, ...) - */ - protected function DrawDots() - { - if (!$this->CheckDataType('text-data, data-data')) - return FALSE; - - // Adjust the point shapes and point sizes arrays: - $this->CheckPointParams(); - - // Suppress duplicate X data labels in linepoints mode; let DrawLines() do them. - $do_labels = ($this->plot_type != 'linepoints'); - - for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) { - $rec = 1; // Skip record #0 (data label) - - // Do we have a value for X? - if ($this->data_type == 'data-data') - $x_now = $this->data[$row][$rec++]; // Read it, advance record index - else - $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc... - - $x_now_pixels = $this->xtr($x_now); - - // Draw X Data labels? - if ($this->x_data_label_pos != 'none' && $do_labels) - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row); - - // Proceed with Y values - for($idx = 0;$rec < $this->num_recs[$row]; $rec++, $idx++) { - if (is_numeric($this->data[$row][$rec])) { // Allow for missing Y data - $this->DrawDot($x_now, $this->data[$row][$rec], - $idx, $this->ndx_data_colors[$idx]); - } - } - } - return TRUE; - } //function DrawDots - - - /* - * Draw a Thin Bar Line plot, also known as an Impulse plot. - * A clean, fast routine for when you just want charts like stock volume charts - * Supports data-data and text-data formats. - */ - protected function DrawThinBarLines() - { - if (!$this->CheckDataType('text-data, data-data')) - return FALSE; - - for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) { - $rec = 1; // Skip record #0 (data label) - - // Do we have a value for X? - if ($this->data_type == 'data-data') - $x_now = $this->data[$row][$rec++]; // Read it, advance record index - else - $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc... - - $x_now_pixels = $this->xtr($x_now); - - // Draw X Data labels? - if ($this->x_data_label_pos != 'none') - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels); - - // Proceed with Y values - for($idx = 0;$rec < $this->num_recs[$row]; $rec++, $idx++) { - if (is_numeric($this->data[$row][$rec])) { // Allow for missing Y data - ImageSetThickness($this->img, $this->line_widths[$idx]); - // Draws a line from user defined x axis position up to ytr($val) - ImageLine($this->img, $x_now_pixels, $this->x_axis_y_pixels, $x_now_pixels, - $this->ytr($this->data[$row][$rec]), $this->ndx_data_colors[$idx]); - } - } - } - - ImageSetThickness($this->img, 1); - return TRUE; - } //function DrawThinBarLines - - /* - * Draw an Error Bar set. Used by DrawDotsError and DrawLinesError - */ - protected function DrawYErrorBar($x_world, $y_world, $error_height, $error_bar_type, $color) - { - /* - // TODO: add a parameter to show datalabels next to error bars? - // something like this: - if ($this->x_data_label_pos == 'plot') - $this->DrawText($this->fonts['error'], 90, $x1, $y2, - $color, $label, 'center', 'bottom'); - */ - - $x1 = $this->xtr($x_world); - $y1 = $this->ytr($y_world); - $y2 = $this->ytr($y_world+$error_height) ; - - ImageSetThickness($this->img, $this->error_bar_line_width); - ImageLine($this->img, $x1, $y1 , $x1, $y2, $color); - - switch ($error_bar_type) { - case 'line': - break; - case 'tee': - ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color); - break; - default: - ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color); - break; - } - - ImageSetThickness($this->img, 1); - return TRUE; - } - - /* - * Draws a styled dot. Uses world coordinates. - * The list of supported shapes can also be found in SetPointShapes(). - * All shapes are drawn using a 3x3 grid, centered on the data point. - * The center is (x_mid, y_mid) and the corners are (x1, y1) and (x2, y2). - * $record is the 0-based index that selects the shape and size. - */ - protected function DrawDot($x_world, $y_world, $record, $color) - { - $index = $record % $this->point_counts; - $point_size = $this->point_sizes[$index]; - - $half_point = (int)($point_size / 2); - - $x_mid = $this->xtr($x_world); - $y_mid = $this->ytr($y_world); - - $x1 = $x_mid - $half_point; - $x2 = $x_mid + $half_point; - $y1 = $y_mid - $half_point; - $y2 = $y_mid + $half_point; - - switch ($this->point_shapes[$index]) { - case 'halfline': - ImageLine($this->img, $x1, $y_mid, $x_mid, $y_mid, $color); - break; - case 'line': - ImageLine($this->img, $x1, $y_mid, $x2, $y_mid, $color); - break; - case 'plus': - ImageLine($this->img, $x1, $y_mid, $x2, $y_mid, $color); - ImageLine($this->img, $x_mid, $y1, $x_mid, $y2, $color); - break; - case 'cross': - ImageLine($this->img, $x1, $y1, $x2, $y2, $color); - ImageLine($this->img, $x1, $y2, $x2, $y1, $color); - break; - case 'circle': - ImageArc($this->img, $x_mid, $y_mid, $point_size, $point_size, 0, 360, $color); - break; - case 'dot': - ImageFilledEllipse($this->img, $x_mid, $y_mid, $point_size, $point_size, $color); - break; - case 'diamond': - $arrpoints = array( $x1, $y_mid, $x_mid, $y1, $x2, $y_mid, $x_mid, $y2); - ImageFilledPolygon($this->img, $arrpoints, 4, $color); - break; - case 'triangle': - $arrpoints = array( $x1, $y_mid, $x2, $y_mid, $x_mid, $y2); - ImageFilledPolygon($this->img, $arrpoints, 3, $color); - break; - case 'trianglemid': - $arrpoints = array( $x1, $y1, $x2, $y1, $x_mid, $y_mid); - ImageFilledPolygon($this->img, $arrpoints, 3, $color); - break; - case 'yield': - $arrpoints = array( $x1, $y1, $x2, $y1, $x_mid, $y2); - ImageFilledPolygon($this->img, $arrpoints, 3, $color); - break; - case 'delta': - $arrpoints = array( $x1, $y2, $x2, $y2, $x_mid, $y1); - ImageFilledPolygon($this->img, $arrpoints, 3, $color); - break; - case 'star': - ImageLine($this->img, $x1, $y_mid, $x2, $y_mid, $color); - ImageLine($this->img, $x_mid, $y1, $x_mid, $y2, $color); - ImageLine($this->img, $x1, $y1, $x2, $y2, $color); - ImageLine($this->img, $x1, $y2, $x2, $y1, $color); - break; - case 'hourglass': - $arrpoints = array( $x1, $y1, $x2, $y1, $x1, $y2, $x2, $y2); - ImageFilledPolygon($this->img, $arrpoints, 4, $color); - break; - case 'bowtie': - $arrpoints = array( $x1, $y1, $x1, $y2, $x2, $y1, $x2, $y2); - ImageFilledPolygon($this->img, $arrpoints, 4, $color); - break; - case 'target': - ImageFilledRectangle($this->img, $x1, $y1, $x_mid, $y_mid, $color); - ImageFilledRectangle($this->img, $x_mid, $y_mid, $x2, $y2, $color); - ImageRectangle($this->img, $x1, $y1, $x2, $y2, $color); - break; - case 'box': - ImageRectangle($this->img, $x1, $y1, $x2, $y2, $color); - break; - case 'home': /* As in: "home plate" (baseball), also looks sort of like a house. */ - $arrpoints = array( $x1, $y2, $x2, $y2, $x2, $y_mid, $x_mid, $y1, $x1, $y_mid); - ImageFilledPolygon($this->img, $arrpoints, 5, $color); - break; - case 'up': - ImagePolygon($this->img, array($x_mid, $y1, $x2, $y2, $x1, $y2), 3, $color); - break; - case 'down': - ImagePolygon($this->img, array($x_mid, $y2, $x1, $y1, $x2, $y1), 3, $color); - break; - case 'none': /* Special case, no point shape here */ - break; - default: /* Also 'rect' */ - ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $color); - break; - } - return TRUE; - } - - /* - * Draw an 'area' or 'stacked area' plot. - * Both of these fill the area between lines, but in the stacked area graph the Y values - * are accumulated for each X, same as stacked bars. In the regular area graph, the areas - * are filled in order from the X axis up to each Y (so the Y values for each X need to be - * in decreasing order in this case). - * Data format can be text-data (label, y1, y2, ...) or data-data (label, x, y1, y2, ...) - * Notes: - * All Y values must be >= 0. (If any Y<0 the absolute value is used.) - * Missing data points are NOT handled. (They are counted as 0.) - * All rows must have the same number of Y points, or an error image will be produced. - */ - protected function DrawArea($do_stacked = False) - { - if (!$this->CheckDataType('text-data, data-data')) - return FALSE; - - $n = $this->num_data_rows; // Number of X values - - // These arrays store the device X and Y coordinates for all lines: - $xd = array(); - $yd = array(); - if ($this->data_type == 'data-data') { // Explicit X values? - $x_supplied = True; - $skip_index = 2; - } else { - $x_supplied = False; - $skip_index = 1; - } - $num_recs = max($this->num_recs); // Number of 'records' (label + x + y's) for each X. - $num_points = $num_recs - $skip_index; // Number of Y values per X, max - $min_points = min($this->num_recs) - $skip_index; // To check for uniform number of Y values - if ($num_points != $min_points) { - return $this->PrintError("DrawArea(): Data array must contain the same number" - . " of Y values for each X ($num_points != $min_points)"); - } - - // Calculate the Y value for each X, and store the device - // coordinates into the xd and yd arrays. - // For stacked area plots, the Y values accumulate. - for ($row = 0; $row < $n; $row++) { - $rec = 1; // Skip record #0 (data label) - - if ($x_supplied) - $x_now = $this->data[$row][$rec++]; - else - $x_now = 0.5 + $row; - - $x_now_pixels = $this->xtr($x_now); - - if ($this->x_data_label_pos != 'none') // Draw X Data labels? - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels); - - // Store the X value. - // There is an artificial Y value at the axis. For 'area' it goes - // at the end; for stackedarea it goes before the start. - $xd[$row] = $x_now_pixels; - $yd[$row] = array(); - if ($do_stacked) - $yd[$row][] = $this->x_axis_y_pixels; - - // Store the Y values for this X. - // All Y values are clipped to the x axis which should be zero but can be moved. - $y = 0; - while ($rec < $num_recs) { - if (is_numeric($this->data[$row][$rec])) { // Treat missing values as 0. - $y += abs($this->data[$row][$rec]); - } - $yd[$row][] = $this->ytr(max($this->x_axis_position, $y)); - if (!$do_stacked) $y = 0; - $rec++; - } - - if (!$do_stacked) - $yd[$row][] = $this->x_axis_y_pixels; - } - - // Now draw the filled polygons. - $prev_row = 0; - for ($row = 1; $row <= $num_points; $row++) { // 1 extra for X axis artificial row - $pts = array(); - // Previous data set forms top (for area) or bottom (for stackedarea): - for ($j = 0; $j < $n; $j++) { - $pts[] = $xd[$j]; - $pts[] = $yd[$j][$prev_row]; - } - // Current data set forms bottom (for area) or top (for stackedarea): - for ($j = $n- 1; $j >= 0; $j--) { - $pts[] = $xd[$j]; - $pts[] = $yd[$j][$row]; - } - // Draw it: - ImageFilledPolygon($this->img, $pts, $n * 2, $this->ndx_data_colors[$prev_row]); - - $prev_row = $row; - } - return TRUE; - } // function DrawArea() - - - /* - * Draw a Line plot - * Supported data-types are 'data-data' and 'text-data'. - */ - protected function DrawLines() - { - if (!$this->CheckDataType('text-data, data-data')) - return FALSE; - - // Flag array telling if the current point is valid, one element per plot line. - // If start_lines[i] is true, then (lastx[i], lasty[i]) is the previous point. - $start_lines = array_fill(0, $this->records_per_group, FALSE); - - for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) { - $record = 1; // Skip record #0 (data label) - - if ($this->data_type == 'data-data') // Do we have a value for X? - $x_now = $this->data[$row][$record++]; // Read it, advance record index - else - $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc... - - $x_now_pixels = $this->xtr($x_now); // Absolute coordinates - - if ($this->x_data_label_pos != 'none') // Draw X Data labels? - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row); - - for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) { - if (($line_style = $this->line_styles[$idx]) == 'none') - continue; //Allow suppressing entire line, useful with linepoints - if (is_numeric($this->data[$row][$record])) { //Allow for missing Y data - $y_now_pixels = $this->ytr($this->data[$row][$record]); - - if ($start_lines[$idx]) { - // Set line width, revert it to normal at the end - ImageSetThickness($this->img, $this->line_widths[$idx]); - - if ($line_style == 'dashed') { - $this->SetDashedStyle($this->ndx_data_colors[$idx]); - ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx], - IMG_COLOR_STYLED); - } else { - ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx], - $this->ndx_data_colors[$idx]); - } - - } - $lasty[$idx] = $y_now_pixels; - $lastx[$idx] = $x_now_pixels; - $start_lines[$idx] = TRUE; - } - // Y data missing... should we leave a blank or not? - else if ($this->draw_broken_lines) { - $start_lines[$idx] = FALSE; - } - } // end for - } // end for - - ImageSetThickness($this->img, 1); // Revert to original state for lines to be drawn later. - return TRUE; - } // function DrawLines() - - - /* - * Draw lines with error bars for an error plot of types lines and linepoints - * Supports only data-data-error format, with each row of the form - * array("title", x, y1, error1+, error1-, y2, error2+, error2-, ...) - * Note: plot type and data type were already checked by the calling function. - */ - protected function DrawLinesError() - { - $start_lines = array_fill(0, $this->records_per_group, FALSE); - - for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) { - $record = 1; // Skip record #0 (data label) - - $x_now = $this->data[$row][$record++]; // Read X value, advance record index - - $x_now_pixels = $this->xtr($x_now); // Absolute coordinates. - - - if ($this->x_data_label_pos != 'none') // Draw X Data labels? - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row); - - // Now go for Y, E+, E- - for ($idx = 0; $record < $this->num_recs[$row]; $idx++) { - if (($line_style = $this->line_styles[$idx]) == 'none') - continue; //Allow suppressing entire line, useful with linepoints - if (is_numeric($this->data[$row][$record])) { // Allow for missing Y data - - // Y - $y_now = $this->data[$row][$record++]; - $y_now_pixels = $this->ytr($y_now); - - if ($start_lines[$idx]) { - ImageSetThickness($this->img, $this->line_widths[$idx]); - - if ($line_style == 'dashed') { - $this->SetDashedStyle($this->ndx_data_colors[$idx]); - ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx], - IMG_COLOR_STYLED); - } else { - ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx], - $this->ndx_data_colors[$idx]); - } - } - - // Error+ - $val = $this->data[$row][$record++]; - $this->DrawYErrorBar($x_now, $y_now, $val, $this->error_bar_shape, - $this->ndx_error_bar_colors[$idx]); - - // Error- - $val = $this->data[$row][$record++]; - $this->DrawYErrorBar($x_now, $y_now, -$val, $this->error_bar_shape, - $this->ndx_error_bar_colors[$idx]); - - // Update indexes: - $start_lines[$idx] = TRUE; // Tells us if we already drew the first column of points, - // thus having $lastx and $lasty ready for the next column. - $lastx[$idx] = $x_now_pixels; - $lasty[$idx] = $y_now_pixels; - - } else { - $record += 3; // Skip over missing Y and its error values - if ($this->draw_broken_lines) { - $start_lines[$idx] = FALSE; - } - } - } // end for - } // end for - - ImageSetThickness($this->img, 1); // Revert to original state for lines to be drawn later. - return TRUE; - } // function DrawLinesError() - - - - /* - * Draw a Squared Line plot. - * Supported data-types are 'data-data' and 'text-data'. - * This is based on DrawLines(), with one more line drawn for each point. - */ - protected function DrawSquared() - { - if (!$this->CheckDataType('text-data, data-data')) - return FALSE; - - // Flag array telling if the current point is valid, one element per plot line. - // If start_lines[i] is true, then (lastx[i], lasty[i]) is the previous point. - $start_lines = array_fill(0, $this->records_per_group, FALSE); - - for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) { - $record = 1; // Skip record #0 (data label) - - if ($this->data_type == 'data-data') // Do we have a value for X? - $x_now = $this->data[$row][$record++]; // Read it, advance record index - else - $x_now = 0.5 + $cnt++; // Place text-data at X = 0.5, 1.5, 2.5, etc... - - $x_now_pixels = $this->xtr($x_now); // Absolute coordinates - - if ($this->x_data_label_pos != 'none') // Draw X Data labels? - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels); // notice there is no last param. - - // Draw Lines - for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) { - if (is_numeric($this->data[$row][$record])) { // Allow for missing Y data - $y_now_pixels = $this->ytr($this->data[$row][$record]); - - if ($start_lines[$idx] == TRUE) { - // Set line width, revert it to normal at the end - ImageSetThickness($this->img, $this->line_widths[$idx]); - - if ($this->line_styles[$idx] == 'dashed') { - $this->SetDashedStyle($this->ndx_data_colors[$idx]); - ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx], - IMG_COLOR_STYLED); - ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels, - IMG_COLOR_STYLED); - } else { - ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx], - $this->ndx_data_colors[$idx]); - ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels, - $this->ndx_data_colors[$idx]); - } - } - $lastx[$idx] = $x_now_pixels; - $lasty[$idx] = $y_now_pixels; - $start_lines[$idx] = TRUE; - } - // Y data missing... should we leave a blank or not? - else if ($this->draw_broken_lines) { - $start_lines[$idx] = FALSE; - } - } - } // end while - - ImageSetThickness($this->img, 1); - return TRUE; - } // function DrawSquared() - - - /* - * Draw a Bar chart - * Supports only text-data format, with each row in the form array("title", y1, y2, y3, ...) - */ - protected function DrawBars() - { - if (!$this->CheckDataType('text-data')) - return False; - - // This is the X offset from the bar group's label center point to the left side of the first bar - // in the group. See also CalcBarWidths above. - $x_first_bar = (($this->records_per_group - 1) * $this->record_bar_width) / 2 - $this->bar_adjust_gap; - - for ($row = 0; $row < $this->num_data_rows; $row++) { - $record = 1; // Skip record #0 (data label) - - $x_now_pixels = $this->xtr(0.5 + $row); // Place text-data at X = 0.5, 1.5, 2.5, etc... - - if ($this->x_data_label_pos != 'none') // Draw X Data labels? - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels); - - // Lower left X of first bar in the group: - $x1 = $x_now_pixels - $x_first_bar; - - // Draw the bars in the group: - for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) { - if (is_numeric($this->data[$row][$record])) { // Allow for missing Y data - $x2 = $x1 + $this->actual_bar_width; - - if ($this->data[$row][$record] < $this->x_axis_position) { - $y1 = $this->x_axis_y_pixels; - $y2 = $this->ytr($this->data[$row][$record]); - $upgoing_bar = False; - } else { - $y1 = $this->ytr($this->data[$row][$record]); - $y2 = $this->x_axis_y_pixels; - $upgoing_bar = True; - } - - // Draw the bar - ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $this->ndx_data_colors[$idx]); - - if ($this->shading) { // Draw the shade? - ImageFilledPolygon($this->img, array($x1, $y1, - $x1 + $this->shading, $y1 - $this->shading, - $x2 + $this->shading, $y1 - $this->shading, - $x2 + $this->shading, $y2 - $this->shading, - $x2, $y2, - $x2, $y1), - 6, $this->ndx_data_dark_colors[$idx]); - } - // Or draw a border? - else { - ImageRectangle($this->img, $x1, $y1, $x2,$y2, $this->ndx_data_border_colors[$idx]); - } - - // Draw optional data labels above the bars (or below, for negative values). - if ( $this->y_data_label_pos == 'plotin') { - if ($upgoing_bar) { - $v_align = 'bottom'; - $y_offset = -5 - $this->shading; - } else { - $v_align = 'top'; - $y_offset = 2; - } - $this->DrawDataLabel($this->fonts['y_label'], $this->y_data_label_angle, - $row+0.5, $this->data[$row][$record], $this->ndx_title_color, - $this->data[$row][$record], 'center', $v_align, - ($idx + 0.5) * $this->record_bar_width - $x_first_bar, $y_offset); - } - - } - // Step to next bar in group: - $x1 += $this->record_bar_width; - } // end for - } // end for - return TRUE; - } //function DrawBars - - /* - * Draw a Horizontal Bar chart - * Supports only text-data-yx format, with each row in the form array("title", x1, x2, x3, ...) - * This is an unusual case, because the data values are X not Y. - * Note: plot type and data type were already checked by the calling function. - */ - protected function DrawHorizBars() - { - // This is the Y offset from the bar group's label center point to the bottom of the first bar - // in the group. See also CalcBarWidths above. - $y_first_bar = (($this->records_per_group - 1) * $this->record_bar_width) / 2 - $this->bar_adjust_gap; - - for ($row = 0; $row < $this->num_data_rows; $row++) { - $record = 1; // Skip record #0 (data label) - - $y_now_pixels = $this->ytr(0.5 + $row); // Place bars at Y=0.5, 1.5, 2.5, etc... - - if ($this->y_data_label_pos != 'none') // Draw Y Data Labels? - $this->DrawYDataLabel($this->data[$row][0], $y_now_pixels); - - // Lower left Y of first bar in the group: - $y1 = $y_now_pixels + $y_first_bar; - - // Draw the bars in the group: - for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) { - if (is_numeric($this->data[$row][$record])) { // Allow for missing X data - $y2 = $y1 - $this->actual_bar_width; - - if ($this->data[$row][$record] < $this->y_axis_position) { - $x1 = $this->y_axis_x_pixels; - $x2 = $this->xtr($this->data[$row][$record]); - $rightwards_bar = False; - } else { - $x1 = $this->xtr($this->data[$row][$record]); - $x2 = $this->y_axis_x_pixels; - $rightwards_bar = True; - } - - // Draw the bar - ImageFilledRectangle($this->img, $x2, $y2, $x1, $y1, $this->ndx_data_colors[$idx]); - - if ($this->shading) { // Draw the shade? - ImageFilledPolygon($this->img, array($x2, $y2, - $x2 + $this->shading, $y2 - $this->shading, - $x1 + $this->shading, $y2 - $this->shading, - $x1 + $this->shading, $y1 - $this->shading, - $x1, $y1, - $x1, $y2), - 6, $this->ndx_data_dark_colors[$idx]); - } - // Or draw a border? - else { - ImageRectangle($this->img, $x1, $y1, $x2,$y2, $this->ndx_data_border_colors[$idx]); - } - - // Draw optional data labels above the bars (or below, for negative values). - // DELETED - - } - // Step to next bar in group: - $y1 -= $this->record_bar_width; - } // end for - } // end for - - return TRUE; - } - - /* - * Draw a Stacked Bar chart - * Supports only text-data format, with each row in the form array("title", y1, y2, y3, ...) - * Original stacked bars idea by Laurent Kruk < lolok at users.sourceforge.net > - */ - protected function DrawStackedBars() - { - if (!$this->CheckDataType('text-data')) - return False; - - // This is the X offset from the bar's label center point to the left side of the bar. - $x_first_bar = $this->record_bar_width / 2 - $this->bar_adjust_gap; - - // Copy shading value to local variable - $shade = $this->shading; - - // Determine if any data labels are on: - if ($this->y_data_label_pos == 'plotin') { - $data_labels_above = True; - $data_labels_within = False; - } elseif ($this->y_data_label_pos == 'plotstack') { - $data_labels_above = True; - $data_labels_within = True; - // Get the text label height, plus a little bit, so we can omit labels in - // segments that are too short for the label to fit. - $data_labels_min_height = $this->fonts['y_label']['height'] + 2; - } else { - $data_labels_above = False; - $data_labels_within = False; - } - if ($data_labels_above || $data_labels_within) { - $data_label_y_offset = -5 - $shade; - } - - for ($row = 0; $row < $this->num_data_rows; $row++) { - $record = 1; // Skip record #0 (data label) - - $x_now_pixels = $this->xtr(0.5 + $row); // Place text-data at X = 0.5, 1.5, 2.5, etc... - - if ($this->x_data_label_pos != 'none') // Draw X Data labels? - $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels); - - // Lower left and lower right X of the bars in this stack: - $x1 = $x_now_pixels - $x_first_bar; - $x2 = $x1 + $this->actual_bar_width; - - // Draw the bar segments in this stack. The first segment is drawn from the X axis to Y1. - // Each additional segment is drawn from the top of the previous segment to the new - // cumulative Y. Skip over any segment of 0 size or part below the X axis. - $wy1 = 0; // World coordinates Y1, upper value - $wy2 = $this->x_axis_position; // World coordinates Y2, lower value - - for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) { - - // Skip missing Y values, and ignore Y=0 values. - if (is_numeric($this->data[$row][$record]) - && ($this_y = abs($this->data[$row][$record])) > 0) { - - $wy1 += $this_y; // Accumulate Y value in world coordinates - top of current segment. - - // Draw nothing if top of segment is below X axis. - // Bottom (wy2) will not go below X axis, so we will get a partial - // segment from X axis up if the segment would cross the X axis. - if ($wy1 > $this->x_axis_position) { - - $y1 = $this->ytr($wy1); - $y2 = $this->ytr($wy2); - - // Draw the bar - ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $this->ndx_data_colors[$idx]); - - if ($shade > 0) { // Draw the shade? - ImageFilledPolygon($this->img, - array($x1, $y1, $x1 + $shade, $y1 - $shade, - $x2 + $shade, $y1 - $shade, $x2 + $shade, $y2 - $shade, - $x2, $y2, $x2, $y1), - 6, $this->ndx_data_dark_colors[$idx]); - } else { // Or draw a border? - ImageRectangle($this->img, $x1, $y1, $x2,$y2, $this->ndx_data_border_colors[$idx]); - } - - // Draw optional data label for this bar segment just below the line. - // Text value is the current Y, but position is the cumulative Y. - // Skip the label if the segment is too short for the label to fit. - if ($data_labels_within && ($y2 - $y1) >= $data_labels_min_height) { - $this->DrawDataLabel($this->fonts['y_label'], $this->y_data_label_angle, - $row+0.5, $wy1, $this->ndx_title_color, - $this_y, 'center', 'top', 0, 3); - } - } - // Make the top of this segment become the bottom of the next segment, but not if - // it is still below the X axis. - $wy2 = max($this->x_axis_position, $wy1); - } - } // end for - - // Draw optional data label above the bar with the total value. - // Value is wy1, but position is wy2. This only makes a difference when - // the stacked bar ends completely below the X axis. Then we see the actual - // cumulative value (wy1), positioned above the axis, with no bar at all. - if ($data_labels_above) { - $this->DrawDataLabel($this->fonts['y_label'], $this->y_data_label_angle, - $row+0.5, $wy2, $this->ndx_title_color, - $wy1, 'center', 'bottom', 0, $data_label_y_offset); - } - } // end for - return TRUE; - } //function DrawStackedBars - - - /* - * Draw the graph. - * This is the function that performs the actual drawing, after all - * the parameters and data are set up. - * It also outputs the finished image, unless told not to. - */ - function DrawGraph() - { - // Test for missing image, missing data, empty data: - if (! $this->img) { - return $this->PrintError('DrawGraph(): No image resource allocated'); - } - if (empty($this->data) || ! is_array($this->data)) { - return $this->PrintError("DrawGraph(): No data array"); - } - if ($this->total_records == 0) { - return $this->PrintError('DrawGraph(): Empty data set'); - } - - // For pie charts: don't draw grid or border or axes, and maximize area usage. - // These controls can be split up in the future if needed. - $draw_axes = ($this->plot_type != 'pie'); - - // Get maxima and minima for scaling: - if (!$this->FindDataLimits()) - return FALSE; - - // Set plot area world values (plot_max_x, etc.): - if (!$this->CalcPlotAreaWorld()) - return FALSE; - - // Calculate X and Y axis positions in World Coordinates: - $this->CalcAxisPositions(); - - // Process label-related parameters: - $this->CheckLabels(); - - // Apply grid defaults: - $this->CalcGridSettings(); - - // Calculate the plot margins, if needed. - // For pie charts, set the $maximize argument to maximize space usage. - $this->CalcMargins(!$draw_axes); - - // Calculate the actual plot area in device coordinates: - $this->CalcPlotAreaPixels(); - - // Calculate the mapping between world and device coordinates: - $this->CalcTranslation(); - - // Pad color and style arrays to fit records per group: - $this->PadArrays(); - $this->DoCallback('draw_setup'); - - $this->DrawBackground(); - $this->DrawImageBorder(); - $this->DoCallback('draw_image_background'); - - $this->DrawPlotAreaBackground(); - $this->DoCallback('draw_plotarea_background', $this->plot_area); - - $this->DrawTitle(); - if ($draw_axes) { // If no axes (pie chart), no axis titles either - $this->DrawXTitle(); - $this->DrawYTitle(); - } - $this->DoCallback('draw_titles'); - - if ($draw_axes && ! $this->grid_at_foreground) { // Usually one wants grids to go back, but... - $this->DrawYAxis(); // Y axis must be drawn before X axis (see DrawYAxis()) - $this->DrawXAxis(); - $this->DoCallback('draw_axes'); - } - - switch ($this->plot_type) { - case 'thinbarline': - $this->DrawThinBarLines(); - break; - case 'area': - $this->DrawArea(); - break; - case 'squared': - $this->DrawSquared(); - break; - case 'lines': - if ( $this->data_type == 'data-data-error') { - $this->DrawLinesError(); - } else { - $this->DrawLines(); - } - break; - case 'linepoints': - if ( $this->data_type == 'data-data-error') { - $this->DrawLinesError(); - $this->DrawDotsError(); - } else { - $this->DrawLines(); - $this->DrawDots(); - } - break; - case 'points'; - if ( $this->data_type == 'data-data-error') { - $this->DrawDotsError(); - } else { - $this->DrawDots(); - } - break; - case 'pie': - $this->DrawPieChart(); - break; - case 'stackedbars': - $this->CalcBarWidths(); - $this->DrawStackedBars(); - break; - case 'stackedarea': - $this->DrawArea(True); - break; - // case 'bars': - default: - $this->plot_type = 'bars'; // Make sure it is set - if ($this->data_type == 'text-data-yx') { - $this->CalcBarWidths(False); - $this->DrawHorizBars(); - } else { - $this->CalcBarWidths(); - $this->DrawBars(); - } - break; - } // end switch - $this->DoCallback('draw_graph', $this->plot_area); - - if ($draw_axes && $this->grid_at_foreground) { // Usually one wants grids to go back, but... - $this->DrawYAxis(); // Y axis must be drawn before X axis (see DrawYAxis()) - $this->DrawXAxis(); - $this->DoCallback('draw_axes'); - } - - if ($draw_axes) { - $this->DrawPlotBorder(); - $this->DoCallback('draw_border'); - } - - if ($this->legend) { - $this->DrawLegend(); - $this->DoCallback('draw_legend'); - } - $this->DoCallback('draw_all', $this->plot_area); - - if ($this->print_image && !$this->PrintImage()) - return FALSE; - - return TRUE; - } //function DrawGraph() - -///////////////////////////////////////////// -////////////////// DEPRECATED METHODS -///////////////////////////////////////////// - - /*! - * Deprecated, use SetYTickPos() - */ - function SetDrawVertTicks($which_dvt) - { - if ($which_dvt != 1) - $this->SetYTickPos('none'); - return TRUE; - } - - /*! - * Deprecated, use SetXTickPos() - */ - function SetDrawHorizTicks($which_dht) - { - if ($which_dht != 1) - $this->SetXTickPos('none'); - return TRUE; - } - - /*! - * \deprecated Use SetNumXTicks() - */ - function SetNumHorizTicks($n) - { - return $this->SetNumXTicks($n); - } - - /*! - * \deprecated Use SetNumYTicks() - */ - function SetNumVertTicks($n) - { - return $this->SetNumYTicks($n); - } - - /*! - * \deprecated Use SetXTickIncrement() - */ - function SetHorizTickIncrement($inc) - { - return $this->SetXTickIncrement($inc); - } - - - /*! - * \deprecated Use SetYTickIncrement() - */ - function SetVertTickIncrement($inc) - { - return $this->SetYTickIncrement($inc); - } - - /*! - * \deprecated Use SetYTickPos() - */ - function SetVertTickPosition($which_tp) - { - return $this->SetYTickPos($which_tp); - } - - /*! - * \deprecated Use SetXTickPos() - */ - function SetHorizTickPosition($which_tp) - { - return $this->SetXTickPos($which_tp); - } - - /*! - * \deprecated Use SetFont() - */ - function SetTitleFontSize($which_size) - { - return $this->SetFont('title', $which_size); - } - - /*! - * \deprecated Use SetFont() - */ - function SetAxisFontSize($which_size) - { - $this->SetFont('x_label', $which_size); - $this->SetFont('y_label', $which_size); - } - - /*! - * \deprecated Use SetFont() - */ - function SetSmallFontSize($which_size) - { - return $this->SetFont('generic', $which_size); - } - - /*! - * \deprecated Use SetFont() - */ - function SetXLabelFontSize($which_size) - { - return $this->SetFont('x_title', $which_size); - } - - /*! - * \deprecated Use SetFont() - */ - function SetYLabelFontSize($which_size) - { - return $this->SetFont('y_title', $which_size); - } - - /*! - * \deprecated Use SetXTitle() - */ - function SetXLabel($which_xlab) - { - return $this->SetXTitle($which_xlab); - } - - /*! - * \deprecated Use SetYTitle() - */ - function SetYLabel($which_ylab) - { - return $this->SetYTitle($which_ylab); - } - - /*! - * \deprecated Use SetXTickLength() and SetYTickLength() instead. - */ - function SetTickLength($which_tl) - { - $this->SetXTickLength($which_tl); - $this->SetYTickLength($which_tl); - return TRUE; - } - - /*! - * \deprecated Use SetYLabelType() - */ - function SetYGridLabelType($which_yglt) - { - return $this->SetYLabelType($which_yglt); - } - - /*! - * \deprecated Use SetXLabelType() - */ - function SetXGridLabelType($which_xglt) - { - return $this->SetXLabelType($which_xglt); - } - /*! - * \deprecated Use SetYTickLabelPos() - */ - function SetYGridLabelPos($which_yglp) - { - return $this->SetYTickLabelPos($which_yglp); - } - /*! - * \deprecated Use SetXTickLabelPos() - */ - function SetXGridLabelPos($which_xglp) - { - return $this->SetXTickLabelPos($which_xglp); - } - - - /*! - * \deprecated Use SetXtitle() - */ - function SetXTitlePos($xpos) - { - $this->x_title_pos = $xpos; - return TRUE; - } - - /*! - * \deprecated Use SetYTitle() - */ - function SetYTitlePos($xpos) - { - $this->y_title_pos = $xpos; - return TRUE; - } - - /*! - * Draw Labels (not grid labels) on X Axis, following data points. Default position is - * down of plot. Care must be taken not to draw these and x_tick_labels as they'd probably overlap. - * - * \deprecated Use SetXDataLabelPos() - */ - function SetDrawXDataLabels($which_dxdl) - { - if ($which_dxdl == '1' ) - $this->SetXDataLabelPos('plotdown'); - else - $this->SetXDataLabelPos('none'); - } - - /*! - * \deprecated - */ - function SetNewPlotAreaPixels($x1, $y1, $x2, $y2) - { - //Like in GD 0, 0 is upper left set via pixel Coordinates - $this->plot_area = array($x1, $y1, $x2, $y2); - $this->plot_area_width = $this->plot_area[2] - $this->plot_area[0]; - $this->plot_area_height = $this->plot_area[3] - $this->plot_area[1]; - $this->y_top_margin = $this->plot_area[1]; - - if (isset($this->plot_max_x)) - $this->CalcTranslation(); - - return TRUE; - } - - /*! - * \deprecated Use _SetRGBColor() - */ - function SetColor($which_color) - { - $this->SetRGBColor($which_color); - return TRUE; - } - - /* - * \deprecated Use SetLineWidths(). - */ - function SetLineWidth($which_lw) - { - - $this->SetLineWidths($which_lw); - - if (!$this->error_bar_line_width) { - $this->SetErrorBarLineWidth($which_lw); - } - return TRUE; - } - - /* - * \deprecated Use SetPointShapes(). - */ - function SetPointShape($which_pt) - { - $this->SetPointShapes($which_pt); - return TRUE; - } - - /* - * \deprecated Use SetPointSizes(). - */ - function SetPointSize($which_ps) - { - $this->SetPointSizes($which_ps); - return TRUE; - } -} // class PHPlot - - -/* - * The PHPlot_truecolor class extends PHPlot to use GD truecolor images. - */ - -class PHPlot_truecolor extends PHPlot { - /* - * PHPlot Truecolor variation constructor: Create a PHPlot_truecolor object and initialize it. - * Note this does NOT call the parent (PHPlot) constructor. It duplicates the code here. - * Everything is the same as the PHPlot constructor except for imagecreatetruecolor. - * - * Parameters are the same as PHPlot: - * which_width, which_height Image width and height in pixels. - * which_output_file Optional filename for output. - * which_input_file Optional path to a file to be used as background. - * - */ - function __construct($which_width=600, $which_height=400, $which_output_file=NULL, $which_input_file=NULL) - { - $this->SetRGBArray($this->color_array); - - if ($which_output_file) - $this->SetOutputFile($which_output_file); - - if ($which_input_file) - $this->SetInputFile($which_input_file); - else { - $this->image_width = $which_width; - $this->image_height = $which_height; - - $this->img = imagecreatetruecolor($this->image_width, $this->image_height); - if (! $this->img) - return $this->PrintError('PHPlot_truecolor(): Could not create image resource.'); - } - - $this->SetDefaultStyles(); - $this->SetDefaultFonts(); - } -} diff --git a/gosa-core/include/phplot-5.1.2/phplot_data.php b/gosa-core/include/phplot-5.1.2/phplot_data.php deleted file mode 100644 index d42c27aee..000000000 --- a/gosa-core/include/phplot-5.1.2/phplot_data.php +++ /dev/null @@ -1,270 +0,0 @@ -img)) { - $this->PHPlot($which_width, $which_height, $which_output_file, $which_input_file); - } - } - - /*! - * Will scale all data rows - * Maybe later I will do a function that only scales some rows - * if $even is TRUE, data will be scaled with "even" factors. - * \note Original code by Thiemo Nagel - */ - function DoScaleData($even, $show_in_legend) - { - $offset = 0; // We use this not to read labels in text-data - - if ($this->data_type == 'text-data') { - $offset = 1; - } elseif ($this->data_type != 'data-data') { - $this->DrawError('wrong data type!!'); - return FALSE; - } - - // Determine maxima for each data row in array $max - // Put maximum of the maxima in $maxmax - $maxmax = 0; - for($i=0; $i < $this->num_data_rows; $i++) { - $rowsize = count($this->data[$i]); - for ($j=$offset; $j < $rowsize; $j++) { - if ($this->data[$i][$j] > @ $max[$j]) - $max[$j] = $this->data[$i][$j]; - if (@ $max[$j] > $maxmax) - $maxmax = $max[$j]; - } - } - - // determine amplification factor $amplify - $end = count($max) + $offset; - for ($i=$offset; $i < $end; $i++) { - if ($max[$i] == 0 || $max[$i] == $maxmax) { - $amplify[$i] = 1; // no divide by zero - } else { - if ($even) { - $amp = pow(10,round(log10($maxmax / $max[$i]))-1); - if ($amp * $max[$i] * 5 < $maxmax) { - $amp *= 5; - } elseif ($amp * $max[$i] * 2 < $maxmax) { - $amp *= 2; - } - } else { - $amp = $maxmax / $max[$i]; - $digits = floor(log10($amp)); - $amp = round($amp/pow(10,$digits-1))*pow(10,$digits-1); - } - $amplify[$i] = $amp; - } - if ($amplify[$i] != 1 && $show_in_legend) - @ $this->legend[$i] .= "*$amplify[$i]"; - } - - // Amplify data - // On my machine, running 1000 iterations over 1000 rows of 12 elements each, - // the for loops were 43.2% faster (MBD) - for ($i = 0; $i < $this->num_data_rows; $i++) { - $rowsize = count($this->data[$i]); - for ($j=$offset; $j < $rowsize; $j++) { - $this->data[$i][$j] *= $amplify[$j]; - } - } - - //Re-Scale Vertical Ticks if not already set - //Removed; does nothing and wrong variable name? - // if ( ! $this->y_tick_increment) { - // $this->SetYTickIncrement() ; - // } - - return TRUE; - } //function DoScaleData - - - /*! - * Computes a moving average of strength $interval for - * data row number $datarow, where 0 denotes the first - * row of y-data. - * - * \param int datarow Index of the row whereupon to make calculations - * \param int interval Number of elements to use in average ("strength") - * \param bool show Whether to tell about the moving average in the legend. - * \param string color Color for the line to be drawn. This color is darkened. - * Can be named or #RRGGBB. - * \param int width Width of the line to be drawn. - * - * \note Original idea by Theimo Nagel - */ - function DoMovingAverage($datarow, $interval, $show=TRUE, $color=NULL, $width=NULL) - { - $off = 1; // Skip record #0 (data label) - - $this->PadArrays(); - - if ($interval == 0) { - $this->DrawError('DoMovingAverage(): interval can\'t be 0'); - return FALSE; - } - - if ($datarow >= $this->records_per_group) { - $this->DrawError("DoMovingAverage(): Data row out of bounds ($datarow >= $this->records_per_group)"); - return FALSE; - } - - if ($this->data_type == 'text-data') { - // Ok. No need to set the offset to skip more records. - } elseif ($this->data_type == 'data-data') { - $off++; // first Y value at $data[][2] - } else { - $this->DrawError('DoMovingAverage(): wrong data type!!'); - return FALSE; - } - - // Set color: - if ($color) { - array_push($this->ndx_data_colors, $this->SetIndexDarkColor($color)); - } else { - array_push($this->ndx_data_colors, $this->SetIndexDarkColor($this->data_colors[$datarow])); - } - // Set line width: - if ($width) { - array_push($this->line_widths, $width); - } else { - array_push($this->line_widths, $this->line_widths[$datarow] * 2); - } - // Show in legend? - if ($show) { - $this->legend[$this->records_per_group-1] = "(MA[$datarow]:$interval)"; - } - - $datarow += $off; - for ($i = 0; $i < $this->num_data_rows; $i++) { - $storage[$i % $interval] = @ $this->data[$i][$datarow]; - $ma = array_sum($storage); - $ma /= count($storage); - array_push($this->data[$i], $ma); // Push the data onto the array - $this->num_recs[$i]++; // Tell the drawing functions it is there - } - $this->records_per_group++; -// $this->FindDataLimits(); - return TRUE; - } //function DoMovingAverage() - - - /** - * Computes an exponentially smoothed moving average. - * @param int perc "smoothing percentage" - * FIXME!!! I haven't checked this. - */ - function DoExponentialMovingAverage($datarow, $perc, $show_in_legend) - { - if ($this->data_type == 'text-data') { - $datarow++; - } elseif ($this->data_type != 'data-data') { - $this->DrawError('DoWeightedMovingAverage(): wrong data type!!'); - return FALSE; - } - - if ($show_in_legend) { - $this->legend[$datarow] .= " (MA: $interval)"; - } - - $storage[0] = $this->data[0][$datarow]; - for ($i=1;$i < $this->num_data_rows; $i++) { - $storage[$i] = @ $storage[$i-1] + $perc * ($this->data[$i][$datarow] - $storage[$i-1]); - $ma = array_sum($storage); - $ma /= count($storage); - $this->data[$i][$datarow] = $ma; - } - return TRUE; - } // function DoExponentialMovingAverage() - - - /*! - * Removes the DataSet of number $index - */ - function DoRemoveDataSet($index) - { - $offset = 1; - if ($this->data_type == 'data-data') { - $offset++; - } elseif ($this->data_type != 'text-data') { - $this->DrawError('wrong data type!!'); - return FALSE; - } - - $index += $offset; - foreach ($this->data as $key=>$val) { - foreach ($val as $key2=>$val2) { - if ($key2 >= $index) { - if (isset($this->data[$key][$key2+1])) { - $this->data[$key][$key2] = $this->data[$key][$key2+1]; - } else { - unset($this->data[$key][$key2]); - } - } - } - } - } // function DoRemoveDataSet - - - /*! - * Computes row x divided by row y, stores the result in row x - * and deletes row y - */ - function DoDivision($x,$y) - { - $offset = 1; - if ($this->data_type == 'data-data') { - $offset++; - } elseif ($this->data_type != 'text-data') { - $this->DrawError('wrong data type!!'); - return FALSE; - } - - $x += $offset; $y += $offset; - reset($this->data); - while (list($key, $val) = each($this->data)) { - if ($this->data[$key][$y] == 0) { - $this->data[$key][$x] = 0; - } else { - $this->data[$key][$x] /= $this->data[$key][$y]; - } - } - - $this->DoRemoveDataSet($y-$offset); - } // function DoDivision - -} // class PHPlot_Data extends PHPlot diff --git a/gosa-core/include/phplot-5.1.2/rgb.inc.php b/gosa-core/include/phplot-5.1.2/rgb.inc.php deleted file mode 100644 index 41256ee25..000000000 --- a/gosa-core/include/phplot-5.1.2/rgb.inc.php +++ /dev/null @@ -1,752 +0,0 @@ -SetRGBArray('large') - * For more information on PHPlot see http://sourceforge.net/projects/phplot/ - * - * rgb.inc.php comes with PHPlot but is derived from the X11 rgb.txt color - * database file, which contains no specific copyright notice. It may be - * covered by X.Org, XFree86, or MIT/X11 copyright and license, all of which - * allow redistribution on terms which are less strict than the LGPL which - * covers PHPlot. - */ -$ColorArray = array( - "snow" => array(255, 250, 250), - "ghost white" => array(248, 248, 255), - "GhostWhite" => array(248, 248, 255), - "white smoke" => array(245, 245, 245), - "WhiteSmoke" => array(245, 245, 245), - "gainsboro" => array(220, 220, 220), - "floral white" => array(255, 250, 240), - "FloralWhite" => array(255, 250, 240), - "old lace" => array(253, 245, 230), - "OldLace" => array(253, 245, 230), - "linen" => array(250, 240, 230), - "antique white" => array(250, 235, 215), - "AntiqueWhite" => array(250, 235, 215), - "papaya whip" => array(255, 239, 213), - "PapayaWhip" => array(255, 239, 213), - "blanched almond" => array(255, 235, 205), - "BlanchedAlmond" => array(255, 235, 205), - "bisque" => array(255, 228, 196), - "peach puff" => array(255, 218, 185), - "PeachPuff" => array(255, 218, 185), - "navajo white" => array(255, 222, 173), - "NavajoWhite" => array(255, 222, 173), - "moccasin" => array(255, 228, 181), - "cornsilk" => array(255, 248, 220), - "ivory" => array(255, 255, 240), - "lemon chiffon" => array(255, 250, 205), - "LemonChiffon" => array(255, 250, 205), - "seashell" => array(255, 245, 238), - "honeydew" => array(240, 255, 240), - "mint cream" => array(245, 255, 250), - "MintCream" => array(245, 255, 250), - "azure" => array(240, 255, 255), - "alice blue" => array(240, 248, 255), - "AliceBlue" => array(240, 248, 255), - "lavender" => array(230, 230, 250), - "lavender blush" => array(255, 240, 245), - "LavenderBlush" => array(255, 240, 245), - "misty rose" => array(255, 228, 225), - "MistyRose" => array(255, 228, 225), - "white" => array(255, 255, 255), - "black" => array( 0, 0, 0), - "dark slate gray" => array( 47, 79, 79), - "DarkSlateGray" => array( 47, 79, 79), - "dark slate grey" => array( 47, 79, 79), - "DarkSlateGrey" => array( 47, 79, 79), - "dim gray" => array(105, 105, 105), - "DimGray" => array(105, 105, 105), - "dim grey" => array(105, 105, 105), - "DimGrey" => array(105, 105, 105), - "slate gray" => array(112, 128, 144), - "SlateGray" => array(112, 128, 144), - "slate grey" => array(112, 128, 144), - "SlateGrey" => array(112, 128, 144), - "light slate gray" => array(119, 136, 153), - "LightSlateGray" => array(119, 136, 153), - "light slate grey" => array(119, 136, 153), - "LightSlateGrey" => array(119, 136, 153), - "gray" => array(190, 190, 190), - "grey" => array(190, 190, 190), - "light grey" => array(211, 211, 211), - "LightGrey" => array(211, 211, 211), - "light gray" => array(211, 211, 211), - "LightGray" => array(211, 211, 211), - "midnight blue" => array( 25, 25, 112), - "MidnightBlue" => array( 25, 25, 112), - "navy" => array( 0, 0, 128), - "navy blue" => array( 0, 0, 128), - "NavyBlue" => array( 0, 0, 128), - "cornflower blue" => array(100, 149, 237), - "CornflowerBlue" => array(100, 149, 237), - "dark slate blue" => array( 72, 61, 139), - "DarkSlateBlue" => array( 72, 61, 139), - "slate blue" => array(106, 90, 205), - "SlateBlue" => array(106, 90, 205), - "medium slate blue" => array(123, 104, 238), - "MediumSlateBlue" => array(123, 104, 238), - "light slate blue" => array(132, 112, 255), - "LightSlateBlue" => array(132, 112, 255), - "medium blue" => array( 0, 0, 205), - "MediumBlue" => array( 0, 0, 205), - "royal blue" => array( 65, 105, 225), - "RoyalBlue" => array( 65, 105, 225), - "blue" => array( 0, 0, 255), - "dodger blue" => array( 30, 144, 255), - "DodgerBlue" => array( 30, 144, 255), - "deep sky blue" => array( 0, 191, 255), - "DeepSkyBlue" => array( 0, 191, 255), - "sky blue" => array(135, 206, 235), - "SkyBlue" => array(135, 206, 235), - "light sky blue" => array(135, 206, 250), - "LightSkyBlue" => array(135, 206, 250), - "steel blue" => array( 70, 130, 180), - "SteelBlue" => array( 70, 130, 180), - "light steel blue" => array(176, 196, 222), - "LightSteelBlue" => array(176, 196, 222), - "light blue" => array(173, 216, 230), - "LightBlue" => array(173, 216, 230), - "powder blue" => array(176, 224, 230), - "PowderBlue" => array(176, 224, 230), - "pale turquoise" => array(175, 238, 238), - "PaleTurquoise" => array(175, 238, 238), - "dark turquoise" => array( 0, 206, 209), - "DarkTurquoise" => array( 0, 206, 209), - "medium turquoise" => array( 72, 209, 204), - "MediumTurquoise" => array( 72, 209, 204), - "turquoise" => array( 64, 224, 208), - "cyan" => array( 0, 255, 255), - "light cyan" => array(224, 255, 255), - "LightCyan" => array(224, 255, 255), - "cadet blue" => array( 95, 158, 160), - "CadetBlue" => array( 95, 158, 160), - "medium aquamarine" => array(102, 205, 170), - "MediumAquamarine" => array(102, 205, 170), - "aquamarine" => array(127, 255, 212), - "dark green" => array( 0, 100, 0), - "DarkGreen" => array( 0, 100, 0), - "dark olive green" => array( 85, 107, 47), - "DarkOliveGreen" => array( 85, 107, 47), - "dark sea green" => array(143, 188, 143), - "DarkSeaGreen" => array(143, 188, 143), - "sea green" => array( 46, 139, 87), - "SeaGreen" => array( 46, 139, 87), - "medium sea green" => array( 60, 179, 113), - "MediumSeaGreen" => array( 60, 179, 113), - "light sea green" => array( 32, 178, 170), - "LightSeaGreen" => array( 32, 178, 170), - "pale green" => array(152, 251, 152), - "PaleGreen" => array(152, 251, 152), - "spring green" => array( 0, 255, 127), - "SpringGreen" => array( 0, 255, 127), - "lawn green" => array(124, 252, 0), - "LawnGreen" => array(124, 252, 0), - "green" => array( 0, 255, 0), - "chartreuse" => array(127, 255, 0), - "medium spring green" => array( 0, 250, 154), - "MediumSpringGreen" => array( 0, 250, 154), - "green yellow" => array(173, 255, 47), - "GreenYellow" => array(173, 255, 47), - "lime green" => array( 50, 205, 50), - "LimeGreen" => array( 50, 205, 50), - "yellow green" => array(154, 205, 50), - "YellowGreen" => array(154, 205, 50), - "forest green" => array( 34, 139, 34), - "ForestGreen" => array( 34, 139, 34), - "olive drab" => array(107, 142, 35), - "OliveDrab" => array(107, 142, 35), - "dark khaki" => array(189, 183, 107), - "DarkKhaki" => array(189, 183, 107), - "khaki" => array(240, 230, 140), - "pale goldenrod" => array(238, 232, 170), - "PaleGoldenrod" => array(238, 232, 170), - "light goldenrod yellow" => array(250, 250, 210), - "LightGoldenrodYellow" => array(250, 250, 210), - "light yellow" => array(255, 255, 224), - "LightYellow" => array(255, 255, 224), - "yellow" => array(255, 255, 0), - "gold" => array(255, 215, 0), - "light goldenrod" => array(238, 221, 130), - "LightGoldenrod" => array(238, 221, 130), - "goldenrod" => array(218, 165, 32), - "dark goldenrod" => array(184, 134, 11), - "DarkGoldenrod" => array(184, 134, 11), - "rosy brown" => array(188, 143, 143), - "RosyBrown" => array(188, 143, 143), - "indian red" => array(205, 92, 92), - "IndianRed" => array(205, 92, 92), - "saddle brown" => array(139, 69, 19), - "SaddleBrown" => array(139, 69, 19), - "sienna" => array(160, 82, 45), - "peru" => array(205, 133, 63), - "burlywood" => array(222, 184, 135), - "beige" => array(245, 245, 220), - "wheat" => array(245, 222, 179), - "sandy brown" => array(244, 164, 96), - "SandyBrown" => array(244, 164, 96), - "tan" => array(210, 180, 140), - "chocolate" => array(210, 105, 30), - "firebrick" => array(178, 34, 34), - "brown" => array(165, 42, 42), - "dark salmon" => array(233, 150, 122), - "DarkSalmon" => array(233, 150, 122), - "salmon" => array(250, 128, 114), - "light salmon" => array(255, 160, 122), - "LightSalmon" => array(255, 160, 122), - "orange" => array(255, 165, 0), - "dark orange" => array(255, 140, 0), - "DarkOrange" => array(255, 140, 0), - "coral" => array(255, 127, 80), - "light coral" => array(240, 128, 128), - "LightCoral" => array(240, 128, 128), - "tomato" => array(255, 99, 71), - "orange red" => array(255, 69, 0), - "OrangeRed" => array(255, 69, 0), - "red" => array(255, 0, 0), - "hot pink" => array(255, 105, 180), - "HotPink" => array(255, 105, 180), - "deep pink" => array(255, 20, 147), - "DeepPink" => array(255, 20, 147), - "pink" => array(255, 192, 203), - "light pink" => array(255, 182, 193), - "LightPink" => array(255, 182, 193), - "pale violet red" => array(219, 112, 147), - "PaleVioletRed" => array(219, 112, 147), - "maroon" => array(176, 48, 96), - "medium violet red" => array(199, 21, 133), - "MediumVioletRed" => array(199, 21, 133), - "violet red" => array(208, 32, 144), - "VioletRed" => array(208, 32, 144), - "magenta" => array(255, 0, 255), - "violet" => array(238, 130, 238), - "plum" => array(221, 160, 221), - "orchid" => array(218, 112, 214), - "medium orchid" => array(186, 85, 211), - "MediumOrchid" => array(186, 85, 211), - "dark orchid" => array(153, 50, 204), - "DarkOrchid" => array(153, 50, 204), - "dark violet" => array(148, 0, 211), - "DarkViolet" => array(148, 0, 211), - "blue violet" => array(138, 43, 226), - "BlueViolet" => array(138, 43, 226), - "purple" => array(160, 32, 240), - "medium purple" => array(147, 112, 219), - "MediumPurple" => array(147, 112, 219), - "thistle" => array(216, 191, 216), - "snow1" => array(255, 250, 250), - "snow2" => array(238, 233, 233), - "snow3" => array(205, 201, 201), - "snow4" => array(139, 137, 137), - "seashell1" => array(255, 245, 238), - "seashell2" => array(238, 229, 222), - "seashell3" => array(205, 197, 191), - "seashell4" => array(139, 134, 130), - "AntiqueWhite1" => array(255, 239, 219), - "AntiqueWhite2" => array(238, 223, 204), - "AntiqueWhite3" => array(205, 192, 176), - "AntiqueWhite4" => array(139, 131, 120), - "bisque1" => array(255, 228, 196), - "bisque2" => array(238, 213, 183), - "bisque3" => array(205, 183, 158), - "bisque4" => array(139, 125, 107), - "PeachPuff1" => array(255, 218, 185), - "PeachPuff2" => array(238, 203, 173), - "PeachPuff3" => array(205, 175, 149), - "PeachPuff4" => array(139, 119, 101), - "NavajoWhite1" => array(255, 222, 173), - "NavajoWhite2" => array(238, 207, 161), - "NavajoWhite3" => array(205, 179, 139), - "NavajoWhite4" => array(139, 121, 94), - "LemonChiffon1" => array(255, 250, 205), - "LemonChiffon2" => array(238, 233, 191), - "LemonChiffon3" => array(205, 201, 165), - "LemonChiffon4" => array(139, 137, 112), - "cornsilk1" => array(255, 248, 220), - "cornsilk2" => array(238, 232, 205), - "cornsilk3" => array(205, 200, 177), - "cornsilk4" => array(139, 136, 120), - "ivory1" => array(255, 255, 240), - "ivory2" => array(238, 238, 224), - "ivory3" => array(205, 205, 193), - "ivory4" => array(139, 139, 131), - "honeydew1" => array(240, 255, 240), - "honeydew2" => array(224, 238, 224), - "honeydew3" => array(193, 205, 193), - "honeydew4" => array(131, 139, 131), - "LavenderBlush1" => array(255, 240, 245), - "LavenderBlush2" => array(238, 224, 229), - "LavenderBlush3" => array(205, 193, 197), - "LavenderBlush4" => array(139, 131, 134), - "MistyRose1" => array(255, 228, 225), - "MistyRose2" => array(238, 213, 210), - "MistyRose3" => array(205, 183, 181), - "MistyRose4" => array(139, 125, 123), - "azure1" => array(240, 255, 255), - "azure2" => array(224, 238, 238), - "azure3" => array(193, 205, 205), - "azure4" => array(131, 139, 139), - "SlateBlue1" => array(131, 111, 255), - "SlateBlue2" => array(122, 103, 238), - "SlateBlue3" => array(105, 89, 205), - "SlateBlue4" => array( 71, 60, 139), - "RoyalBlue1" => array( 72, 118, 255), - "RoyalBlue2" => array( 67, 110, 238), - "RoyalBlue3" => array( 58, 95, 205), - "RoyalBlue4" => array( 39, 64, 139), - "blue1" => array( 0, 0, 255), - "blue2" => array( 0, 0, 238), - "blue3" => array( 0, 0, 205), - "blue4" => array( 0, 0, 139), - "DodgerBlue1" => array( 30, 144, 255), - "DodgerBlue2" => array( 28, 134, 238), - "DodgerBlue3" => array( 24, 116, 205), - "DodgerBlue4" => array( 16, 78, 139), - "SteelBlue1" => array( 99, 184, 255), - "SteelBlue2" => array( 92, 172, 238), - "SteelBlue3" => array( 79, 148, 205), - "SteelBlue4" => array( 54, 100, 139), - "DeepSkyBlue1" => array( 0, 191, 255), - "DeepSkyBlue2" => array( 0, 178, 238), - "DeepSkyBlue3" => array( 0, 154, 205), - "DeepSkyBlue4" => array( 0, 104, 139), - "SkyBlue1" => array(135, 206, 255), - "SkyBlue2" => array(126, 192, 238), - "SkyBlue3" => array(108, 166, 205), - "SkyBlue4" => array( 74, 112, 139), - "LightSkyBlue1" => array(176, 226, 255), - "LightSkyBlue2" => array(164, 211, 238), - "LightSkyBlue3" => array(141, 182, 205), - "LightSkyBlue4" => array( 96, 123, 139), - "SlateGray1" => array(198, 226, 255), - "SlateGray2" => array(185, 211, 238), - "SlateGray3" => array(159, 182, 205), - "SlateGray4" => array(108, 123, 139), - "LightSteelBlue1" => array(202, 225, 255), - "LightSteelBlue2" => array(188, 210, 238), - "LightSteelBlue3" => array(162, 181, 205), - "LightSteelBlue4" => array(110, 123, 139), - "LightBlue1" => array(191, 239, 255), - "LightBlue2" => array(178, 223, 238), - "LightBlue3" => array(154, 192, 205), - "LightBlue4" => array(104, 131, 139), - "LightCyan1" => array(224, 255, 255), - "LightCyan2" => array(209, 238, 238), - "LightCyan3" => array(180, 205, 205), - "LightCyan4" => array(122, 139, 139), - "PaleTurquoise1" => array(187, 255, 255), - "PaleTurquoise2" => array(174, 238, 238), - "PaleTurquoise3" => array(150, 205, 205), - "PaleTurquoise4" => array(102, 139, 139), - "CadetBlue1" => array(152, 245, 255), - "CadetBlue2" => array(142, 229, 238), - "CadetBlue3" => array(122, 197, 205), - "CadetBlue4" => array( 83, 134, 139), - "turquoise1" => array( 0, 245, 255), - "turquoise2" => array( 0, 229, 238), - "turquoise3" => array( 0, 197, 205), - "turquoise4" => array( 0, 134, 139), - "cyan1" => array( 0, 255, 255), - "cyan2" => array( 0, 238, 238), - "cyan3" => array( 0, 205, 205), - "cyan4" => array( 0, 139, 139), - "DarkSlateGray1" => array(151, 255, 255), - "DarkSlateGray2" => array(141, 238, 238), - "DarkSlateGray3" => array(121, 205, 205), - "DarkSlateGray4" => array( 82, 139, 139), - "aquamarine1" => array(127, 255, 212), - "aquamarine2" => array(118, 238, 198), - "aquamarine3" => array(102, 205, 170), - "aquamarine4" => array( 69, 139, 116), - "DarkSeaGreen1" => array(193, 255, 193), - "DarkSeaGreen2" => array(180, 238, 180), - "DarkSeaGreen3" => array(155, 205, 155), - "DarkSeaGreen4" => array(105, 139, 105), - "SeaGreen1" => array( 84, 255, 159), - "SeaGreen2" => array( 78, 238, 148), - "SeaGreen3" => array( 67, 205, 128), - "SeaGreen4" => array( 46, 139, 87), - "PaleGreen1" => array(154, 255, 154), - "PaleGreen2" => array(144, 238, 144), - "PaleGreen3" => array(124, 205, 124), - "PaleGreen4" => array( 84, 139, 84), - "SpringGreen1" => array( 0, 255, 127), - "SpringGreen2" => array( 0, 238, 118), - "SpringGreen3" => array( 0, 205, 102), - "SpringGreen4" => array( 0, 139, 69), - "green1" => array( 0, 255, 0), - "green2" => array( 0, 238, 0), - "green3" => array( 0, 205, 0), - "green4" => array( 0, 139, 0), - "chartreuse1" => array(127, 255, 0), - "chartreuse2" => array(118, 238, 0), - "chartreuse3" => array(102, 205, 0), - "chartreuse4" => array( 69, 139, 0), - "OliveDrab1" => array(192, 255, 62), - "OliveDrab2" => array(179, 238, 58), - "OliveDrab3" => array(154, 205, 50), - "OliveDrab4" => array(105, 139, 34), - "DarkOliveGreen1" => array(202, 255, 112), - "DarkOliveGreen2" => array(188, 238, 104), - "DarkOliveGreen3" => array(162, 205, 90), - "DarkOliveGreen4" => array(110, 139, 61), - "khaki1" => array(255, 246, 143), - "khaki2" => array(238, 230, 133), - "khaki3" => array(205, 198, 115), - "khaki4" => array(139, 134, 78), - "LightGoldenrod1" => array(255, 236, 139), - "LightGoldenrod2" => array(238, 220, 130), - "LightGoldenrod3" => array(205, 190, 112), - "LightGoldenrod4" => array(139, 129, 76), - "LightYellow1" => array(255, 255, 224), - "LightYellow2" => array(238, 238, 209), - "LightYellow3" => array(205, 205, 180), - "LightYellow4" => array(139, 139, 122), - "yellow1" => array(255, 255, 0), - "yellow2" => array(238, 238, 0), - "yellow3" => array(205, 205, 0), - "yellow4" => array(139, 139, 0), - "gold1" => array(255, 215, 0), - "gold2" => array(238, 201, 0), - "gold3" => array(205, 173, 0), - "gold4" => array(139, 117, 0), - "goldenrod1" => array(255, 193, 37), - "goldenrod2" => array(238, 180, 34), - "goldenrod3" => array(205, 155, 29), - "goldenrod4" => array(139, 105, 20), - "DarkGoldenrod1" => array(255, 185, 15), - "DarkGoldenrod2" => array(238, 173, 14), - "DarkGoldenrod3" => array(205, 149, 12), - "DarkGoldenrod4" => array(139, 101, 8), - "RosyBrown1" => array(255, 193, 193), - "RosyBrown2" => array(238, 180, 180), - "RosyBrown3" => array(205, 155, 155), - "RosyBrown4" => array(139, 105, 105), - "IndianRed1" => array(255, 106, 106), - "IndianRed2" => array(238, 99, 99), - "IndianRed3" => array(205, 85, 85), - "IndianRed4" => array(139, 58, 58), - "sienna1" => array(255, 130, 71), - "sienna2" => array(238, 121, 66), - "sienna3" => array(205, 104, 57), - "sienna4" => array(139, 71, 38), - "burlywood1" => array(255, 211, 155), - "burlywood2" => array(238, 197, 145), - "burlywood3" => array(205, 170, 125), - "burlywood4" => array(139, 115, 85), - "wheat1" => array(255, 231, 186), - "wheat2" => array(238, 216, 174), - "wheat3" => array(205, 186, 150), - "wheat4" => array(139, 126, 102), - "tan1" => array(255, 165, 79), - "tan2" => array(238, 154, 73), - "tan3" => array(205, 133, 63), - "tan4" => array(139, 90, 43), - "chocolate1" => array(255, 127, 36), - "chocolate2" => array(238, 118, 33), - "chocolate3" => array(205, 102, 29), - "chocolate4" => array(139, 69, 19), - "firebrick1" => array(255, 48, 48), - "firebrick2" => array(238, 44, 44), - "firebrick3" => array(205, 38, 38), - "firebrick4" => array(139, 26, 26), - "brown1" => array(255, 64, 64), - "brown2" => array(238, 59, 59), - "brown3" => array(205, 51, 51), - "brown4" => array(139, 35, 35), - "salmon1" => array(255, 140, 105), - "salmon2" => array(238, 130, 98), - "salmon3" => array(205, 112, 84), - "salmon4" => array(139, 76, 57), - "LightSalmon1" => array(255, 160, 122), - "LightSalmon2" => array(238, 149, 114), - "LightSalmon3" => array(205, 129, 98), - "LightSalmon4" => array(139, 87, 66), - "orange1" => array(255, 165, 0), - "orange2" => array(238, 154, 0), - "orange3" => array(205, 133, 0), - "orange4" => array(139, 90, 0), - "DarkOrange1" => array(255, 127, 0), - "DarkOrange2" => array(238, 118, 0), - "DarkOrange3" => array(205, 102, 0), - "DarkOrange4" => array(139, 69, 0), - "coral1" => array(255, 114, 86), - "coral2" => array(238, 106, 80), - "coral3" => array(205, 91, 69), - "coral4" => array(139, 62, 47), - "tomato1" => array(255, 99, 71), - "tomato2" => array(238, 92, 66), - "tomato3" => array(205, 79, 57), - "tomato4" => array(139, 54, 38), - "OrangeRed1" => array(255, 69, 0), - "OrangeRed2" => array(238, 64, 0), - "OrangeRed3" => array(205, 55, 0), - "OrangeRed4" => array(139, 37, 0), - "red1" => array(255, 0, 0), - "red2" => array(238, 0, 0), - "red3" => array(205, 0, 0), - "red4" => array(139, 0, 0), - "DeepPink1" => array(255, 20, 147), - "DeepPink2" => array(238, 18, 137), - "DeepPink3" => array(205, 16, 118), - "DeepPink4" => array(139, 10, 80), - "HotPink1" => array(255, 110, 180), - "HotPink2" => array(238, 106, 167), - "HotPink3" => array(205, 96, 144), - "HotPink4" => array(139, 58, 98), - "pink1" => array(255, 181, 197), - "pink2" => array(238, 169, 184), - "pink3" => array(205, 145, 158), - "pink4" => array(139, 99, 108), - "LightPink1" => array(255, 174, 185), - "LightPink2" => array(238, 162, 173), - "LightPink3" => array(205, 140, 149), - "LightPink4" => array(139, 95, 101), - "PaleVioletRed1" => array(255, 130, 171), - "PaleVioletRed2" => array(238, 121, 159), - "PaleVioletRed3" => array(205, 104, 137), - "PaleVioletRed4" => array(139, 71, 93), - "maroon1" => array(255, 52, 179), - "maroon2" => array(238, 48, 167), - "maroon3" => array(205, 41, 144), - "maroon4" => array(139, 28, 98), - "VioletRed1" => array(255, 62, 150), - "VioletRed2" => array(238, 58, 140), - "VioletRed3" => array(205, 50, 120), - "VioletRed4" => array(139, 34, 82), - "magenta1" => array(255, 0, 255), - "magenta2" => array(238, 0, 238), - "magenta3" => array(205, 0, 205), - "magenta4" => array(139, 0, 139), - "orchid1" => array(255, 131, 250), - "orchid2" => array(238, 122, 233), - "orchid3" => array(205, 105, 201), - "orchid4" => array(139, 71, 137), - "plum1" => array(255, 187, 255), - "plum2" => array(238, 174, 238), - "plum3" => array(205, 150, 205), - "plum4" => array(139, 102, 139), - "MediumOrchid1" => array(224, 102, 255), - "MediumOrchid2" => array(209, 95, 238), - "MediumOrchid3" => array(180, 82, 205), - "MediumOrchid4" => array(122, 55, 139), - "DarkOrchid1" => array(191, 62, 255), - "DarkOrchid2" => array(178, 58, 238), - "DarkOrchid3" => array(154, 50, 205), - "DarkOrchid4" => array(104, 34, 139), - "purple1" => array(155, 48, 255), - "purple2" => array(145, 44, 238), - "purple3" => array(125, 38, 205), - "purple4" => array( 85, 26, 139), - "MediumPurple1" => array(171, 130, 255), - "MediumPurple2" => array(159, 121, 238), - "MediumPurple3" => array(137, 104, 205), - "MediumPurple4" => array( 93, 71, 139), - "thistle1" => array(255, 225, 255), - "thistle2" => array(238, 210, 238), - "thistle3" => array(205, 181, 205), - "thistle4" => array(139, 123, 139), - "gray0" => array( 0, 0, 0), - "grey0" => array( 0, 0, 0), - "gray1" => array( 3, 3, 3), - "grey1" => array( 3, 3, 3), - "gray2" => array( 5, 5, 5), - "grey2" => array( 5, 5, 5), - "gray3" => array( 8, 8, 8), - "grey3" => array( 8, 8, 8), - "gray4" => array( 10, 10, 10), - "grey4" => array( 10, 10, 10), - "gray5" => array( 13, 13, 13), - "grey5" => array( 13, 13, 13), - "gray6" => array( 15, 15, 15), - "grey6" => array( 15, 15, 15), - "gray7" => array( 18, 18, 18), - "grey7" => array( 18, 18, 18), - "gray8" => array( 20, 20, 20), - "grey8" => array( 20, 20, 20), - "gray9" => array( 23, 23, 23), - "grey9" => array( 23, 23, 23), - "gray10" => array( 26, 26, 26), - "grey10" => array( 26, 26, 26), - "gray11" => array( 28, 28, 28), - "grey11" => array( 28, 28, 28), - "gray12" => array( 31, 31, 31), - "grey12" => array( 31, 31, 31), - "gray13" => array( 33, 33, 33), - "grey13" => array( 33, 33, 33), - "gray14" => array( 36, 36, 36), - "grey14" => array( 36, 36, 36), - "gray15" => array( 38, 38, 38), - "grey15" => array( 38, 38, 38), - "gray16" => array( 41, 41, 41), - "grey16" => array( 41, 41, 41), - "gray17" => array( 43, 43, 43), - "grey17" => array( 43, 43, 43), - "gray18" => array( 46, 46, 46), - "grey18" => array( 46, 46, 46), - "gray19" => array( 48, 48, 48), - "grey19" => array( 48, 48, 48), - "gray20" => array( 51, 51, 51), - "grey20" => array( 51, 51, 51), - "gray21" => array( 54, 54, 54), - "grey21" => array( 54, 54, 54), - "gray22" => array( 56, 56, 56), - "grey22" => array( 56, 56, 56), - "gray23" => array( 59, 59, 59), - "grey23" => array( 59, 59, 59), - "gray24" => array( 61, 61, 61), - "grey24" => array( 61, 61, 61), - "gray25" => array( 64, 64, 64), - "grey25" => array( 64, 64, 64), - "gray26" => array( 66, 66, 66), - "grey26" => array( 66, 66, 66), - "gray27" => array( 69, 69, 69), - "grey27" => array( 69, 69, 69), - "gray28" => array( 71, 71, 71), - "grey28" => array( 71, 71, 71), - "gray29" => array( 74, 74, 74), - "grey29" => array( 74, 74, 74), - "gray30" => array( 77, 77, 77), - "grey30" => array( 77, 77, 77), - "gray31" => array( 79, 79, 79), - "grey31" => array( 79, 79, 79), - "gray32" => array( 82, 82, 82), - "grey32" => array( 82, 82, 82), - "gray33" => array( 84, 84, 84), - "grey33" => array( 84, 84, 84), - "gray34" => array( 87, 87, 87), - "grey34" => array( 87, 87, 87), - "gray35" => array( 89, 89, 89), - "grey35" => array( 89, 89, 89), - "gray36" => array( 92, 92, 92), - "grey36" => array( 92, 92, 92), - "gray37" => array( 94, 94, 94), - "grey37" => array( 94, 94, 94), - "gray38" => array( 97, 97, 97), - "grey38" => array( 97, 97, 97), - "gray39" => array( 99, 99, 99), - "grey39" => array( 99, 99, 99), - "gray40" => array(102, 102, 102), - "grey40" => array(102, 102, 102), - "gray41" => array(105, 105, 105), - "grey41" => array(105, 105, 105), - "gray42" => array(107, 107, 107), - "grey42" => array(107, 107, 107), - "gray43" => array(110, 110, 110), - "grey43" => array(110, 110, 110), - "gray44" => array(112, 112, 112), - "grey44" => array(112, 112, 112), - "gray45" => array(115, 115, 115), - "grey45" => array(115, 115, 115), - "gray46" => array(117, 117, 117), - "grey46" => array(117, 117, 117), - "gray47" => array(120, 120, 120), - "grey47" => array(120, 120, 120), - "gray48" => array(122, 122, 122), - "grey48" => array(122, 122, 122), - "gray49" => array(125, 125, 125), - "grey49" => array(125, 125, 125), - "gray50" => array(127, 127, 127), - "grey50" => array(127, 127, 127), - "gray51" => array(130, 130, 130), - "grey51" => array(130, 130, 130), - "gray52" => array(133, 133, 133), - "grey52" => array(133, 133, 133), - "gray53" => array(135, 135, 135), - "grey53" => array(135, 135, 135), - "gray54" => array(138, 138, 138), - "grey54" => array(138, 138, 138), - "gray55" => array(140, 140, 140), - "grey55" => array(140, 140, 140), - "gray56" => array(143, 143, 143), - "grey56" => array(143, 143, 143), - "gray57" => array(145, 145, 145), - "grey57" => array(145, 145, 145), - "gray58" => array(148, 148, 148), - "grey58" => array(148, 148, 148), - "gray59" => array(150, 150, 150), - "grey59" => array(150, 150, 150), - "gray60" => array(153, 153, 153), - "grey60" => array(153, 153, 153), - "gray61" => array(156, 156, 156), - "grey61" => array(156, 156, 156), - "gray62" => array(158, 158, 158), - "grey62" => array(158, 158, 158), - "gray63" => array(161, 161, 161), - "grey63" => array(161, 161, 161), - "gray64" => array(163, 163, 163), - "grey64" => array(163, 163, 163), - "gray65" => array(166, 166, 166), - "grey65" => array(166, 166, 166), - "gray66" => array(168, 168, 168), - "grey66" => array(168, 168, 168), - "gray67" => array(171, 171, 171), - "grey67" => array(171, 171, 171), - "gray68" => array(173, 173, 173), - "grey68" => array(173, 173, 173), - "gray69" => array(176, 176, 176), - "grey69" => array(176, 176, 176), - "gray70" => array(179, 179, 179), - "grey70" => array(179, 179, 179), - "gray71" => array(181, 181, 181), - "grey71" => array(181, 181, 181), - "gray72" => array(184, 184, 184), - "grey72" => array(184, 184, 184), - "gray73" => array(186, 186, 186), - "grey73" => array(186, 186, 186), - "gray74" => array(189, 189, 189), - "grey74" => array(189, 189, 189), - "gray75" => array(191, 191, 191), - "grey75" => array(191, 191, 191), - "gray76" => array(194, 194, 194), - "grey76" => array(194, 194, 194), - "gray77" => array(196, 196, 196), - "grey77" => array(196, 196, 196), - "gray78" => array(199, 199, 199), - "grey78" => array(199, 199, 199), - "gray79" => array(201, 201, 201), - "grey79" => array(201, 201, 201), - "gray80" => array(204, 204, 204), - "grey80" => array(204, 204, 204), - "gray81" => array(207, 207, 207), - "grey81" => array(207, 207, 207), - "gray82" => array(209, 209, 209), - "grey82" => array(209, 209, 209), - "gray83" => array(212, 212, 212), - "grey83" => array(212, 212, 212), - "gray84" => array(214, 214, 214), - "grey84" => array(214, 214, 214), - "gray85" => array(217, 217, 217), - "grey85" => array(217, 217, 217), - "gray86" => array(219, 219, 219), - "grey86" => array(219, 219, 219), - "gray87" => array(222, 222, 222), - "grey87" => array(222, 222, 222), - "gray88" => array(224, 224, 224), - "grey88" => array(224, 224, 224), - "gray89" => array(227, 227, 227), - "grey89" => array(227, 227, 227), - "gray90" => array(229, 229, 229), - "grey90" => array(229, 229, 229), - "gray91" => array(232, 232, 232), - "grey91" => array(232, 232, 232), - "gray92" => array(235, 235, 235), - "grey92" => array(235, 235, 235), - "gray93" => array(237, 237, 237), - "grey93" => array(237, 237, 237), - "gray94" => array(240, 240, 240), - "grey94" => array(240, 240, 240), - "gray95" => array(242, 242, 242), - "grey95" => array(242, 242, 242), - "gray96" => array(245, 245, 245), - "grey96" => array(245, 245, 245), - "gray97" => array(247, 247, 247), - "grey97" => array(247, 247, 247), - "gray98" => array(250, 250, 250), - "grey98" => array(250, 250, 250), - "gray99" => array(252, 252, 252), - "grey99" => array(252, 252, 252), - "gray100" => array(255, 255, 255) -); -- 2.30.2